Jo kinne Android net freegje oft in VPN ferbûn is. VpnService biedt gjin getter foar ferbining, en it kaaiikoan yn 'e statusbalke wurdt troch it systeem tekene, net troch eat dat jo app lêze kin. Wat jo wol kinne, is de ferbiningstapel in smeller fraach stelle: hokker netwurk brûkt it ferkear fan dizze app, en draacht dat netwurk it VPN-transport. Dizze hantlieding rint de kontrôles ôf yn 'e folchoarder dy't falske positives foarkomt, fan in shell-opdracht op it apparaat oant de callback dy't jo yn 'e app rinnen litte.

Kontrolearje it apparaat fanút in shell foardat jo app-koade oanreitsje

Krij earst in basisline. adb shell dumpsys connectivity printsjelet elk netwurk dat it systeem ken, en elk blok listet syn transports op, dus in VPN-netwurk ferskynt mei VPN yn dy list. Lês it blok fan it standertnetwurk foar al it oare, en sykje dan nei oare netwurken dy't itselde transport drage.

Twa útfieringen beantwurdzje ferskillende fragen. Oft in VPN-netwurk bestiet is net itselde as oft jo app it brûkt, en op in apparaat mei in wurkprofyl of in twadde brûker kinne beide tagelyk wier wêze wylst jo proses direkt mei it ynternet praat. De rigel fan it aktive netwurk is dejinge dy't beslút wat jo sockets dogge.

Freegje om it netwurk dat de app brûkt

Yn koade is de mooglikheidstest fjouwer rigels. Freegje ACCESS_NETWORK_STATE oan yn it manifest, en fergelykje dan de mooglikheden fan it aktive netwurk mei it VPN-transport:

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);

It antwurd is mei opsetsin smel: is it standertnetwurk fan 'e app no in VPN. It seit neat oer hokker VPN it is, oft it fan jo is of oft de tunnel syn fiere ein berikt. Behannelje in true as “ferkear ferlit troch in tunnel” en hâld jo eigen boekhâlding apart. In boolean dy't stil trije dingen tagelyk betsjut, is hoe't in ynstellingsskerm úteinlik de VPN as út rapportearret wylst de brûker der trochhinne bladet.

As jo ynstee witte wolle oft der hokker VPN-netwurk dan ek is, iterearje oer cm.getAllNetworks() en test elke mooglikheidsset. De twa antwurden ferskille op in apparaat dat in per-app VPN rint dy't oare applikaasjes dekt mar net dy fan jo, en dat ferskil is de boarne fan de measte bugrapporten dy't sizze dat de app in VPN net sjen kin dy't dúdlik oan is.

Folgje feroarings ynstee fan te polljen

Polljen op in timer is de ferkearde foarm foar dizze fraach, om't steatferoarings as barrens ynkomme. Registrearje in fersyk dat by it VPN-transport past en lit it framework jo fertelle wannear't in passend netwurk ferskynt, ferdwynt of feroaret:

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

In VPN-netwurk draacht nea NET_CAPABILITY_NOT_VPN, dus it eksplisite fuortheljen dokumintearret de bedoeling. Sûnder dat past it fersyk noch hieltyd, mar de folgjende persoan dy't de koade lêst, moat dat sels útwurkje.

Registraasje heart by it berik dat de observaasje nedich hat, meastentiids in skerm of in foargrûnttsjinst. Deregistrearje yn onStop of onDestroy, en lit gjin callback hingje oan in aktiviteit dy't al fuort is. In app sûnder sichtbere komponint is in minne gasthear foar in permaninte waarnimmer, en de callbacks dy't jo ferjitte binne dejingen dy't nei in konfiguraasjeferoaring ynstoarte.

Hâld trije fragen apart

It measte betizing yn dit mêd komt fan it behanneljen fan trije ferskillende kontrôles as ien. Se brûke ferskillende API's, en elk kin wier wêze wylst de oaren falsk binne.

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

De tredde rigel is dejinge dy't minsken op 'e kliïnt besykje te beantwurdzjen, en dêr kin it net beantwurde wurde. Jou VPN-kliïnten har eigen adrespulel en lês it boarne-adres op 'e server; dat is it iennige bewiis dat in brûker oerlibbet dy't midden yn in sesje fan tunnel wikselet.

Ferifikaasjefolchoarder dy't falske positives útslút

Aldere foarbyldkoade dy't noch yn omgong is, ropt getNetworkInfo(ConnectivityManager.TYPE_VPN). Dy oprop is ferâldere, en yn ferskate releases joech er null werom sels wylst in VPN ferbûn wie, dêrom sjogge safolle kopiearre stikken der brutsen út op in apparaat dat wurket. Mooglikheidskontrôles mije de fal en gedrage har itselde fanôf Android 5.0. As jo in koadebasis ûnderhâlde dy't him noch ropt, ferfange de oprop ynstee fan him yn in fallback te wikkeljen, want de fallback wie wat it ferkearde antwurd oarspronklik makke.

Ien koarte wei fertsjinnet in warskôging. It fergelykjen fan it iepenbiere adres dat in eksterne tsjinst rapportearret mei it útgeansadres fan 'e VPN bewiist wol wat oer it paad, mar it foeget in fersyk fan in tredde partij ta oan elke kontrôle, is ôfhinklik fan dat dy tsjinst oan bliuwt, en kin cachet of blokkearre wurde. Hâld it as hânmjittige diagnoaze, nea as de steatkontrôle yn 'e app.

Run de kontrôles yn dizze folchoarder en stop by de earste dy't net oerienkomt mei it rapport fan 'e brûker: transportlist yn 'e shell, mooglikheden fan it aktive netwurk, callback-barrens wylst jo de tunnel oan en út sette, dan it boarne-adres oan 'e serverkant. As alle fjouwer oerienkomme en de app him noch hieltyd ferkeard hâldt, sit de bug yn jo eigen steatmasjine en net yn 'e manier wêrop Android it netwurk sjocht.

Relatearre artikelen