एक Android ऐप किसी आंतरिक नाम को resolve नहीं कर पाता, जबकि VPN क्लाइंट का अपना ब्राउज़र उस तक पहुँच जाता है, और वही बिल्ड किसी दूसरे फ़ोन पर काम करती है। URL चर नहीं है। चर यह है कि ऐप की प्रोसेस को resolution के लिए कौन-सा नेटवर्क इस्तेमाल करने की अनुमति है, और Android यह गारंटी नहीं देता कि सक्रिय VPN वही है जिसे आपके sockets इस्तेमाल करते हैं। इन जाँचों को क्रम से करें और तब रुकें जब resolver का स्नैपशॉट आपकी धारणा से मेल न खाए।

चरण 1: साबित करें कि ऐप किस नेटवर्क पर है

स्टेटस बार के बजाय ऐप का अपना दृश्य पढ़ें। ConnectivityManager से सक्रिय नेटवर्क, उसका LinkProperties, DNS सर्वर की सूची और निजी DNS सेटिंग लें। अगर सूची में VPN का resolver है, तो ऐप के पास उस तक रास्ता है; अगर उसमें Wi-Fi का resolver है, तो टनल उस प्रोसेस के लिए डिफ़ॉल्ट नेटवर्क नहीं है।

VPN आइकन केवल यह बताता है कि एक टनल मौजूद है। यह नहीं बताता कि ऐप की प्रोसेस उससे बाइंड हुई थी, और Android हमेशा नाम resolution को उस नेटवर्क से नहीं भेजता जो सक्रिय दिखता है। दूसरे डिवाइस पर forward करने वाले लोकल VPN ऐप, बिना इंटरनेट वाले Wi-Fi नेटवर्क और विक्रेता के बिल्ड सभी ऐप को टनल के सर्वर की जगह डिफ़ॉल्ट resolver से पूछते छोड़ सकते हैं।

चरण 2: VPN ट्रांसपोर्ट माँगें और प्रोसेस बाइंड करें

जब ऐप को टनल का resolver ही इस्तेमाल करना हो, तो VPN ट्रांसपोर्ट वाला नेटवर्क माँगें और callback में प्रोसेस बाइंड करें, ताकि कोड अंदाज़ा न लगाए कि नेटवर्क कब आएगा:

val request = NetworkRequest.Builder()
    .addTransportType(NetworkCapabilities.TRANSPORT_VPN)
    .build()

connectivityManager.requestNetwork(request, object : NetworkCallback() {
    override fun onAvailable(network: Network) {
        val bound = connectivityManager.bindProcessToNetwork(network)
        Log.i(TAG, "bound to VPN network: " + bound)
    }
})

यह कॉल पूरी प्रोसेस का डिफ़ॉल्ट नेटवर्क बदल देती है, इसलिए उसके बाद बनने वाला हर socket उसी का उपयोग करता है। पहले से मौजूद sockets वही नेटवर्क बनाए रखते हैं जिस पर वे बने थे, इसीलिए बाइंड से पहले खुला connection pool पुराने रास्ते से resolve करता रह सकता है। लौटाया गया मान boolean है, और false परिणाम का अर्थ है कि बाइंड नहीं हुआ; छोटी देरी के साथ फिर कोशिश करें और दोनों प्रयास लॉग करें।

चरण 3: बाइंड को उतने ही दायरे में रखें जितना ज़रूरी है

पूरी प्रोसेस का बाइंडिंग कठोर है। Telemetry, अपडेट जाँच और तीसरे पक्ष के SDK भी टनल पर चले जाते हैं, और अगर टनल में इंटरनेट नहीं है तो वे विफल होने लगते हैं। एक ही अनुरोध के लिए नेटवर्क की socket factory इस्तेमाल करें और बाकी सब कुछ डिवाइस के डिफ़ॉल्ट पर रखें। जानबूझकर एक मॉडल चुनें: प्रति कनेक्शन संकीर्ण बाइंड, या प्रोसेस बाइंड जिसमें VPN गायब होने पर स्पष्ट unbind हो।

resolver की दो सुविधाएँ बिना किसी त्रुटि के बाइंड को हरा सकती हैं। कड़े मोड में निजी DNS क्वेरी को नेटवर्क resolver की जगह नाम वाले DoT सर्वर पर भेजता है, और अपना DNS-over-HTTPS क्लाइंट लेकर आने वाला ऐप सिस्टम resolver को पूरी तरह बायपास कर देता है। यह निष्कर्ष निकालने से पहले कि बाइंड विफल हुआ, दोनों जाँचें। जो क्वेरी कभी VPN के DNS सर्वर तक नहीं पहुँचती, वह टनल की ओर के किसी लॉग में नहीं दिखेगी।

चरण 4: CONNECTED बाधा पर भरोसा न करें

WorkManager में NetworkType.CONNECTED का अर्थ है कि कोई नेटवर्क जुड़ा है, और VPN ट्रांसपोर्ट उसे तब भी संतुष्ट करता है जब नीचे की Wi-Fi या सेल्युलर लिंक चली गई हो। जॉब चलता है, हर अनुरोध विफल होता है, और retry नीति उसे ऐसे तूफ़ान में बदल देती है जो शेड्यूलिंग बग जैसा दिखता है। टनल एक नेटवर्क है; यह बाधा कभी इंटरनेट जाँच नहीं थी।

वह क्षमता जाँचें जो काम को वास्तव में चाहिए, जैसे सत्यापित इंटरनेट पहुँच, और backoff के साथ सीमित retry नीति रखें। अगर जॉब को निजी नाम चाहिए, तो काम करने से पहले उस नाम को चुने गए नेटवर्क में resolve करें, और जो अनुरोध सफल नहीं हो सकता उसे दोहराने के बजाय स्पष्ट त्रुटि के साथ जल्दी विफल हों।

चरण 5: सबूत दर्ज करें और रेंज फिर से जाँचें

चुने गए नेटवर्क के ट्रांसपोर्ट प्रकार, LinkProperties से DNS सर्वर, बाइंड ने true लौटाया या नहीं, और पहले अनुरोध की सटीक विफलता लॉग करें। फिर उसी बाइंडिंग के तहत एक निजी नाम और एक सार्वजनिक नाम चलाएँ। यह जोड़ी दिखाती है कि ऐप ने टनल resolver इस्तेमाल किया या चुपचाप डिवाइस डिफ़ॉल्ट पर लौट गया, और यही वह अंतर है जो उपयोगकर्ता अनुभव करता है।

इसे उस सबसे पुराने Android संस्करण पर दोहराएँ जिसे आप सपोर्ट करते हैं और एक मौजूदा रिलीज़ पर। जो resolver व्यवहार डिफ़ॉल्ट रास्ते को सही दिखाता है, वही वह जगह है जहाँ डिवाइस और संस्करण अलग होते हैं, और जो बिल्ड केवल नए परीक्षण डिवाइस पर पास होती है, वह आपके द्वारा भेजी जाने वाली रेंज के लिए सत्यापित नहीं है। adb shell dumpsys connectivity यह पुष्टि करने का तेज़ तरीका है कि विफलता दोहराते समय डिवाइस कौन-से नेटवर्क और क्षमताएँ बताता है।

संबंधित लेख