Kā kodā pārbaudīt, vai Android ierīcē ir pieslēgts VPN
Android nav VPN pieslēguma getter. Vaicājiet tīkla iespējas, sekojiet transporta izmaiņām un šķiriet lietotnes piekrišanu, ierīces stāvokli un servera pierādījumu.
Jūs nevarat Android pajautāt, vai VPN ir pieslēgts. VpnService nepiedāvā pieslēguma stāvokļa getter, un atslēgas ikonu statusa joslā zīmē sistēma, nevis kaut kas, ko jūsu lietotne var nolasīt. Ko jūs varat darīt, ir uzdot savienojamības stekam šaurāku jautājumu: kuru tīklu izmanto šīs lietotnes trafiks un vai šis tīkls pārvadā VPN transportu. Šī rokasgrāmata iziet pārbaudes tādā secībā, kas izvairās no viltus pozitīviem, sākot no shell komandas ierīcē līdz atzvanam, ko atstājat darboties lietotnē.
Pirms aiztikt lietotnes kodu, pārbaudiet ierīci no shell
Vispirms iegūstiet bāzes stāvokli. adb shell dumpsys connectivity izdrukā katru sistēmai zināmo tīklu, un katrs bloks uzskaita savus transportus, tāpēc VPN tīkls šajā sarakstā parādās ar VPN. Vispirms izlasiet noklusējuma tīkla bloku, pēc tam meklējiet citus tīklus, kas pārvadā to pašu transportu.
Divi izvadi atbild uz dažādiem jautājumiem. Tas, vai VPN tīkls pastāv, nav tas pats, kas tas, vai jūsu lietotne to izmanto, un ierīcē ar darba profilu vai otru lietotāju abi var būt patiesi vienlaikus, kamēr jūsu process runā tieši ar internetu. Aktīvā tīkla rinda ir tā, kas izlemj, ko dara jūsu ligzdas.
Vaicājiet tīklu, ko lietotne izmanto
Kodā iespēju tests ir četras rindas. Manifestā pieprasiet ACCESS_NETWORK_STATE, pēc tam salīdziniet aktīvā tīkla iespējas ar VPN transportu:
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);
Atbilde ir apzināti šaura: vai lietotnes noklusējuma tīkls šobrīd ir VPN. Tā neko nesaka par to, kurš VPN, vai tas pieder jums, vai tunelis sasniedz otru galu. true uztveriet kā “trafiks iziet pa kādu tuneli” un savu uzskaiti turiet atsevišķi. Būla vērtība, kas klusi nozīmē trīs lietas vienlaikus, ir iemesls, kāpēc iestatījumu ekrāns ziņo, ka VPN ir izslēgts, kamēr lietotājs pārlūko caur to.
Ja gluži pretēji jums jāzina, vai vispār ir kāds VPN tīkls, atkārtojiet cm.getAllNetworks() un pārbaudiet katru iespēju kopu. Divas atbildes atšķiras ierīcē, kur darbojas lietotnei specifisks VPN, kas aptver citas lietotnes, bet ne jūsējo, un šī atšķirība ir lielākās daļas kļūdu ziņojumu avots, kuros teikts, ka lietotne neredz skaidri ieslēgtu VPN.
Sekojiet izmaiņām, nevis aptaujājiet
Aptaujāšana ar taimeri šim jautājumam ir nepareiza forma, jo stāvokļa izmaiņas nāk kā notikumi. Reģistrējiet pieprasījumu, kas atbilst VPN transportam, un ļaujiet sistēmai pateikt, kad atbilstošs tīkls parādās, pazūd vai mainās:
NetworkRequest request = new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_VPN)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
.build();
cm.registerNetworkCallback(request, callback);
VPN tīkls nekad nepārvadā NET_CAPABILITY_NOT_VPN, tāpēc skaidra noņemšana dokumentē nodomu. Bez tā pieprasījums joprojām atbilst, bet nākamajam cilvēkam, kas lasa kodu, tas jāizdomā pašam.
Reģistrācija pieder tvērumam, kuram nepieciešams novērojums, parasti ekrānam vai priekšplāna pakalpojumam. Atcēliet reģistrāciju onStop vai onDestroy, un neatstājiet atzvanu piesaistītu jau pazudušai aktivitātei. Lietotne bez redzamas komponentes ir slikts pastāvīga novērotāja saimnieks, un aizmirstie atzvani ir tie, kas avarē pēc konfigurācijas maiņas.
Turiet trīs jautājumus atsevišķi
Lielākā daļa apjukumā šajā jomā rodas, traktējot trīs dažādas pārbaudes kā vienu. Tās izmanto dažādas API, un katra var būt patiesa, kamēr pārējās ir nepatiesas.
| Question | How you answer it | What a yes means |
|---|---|---|
| Did the user grant VPN consent to my app? | VpnService.prepare() returns null | Consent exists; the tunnel may still be down |
| Is the device sending default traffic through a VPN? | TRANSPORT_VPN on the active network | Something is tunneling, not necessarily your app |
| Did this request arrive through the VPN? | Source address seen by the server | Proof for that connection, nothing wider |
Trešā rinda ir tā, uz kuru cilvēki mēģina atbildēt klientā, un tur to nevar atbildēt. Piešķiriet VPN klientiem savu adrešu kopu un lasiet avota adresi serverī; tas ir vienīgais pierādījums, kas pārdzīvo lietotāja tunela maiņu sesijas vidū.
Pārbaudes secība, kas izslēdz viltus pozitīvos
Vecāks parauga kods, kas vēl cirkulē, izsauc getNetworkInfo(ConnectivityManager.TYPE_VPN). Šis izsaukums ir novecojis, un vairākās versijās tas atgrieza null arī tad, kad VPN bija pieslēgts, tāpēc tik daudz nokopētu fragmentu izskatās salauzti ierīcē, kas darbojas. Iespēju pārbaudes izvairās no šīs lamatām un uzvedas vienādi no Android 5.0. Ja uzturat kodu bāzi, kas to joprojām izsauc, aizstājiet izsaukumu, nevis iesaiņojiet to rezerves variantā, jo tieši rezerves variants radīja nepareizo atbildi.
Viens saīsinājums pelna brīdinājumu. Publiskās adreses, ko ziņo ārējs pakalpojums, salīdzināšana ar VPN izejas adresi kaut ko pierāda par ceļu, bet tā pievieno trešās puses pieprasījumu katrai pārbaudei, ir atkarīga no tā, vai pakalpojums darbojas, un var tikt kešota vai bloķēta. Turiet to kā manuālu diagnostiku, nekad ne kā stāvokļa pārbaudi lietotnes iekšienē.
Veiciet pārbaudes šajā secībā un apstājieties pie pirmās, kas neatbilst lietotāja ziņojumam: transportu saraksts no shell, aktīvā tīkla iespējas, atzvanu notikumi, ieslēdzot un izslēdzot tuneli, tad avota adrese servera pusē. Ja visi četri sakrīt un lietotne joprojām darbojas nepareizi, kļūda ir jūsu pašu stāvokļa mašīnā, nevis Android tīkla redzējumā.