Kuidas koodis kontrollida, kas Androidis on VPN ühendatud
Androidil pole VPN-i ühenduse getterit. Küsige võrgu võimekusi, jälgige transpordi muutusi ning hoidke rakenduse nõusolek, seadme olek ja serveri tõestus lahus.
Te ei saa Androidilt küsida, kas VPN on ühendatud. VpnService ei paku ühenduse getterit ja olekuriba võtmeikooni joonistab süsteem, mitte miski, mida teie rakendus saaks lugeda. Mida saate teha, on küsida ühenduvuspinult kitsamat küsimust: millist võrku kasutab selle rakenduse liiklus ja kas see võrk kannab VPN-transporti. See juhend käib kontrollid läbi sellises järjekorras, mis väldib valepositiivseid, seadme shell-käsust kuni callbackini, mille jätate rakenduses tööle.
Kontrollige seadet shellist enne, kui puudutate rakenduse koodi
Hankige esmalt baasjoon. adb shell dumpsys connectivity trükib iga võrgu, mida süsteem teab, ja iga plokk loetleb oma transpordid, nii et VPN-võrk ilmub sellesse loendisse VPN-ga. Lugege vaikevõrgu plokk enne kõike muud ja otsige siis teisi võrke, mis kannavad sama transporti.
Kaks väljundit vastavad erinevatele küsimustele. VPN-võrgu olemasolu ei ole sama asi kui see, kas teie rakendus seda kasutab, ja tööprofiili või teise kasutajaga seadmes võivad mõlemad olla korraga tõesed, samal ajal kui teie protsess räägib internetiga otse. Aktiivse võrgu rida on see, mis otsustab, mida teie soklid teevad.
Küsige võrku, mida rakendus kasutab
Koodis on võimekuse test neli rida. Taotlege manifestis ACCESS_NETWORK_STATE ja võrrelge seejärel aktiivse võrgu võimekusi VPN-transpordiga:
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);
Vastus on meelega kitsas: kas rakenduse vaikevõrk on praegu VPN. See ei ütle midagi selle kohta, milline VPN see on, kas see kuulub teile või kas tunnel jõuab oma kaugemasse otsa. Käsitlege true kui „liiklus väljub mingi tunneli kaudu“ ja hoidke oma arvestust eraldi. Boolean, mis vaikselt tähendab kolme asja korraga, on põhjus, miks seadete ekraan lõpuks teatab, et VPN on väljas, samal ajal kui kasutaja selle kaudu sirvib.
Kui vajate hoopis teada, kas mõni VPN-võrk on olemas, itereerige üle cm.getAllNetworks() ja testige iga võimekuse komplekti. Need kaks vastust lahknevad seadmes, mis käitab rakendusepõhist VPN-i, mis katab teisi rakendusi, kuid mitte teie oma, ja see lahknevus on enamiku veateadete allikas, mis ütlevad, et rakendus ei näe VPN-i, mis on selgelt sees.
Jälgige muutusi selle asemel, et küsitleda
Taimeril küsitlemine on selle küsimuse jaoks vale vorm, sest olekumuutused saabuvad sündmustena. Registreerige taotlus, mis sobib VPN-transpordiga, ja laske raamistikul teile öelda, millal sobiv võrk ilmub, kaob või muutub:
NetworkRequest request = new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_VPN)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
.build();
cm.registerNetworkCallback(request, callback);
VPN-võrk ei kanna kunagi NET_CAPABILITY_NOT_VPN, seega dokumenteerib selgesõnaline eemaldamine kavatsuse. Ilma selleta taotlus ikkagi sobib, kuid järgmine inimene, kes koodi loeb, peab selle ise välja mõtlema.
Registreerimine kuulub sellele ulatusele, mis vaatlust vajab, tavaliselt ekraanile või esiplaani teenusele. Tühistage registreerimine funktsioonis onStop või onDestroy ja ärge jätke callbacki külge aktiivsusele, mida enam pole. Nähtava komponendita rakendus on püsiva vaatleja jaoks halb peremees, ja callbackid, mille unustate, on need, mis kukuvad pärast konfiguratsiooni muutust.
Hoidke kolm küsimust lahus
Suurem osa segadusest selles valdkonnas tuleb sellest, et kolme erinevat kontrolli käsitletakse ühena. Need kasutavad erinevaid API-sid ja igaüks võib olla tõene, samal ajal kui teised on väärad.
| 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 |
Kolmas rida on see, millele inimesed proovivad kliendis vastata, ja seal ei saa sellele vastata. Andke VPN-klientidele oma aadresside kogum ja lugege lähteaadressi serveris; see on ainus tõestus, mis jääb püsima, kui kasutaja vahetab seansi keskel tunnelit.
Kontrollijärjekord, mis välistab valepositiivsed
Vanem näidiskood, mis on veel ringluses, kutsub getNetworkInfo(ConnectivityManager.TYPE_VPN). See kutse on vananenud ja mitmes väljaandes tagastas see null ka VPN-i ühendatud oleku korral, mistõttu näib nii palju kopeeritud katkendeid töötaval seadmel katki. Võimekuse kontrollid väldivad lõksu ja käituvad samamoodi alates Androidist 5.0. Kui hooldate koodibaasi, mis seda veel kutsub, asendage kutse, selle asemel et see varuvariandiga mässida, sest varuvariant oligi see, mis vale vastuse tekitas.
Üks otsetee väärib hoiatust. Avaliku aadressi, millest väline teenus teatab, võrdlemine VPN-i väljumisaadressiga tõestab tõepoolest midagi tee kohta, kuid lisab igale kontrollile kolmanda osapoole taotluse, sõltub sellest, et see teenus püsiks töös, ja seda saab vahemällu salvestada või blokeerida. Hoidke seda käsitsi diagnoosina, mitte kunagi olekukontrollina rakenduse sees.
Tehke kontrollid selles järjekorras ja peatuge esimesel, mis ei ühti kasutaja aruandega: transportide loend shellis, aktiivse võrgu võimekused, callback-sündmused tunnelit sisse ja välja lülitades, seejärel lähteaadress serveri poolel. Kui kõik neli klapivad ja rakendus käitub endiselt valesti, on viga teie enda olekumasinas, mitte Androidi nägemuses võrgust.