Hvorfor din Android-app ikke kan tilføje en system-VPN-profil
VpnService bygger en tunnel, din app ejer; den kan ikke tilføje eller redigere telefonens PPTP-, L2TP- eller IPsec-poster. Følg grænsen og vælg den rigtige vej.
Du trykker på VPN-rækken i Indstillinger, ser en profil, som en anden har installeret, og begynder at lede efter det kald, der tilføjer en. Der findes ikke sådan et kald. En app kan åbne sin egen tunnel via VpnService, men posterne på listen tilhører platformen og den klient, der oprettede dem. At vide præcis, hvor grænsen ligger, sparer dig en uges jagt på skjulte klasser.
Start med det, skærmen Indstillinger viser
VPN-listen er et register over profiler, som systemet eller en leverandørklient har installeret: PPTP, L2TP/IPsec, IKEv2 og de rækker, en OEM-app eller en MDM har skubbet ind. Hver række bærer en serveradresse, legitimationsoplysninger og en protokolimplementering, der lever uden for din proces. Når brugeren trykker Forbind der, er det platformens klient, der rejser tunnelen, ikke din kode. Derfor overlever rækken en genstart, og derfor fjerner afinstallationen af din app den aldrig.
Set fra brugerens side ligner listen en API-flade, et sted, hvor tilføjelse af en VPN burde være ét intent væk. Det er den ikke. De eneste offentlige indgangspunkter, der rører den, er navigationsintents, og alt, der skriver til den, tilhører platformen eller en privilegeret komponent.
Praktisk konsekvens: hvis en supporttekst fortæller brugerne at tilføje profilen i Indstillinger, er din app slet ikke en del af det flow.
Hvad VpnService egentlig giver dig
VpnService og VpnService.Builder beskriver én tunnel, som din app ejer. Du tilføjer adresser, ruter, DNS-servere og en MTU, afgrænser trafik med addAllowedApplication() eller addDisallowedApplication(), og derefter returnerer establish() en ParcelFileDescriptor til et TUN-interface. Fra det punkt læser appen IP-pakker og skriver svar, hvilket betyder, at protokollen er din at implementere eller indlejre: OpenVPN, WireGuard, en egen transport.
Intet i den sekvens taler PPTP, L2TP/IPsec eller IKEv2. Builder har ingen kontakt, der siger brug systemets L2TP-klient, og der er ingen callback, der lader dig styre en profil, som platformen allerede ejer. Det er den egentlige grænse, og det er en designgrænse snarere end et hul i tilladelserne.
Så en app kan afgjort være en VPN-klient på Android. Den kan bare ikke være administrator for de klienter, der følger med telefonen.
Samtykkedialogen er ikke pynt
Fordi din tunnel kan opfange andre appes trafik, kræver systemet, at brugeren godkender den udtrykkeligt. prepare() returnerer et Intent, du skal starte, godkendelsen er knyttet til din pakke, og mens tunnelen er oppe viser statuslinjen en fast indikator. En anden VPN, der kommer op, deaktiverer den første, fordi Android kører én aktiv VPN ad gangen.
Den regel med én aktiv snyder folk i test. Du rejser din tunnel, mens en virksomhedsklient er forbundet, og konkluderer, at din kode er i stykker, mens platformen blot skiftede væk fra den anden klient. Godkendelser kan trækkes tilbage senere, og prepare() kan returnere null på enheder, hvor samtykkeaktiviteten mangler, så establish() skal stadig håndtere fejl.
Skjulte API'er og indstillingsintents
Ældre svar peger på com.android.internal-klasser og AIDL-interfaces, som den indbyggede klient bruger. De er ikke i SDK'en, de ændrer sig mellem udgivelser uden varsel, og app-butikker betragter den adgang som en risiko. At roote enheden gør dem heller ikke stabile, fordi root og adgang til skjulte API'er er uafhængige problemer.
Den understøttede navigationshjælp er Settings.ACTION_VPN_SETTINGS, hvis værdi er android.net.vpn.SETTINGS. Slå den op før start, fordi nogle OEM-builds ikke leverer den aktivitet, og fald tilbage til skrevne trin, når opslaget fejler. Den fører brugeren til skærmen og konfigurerer intet.
Enhedsejer- og MDM-veje er den undtagelse, folk normalt mener. DevicePolicyManager kan udpege en always-on VPN-pakke, og administrerede konfigurationer kan forudindlæse indstillinger til en klient, der understøtter dem, men det er stadig ikke den offentlige SDK, der forfatter en PPTP-profil.
Gå beslutningen igennem fra brugerens side
Hvis dit produkt skal bære trafik, planlæg VpnService plus en rigtig protokolstak, og afsæt tid til samtykkeflowet og reglen om én VPN. Hvis målet er at forbinde til en eksisterende virksomhedsprofil, er dit arbejde vejledning: deep-link til indstillingsskærmen, dokumentér felterne, og lad platformens klient gøre tuneringen. Hvis appen kun skal nå et privat endepunkt, har den slet ikke brug for sin egen tunnel.
Skriv den beslutning ned, før du skriver kode, fordi de tre veje næsten intet har til fælles efter den første sprint.
En sidste kontrol, før du starter: siger kravet, at vores app forbinder, eller at enheden forbinder? Det første er VpnService, det andet er en profil, du ikke kan oprette. At få den sætning rigtig er billigere end enhver refaktorering.