Kvifor Android-appen din ikkje kan leggje til ein system-VPN-profil
VpnService byggjer ein tunnel som appen din eig; han kan ikkje leggje til eller endre PPTP-, L2TP- eller IPsec-oppføringane til telefonen. Gå grensa og vel rett veg.
Du trykkjer på VPN-radi i Innstillingar, ser ein profil nokon andre har installert, og byrjar å leite etter kallet som legg til ein. Det finst ikkje eit slikt kall. Ein app kan opne sin eigen tunnel via VpnService, men oppføringane i den lista høyrer til plattforma og den klienten som laga dei. Å vite nøyaktig kvar grensa går sparer deg ei veke med jakt på skjulte klassar.
Byrj med det Innstillingar-skjermen viser
VPN-lista er eit register over profilar som systemet eller ein leverandørklient har installert: PPTP, L2TP/IPsec, IKEv2 og radene ein OEM-app eller ein MDM har dytta inn. Kvar rad ber ei serveradresse, påloggingsdetaljar og ein protokollimplementasjon som lever utanfor prosessen din. Når brukaren trykkjer Kople til der, er det klienten til plattforma som reiser tunnelen, ikkje koden din. Derfor overlever rada ein omstart, og derfor fjernar avinstallering av appen din ho aldri.
Frå brukaren si side ser lista ut som ei API-flate, ein stad der det å leggje til ein VPN burde vere éin intensjon unna. Det er ho ikkje. Dei einaste offentlege inngangspunkta som rører ho, er navigasjonsintensjonar, og alt som skriv til ho, høyrer til plattforma eller ein privilegert komponent.
Praktisk følgje: om ein støttetekst ber brukarane leggje til profilen i Innstillingar, er appen din ikkje del av den flyten i det heile.
Kva VpnService faktisk gjev deg
VpnService og VpnService.Builder skildrar éin tunnel som appen din eig. Du legg til adresser, ruter, DNS-tenarar og ein MTU, avgrensar trafikken med addAllowedApplication() eller addDisallowedApplication(), og så returnerer establish() ein ParcelFileDescriptor for eit TUN-grensesnitt. Frå det punktet les appen IP-pakkar og skriv svar, som tyder at protokollen er din å implementere eller byggje inn: OpenVPN, WireGuard, ein eigen transport.
Ingenting i den sekvensen snakkar PPTP, L2TP/IPsec eller IKEv2. Builder har ingen brytar som seier bruk L2TP-klienten til systemet, og det finst ingen callback som lèt deg styre ein profil plattforma allereie eig. Det er den verkelege grensa, og det er ei designgrense, ikkje eit hol i løyva.
Så ein app kan absolutt vere ein VPN-klient på Android. Han kan berre ikkje vere administrator for klientane som følgjer med telefonen.
Samtykkedialogen er ikkje pynt
Fordi tunnelen din kan fange trafikken til andre apper, krev systemet at brukaren godkjenner han uttrykkeleg. prepare() returnerer ein Intent du må starte, godkjenninga er knytt til pakken din, og medan tunnelen er oppe viser statuslinja ein fast indikator. Ein andre VPN som kjem opp, deaktiverer den første, fordi Android køyrer éin aktiv VPN om gongen.
Den regelen om éin aktiv får folk til å snuble i testing. Du reiser tunnelen din medan ein bedriftsklient er tilkopla og konkluderer med at koden din er øydelagd, medan plattforma berre bytte bort frå den andre klienten. Godkjenningar kan trekkjast tilbake seinare, og prepare() kan returnere null på einingar der samtykkeaktiviteten manglar, så establish() må framleis handtere feil.
Skjulte API-ar og innstillingintensjonar
Eldre svar peikar på com.android.internal-klassar og AIDL-grensesnitt som den innebygde klienten brukar. Dei er ikkje i SDK-en, dei endrar seg mellom utgjevingar utan varsel, og app-butikkar ser på den tilgangen som ein risiko. Å roote eininga gjer dei heller ikkje stabile, fordi root og tilgang til skjulte API-ar er uavhengige problem.
Den støtta navigasjonshjelpa er Settings.ACTION_VPN_SETTINGS, kvor verdien er android.net.vpn.SETTINGS. Slå han opp før du startar han, fordi nokre OEM-bygg leverer ikkje den aktiviteten, og fall tilbake til skrivne steg når oppslaget feilar. Ho fører brukaren til skjermen og konfigurerer ingenting.
Einingseigar- og MDM-vegar er unntaket folk vanlegvis meiner. DevicePolicyManager kan peike ut ein alltid-på VPN-pakke, og administrerte konfigurasjonar kan førehandslaste innstillingar for ein klient som støttar dei, men det er framleis ikkje den offentlege SDK-en som skriv ein PPTP-profil.
Gå avgjerda frå brukaren si side
Om produktet ditt må bere trafikk, planlegg VpnService pluss ein ekte protokollstakk, og set av tid til samtykkeflyten og regelen om éin VPN. Om målet er å kople til ein eksisterande bedriftsprofil, er jobben din rettleiing: djup lenkje til innstillingane, dokumenter felta, og la klienten til plattforma gjere tunneleringa. Om appen berre treng å nå eit privat endepunkt, treng han ingen eigen tunnel i det heile.
Skriv ned den avgjerda før du skriv kode, fordi dei tre vegane har nesten ingenting til felles etter den første sprinten.
Ein siste sjekk før du byrjar: seier kravet at appen vår koplar til, eller at eininga koplar til? Det første er VpnService, det andre er ein profil du ikkje kan lage. Å få den setninga rett er billegare enn kvar ein refaktorering.