آپ اینڈرائیڈ سے یہ نہیں پوچھ سکتے کہ VPN منسلک ہے یا نہیں۔ VpnService کنکشن کی حالت بتانے والا کوئی getter ظاہر نہیں کرتا، اور اسٹیٹس بار میں چابی کا نشان سسٹم بناتا ہے، کوئی ایسی چیز نہیں جو آپ کی ایپ پڑھ سکے۔ آپ جو کر سکتے ہیں وہ یہ ہے کہ کنیکٹیویٹی اسٹیک سے زیادہ تنگ سوال پوچھیں: اس ایپ کا ٹریفک کون سا نیٹ ورک استعمال کر رہا ہے، اور کیا وہ نیٹ ورک VPN ٹرانسپورٹ اٹھائے ہوئے ہے۔ یہ رہنما غلط مثبت نتائج سے بچنے والی ترتیب میں جانچ کرتا ہے، ڈیوائس پر shell کمانڈ سے لے کر ایپ میں چھوڑے گئے callback تک۔

ایپ کا کوڈ چھونے سے پہلے shell سے ڈیوائس کی جانچ کریں

پہلے بنیادی حالت حاصل کریں۔ adb shell dumpsys connectivity ہر وہ نیٹ ورک چھاپتا ہے جو سسٹم جانتا ہے، اور ہر بلاک اپنے ٹرانسپورٹ گنواتا ہے، اس لیے VPN نیٹ ورک اس فہرست میں VPN کے ساتھ نظر آتا ہے۔ سب سے پہلے ڈیفالٹ نیٹ ورک کا بلاک پڑھیں، پھر وہ دوسرے نیٹ ورک تلاش کریں جو وہی ٹرانسپورٹ اٹھاتے ہیں۔

دو آؤٹ پٹ مختلف سوالوں کے جواب دیتے ہیں۔ VPN نیٹ ورک کا موجود ہونا اور آپ کی ایپ کا اسے استعمال کرنا ایک جیسی بات نہیں، اور کام کے پروفائل یا دوسرے صارف والے ڈیوائس پر دونوں بیک وقت درست ہو سکتے ہیں جب آپ کا پروسیس براہ راست انٹرنیٹ سے بات کر رہا ہو۔ آپ کے ساکٹ کیا کرتے ہیں یہ فعال نیٹ ورک کی سطر طے کرتی ہے۔

وہ نیٹ ورک پوچھیں جو ایپ استعمال کر رہی ہے

کوڈ میں صلاحیت کا امتحان چار سطریں ہے۔ مینی فیسٹ میں ACCESS_NETWORK_STATE طلب کریں، پھر فعال نیٹ ورک کی صلاحیتوں کا VPN ٹرانسپورٹ سے موازنہ کریں:

ConnectivityManager cm = (ConnectivityManager)
    context.getSystemService(Context.CONNECTIVITY_SERVICE);
Network active = cm.getActiveNetwork();
NetworkCapabilities caps = cm.getNetworkCapabilities(active);
boolean vpnInUse = caps != null
    && caps.hasTransport(NetworkCapabilities.TRANSPORT_VPN);

جواب جان بوجھ کر تنگ ہے: کیا ایپ کا ڈیفالٹ نیٹ ورک اس وقت VPN ہے۔ یہ نہیں بتاتا کہ کون سا VPN، کیا وہ آپ کا ہے، یا کیا سرنگ دوسرے سرے تک پہنچتی ہے۔ true کو ”ٹریفک کسی سرنگ سے باہر جاتا ہے“ سمجھیں اور اپنا حساب الگ رکھیں۔ تین چیزیں خاموشی سے بیک وقت بتانے والا بولین ہی وہ سبب ہے کہ صارف کے VPN کے ذریعے براؤز کرتے وقت سیٹنگز اسکرین VPN کو بند بتاتی ہے۔

اس کے برعکس، اگر آپ کو جاننا ہو کہ کوئی بھی VPN نیٹ ورک موجود ہے یا نہیں، تو cm.getAllNetworks() پر دہرائیں اور ہر صلاحیت کے مجموعے کو جانچیں۔ دونوں جواب اس ڈیوائس پر مختلف ہوتے ہیں جہاں دوسری ایپس کو ڈھانپنے والا مگر آپ کی ایپ کو نہ ڈھانپنے والا ایپ مخصوص VPN چل رہا ہو، اور یہی فرق ان زیادہ تر بگ رپورٹس کا ذریعہ ہے جو کہتی ہیں کہ ایپ کو واضح طور پر آن VPN نظر نہیں آتا۔

پولنگ کی بجائے تبدیلیاں دیکھیں

ٹائمر پر پولنگ اس سوال کے لیے غلط شکل ہے، کیونکہ حالت کی تبدیلیاں واقعات کے طور پر آتی ہیں۔ VPN ٹرانسپورٹ سے مطابقت رکھنے والی درخواست رجسٹر کریں اور فریم ورک کو بتانے دیں کہ مطابق نیٹ ورک کب نمودار ہوتا ہے، غائب ہوتا ہے یا بدلتا ہے:

NetworkRequest request = new NetworkRequest.Builder()
    .addTransportType(NetworkCapabilities.TRANSPORT_VPN)
    .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
    .build();
cm.registerNetworkCallback(request, callback);

VPN نیٹ ورک کبھی NET_CAPABILITY_NOT_VPN نہیں اٹھاتا، اس لیے واضح طور پر ہٹانا ارادے کو دستاویز کرتا ہے۔ اس کے بغیر بھی درخواست مطابقت رکھتی ہے، مگر اگلے قاری کو یہ خود سمجھنا پڑے گا۔

رجسٹریشن اسی دائرے کی ہے جسے مشاہدہ درکار ہے، عام طور پر اسکرین یا فارگراؤنڈ سروس۔ onStop یا onDestroy میں رجسٹریشن ہٹائیں، اور پہلے ہی جا چکی سرگرمی کے ساتھ callback لٹکا نہ چھوڑیں۔ نظر آنے والا جزو نہ رکھنے والی ایپ مستقل مشاہدے کے لیے برا میزبان ہے، اور بھولے ہوئے callback ہی کنفیگریشن تبدیلی کے بعد کریش ہوتے ہیں۔

تین سوال الگ رکھیں

اس شعبے کی زیادہ تر الجھن تین مختلف جانچوں کو ایک سمجھنے سے آتی ہے۔ وہ مختلف API استعمال کرتی ہیں، اور ایک درست ہو تو باقی غلط ہو سکتی ہیں۔

QuestionHow you answer itWhat a yes means
Did the user grant VPN consent to my app?VpnService.prepare() returns nullConsent exists; the tunnel may still be down
Is the device sending default traffic through a VPN?TRANSPORT_VPN on the active networkSomething is tunneling, not necessarily your app
Did this request arrive through the VPN?Source address seen by the serverProof for that connection, nothing wider

تیسری سطر وہ ہے جس کا جواب لوگ کلائنٹ پر دینا چاہتے ہیں، اور وہاں جواب نہیں دیا جا سکتا۔ VPN کلائنٹس کو اپنا ایڈریس پول دیں اور سرور پر ماخذ ایڈریس پڑھیں؛ سیشن کے وسط میں صارف کے سرنگ بدلنے پر بھی بچنے والا یہی واحد ثبوت ہے۔

غلط مثبت نتائج خارج کرنے والی ترتیب

اب بھی رائج پرانا نمونہ کوڈ getNetworkInfo(ConnectivityManager.TYPE_VPN) کو کال کرتا ہے۔ وہ کال متروک ہے، اور کئی ریلیز میں VPN منسلک ہونے کے باوجود null واپس کرتا تھا، اسی لیے بہت سے نقل کیے گئے ٹکڑے کام کرنے والے ڈیوائس پر ٹوٹے نظر آتے ہیں۔ صلاحیت کی جانچیں اس جال سے بچتی ہیں اور اینڈرائیڈ 5.0 سے یکساں برتاؤ کرتی ہیں۔ اگر آپ ایسا کوڈ بیس رکھتے ہیں جو اب بھی اسے کال کرتا ہے تو کال کو fallback میں لپیٹنے کے بجائے خود کال بدلیں، کیونکہ غلط جواب پہلے اسی fallback نے پیدا کیا تھا۔

ایک شارٹ کٹ تنبیہ کا مستحق ہے۔ بیرونی سروس کے بتائے گئے عوامی ایڈریس کا VPN کے اخراجی ایڈریس سے موازنہ راستے کے بارے میں کچھ ثابت کرتا ہے، مگر ہر جانچ میں تیسرے فریق کی درخواست شامل کرتا ہے، اس سروس کے چلتے رہنے پر منحصر ہے، اور کیش یا مسدود ہو سکتا ہے۔ اسے دستی تشخیص رکھیں، ایپ کے اندر حالت کی جانچ کے طور پر کبھی نہیں۔

یہ جانچیں اسی ترتیب سے چلائیں اور پہلی ایسی پر رکیں جو صارف کی رپورٹ سے متصادم ہو: shell میں ٹرانسپورٹ کی فہرست، فعال نیٹ ورک کی صلاحیتیں، سرنگ آن اور آف کرتے وقت callback واقعات، پھر سرور کی طرف ماخذ ایڈریس۔ اگر چاروں میل کھاتے ہیں اور ایپ پھر بھی غلط برتاؤ کرتی ہے تو بگ اینڈرائیڈ کے نیٹ ورک کے نظریے میں نہیں، آپ کی اپنی حالت مشین میں ہے۔

متعلقہ مضامین