Waarom je Android-app geen systeem-VPN-profiel kan toevoegen
VpnService bouwt een tunnel die je app bezit; hij kan de PPTP-, L2TP- of IPsec-vermeldingen van de telefoon niet toevoegen of bewerken. Volg de grens en kies de juiste weg.
Je tikt in Instellingen op de VPN-rij, ziet een profiel dat iemand anders heeft geïnstalleerd, en begint te zoeken naar de aanroep die er een toevoegt. Die aanroep bestaat niet. Een app kan via VpnService een eigen tunnel openen, maar de vermeldingen in die lijst zijn van het platform en van de client die ze heeft gemaakt. Precies weten waar de grens ligt, bespaart je een week jagen op verborgen klassen.
Begin bij wat het scherm Instellingen toont
De VPN-lijst is een register van profielen die het systeem of een leveranciersclient heeft geïnstalleerd: PPTP, L2TP/IPsec, IKEv2 en alle rijen die een OEM-app of een MDM erin heeft geduwd. Elke rij draagt een serveradres, inloggegevens en een protocolimplementatie die buiten je proces leeft. Als de gebruiker daar op Verbinden tikt, brengt de client van het platform de tunnel op, niet jouw code. Daarom overleeft de rij een herstart en daarom verwijdert het verwijderen van je app hem nooit.
Vanuit de gebruiker gezien lijkt de lijst op een API-oppervlak, een plek waar een VPN toevoegen één intent verder zou moeten zijn. Dat is het niet. De enige openbare toegangspunten die hem raken zijn navigatie-intents, en alles wat erin schrijft is van het platform of van een bevoorrechte component.
Praktisch gevolg: als een ondersteuningstekst gebruikers vertelt het profiel in Instellingen toe te voegen, maakt je app helemaal geen deel uit van die stroom.
Wat VpnService je echt geeft
VpnService en VpnService.Builder beschrijven één tunnel die je app bezit. Je voegt adressen, routes, DNS-servers en een MTU toe, begrenst verkeer met addAllowedApplication() of addDisallowedApplication(), en dan geeft establish() een ParcelFileDescriptor voor een TUN-interface terug. Vanaf dat punt leest de app IP-pakketten en schrijft antwoorden, wat betekent dat het protocol van jou is om te implementeren of in te bouwen: OpenVPN, WireGuard, een eigen transport.
Niets in die reeks spreekt PPTP, L2TP/IPsec of IKEv2. Builder heeft geen schakelaar die zegt gebruik de L2TP-client van het systeem, en er is geen callback waarmee je een profiel kunt besturen dat het platform al bezit. Dat is de echte grens, en het is een ontwerpgrens, geen gat in de machtigingen.
Een app kan dus heel goed een VPN-client op Android zijn. Hij kan alleen geen beheerder zijn voor de clients die met de telefoon meekomen.
De toestemmingsdialoog is geen versiering
Omdat je tunnel verkeer van andere apps kan onderscheppen, eist het systeem dat de gebruiker die uitdrukkelijk goedkeurt. prepare() geeft een Intent terug die je moet starten, de goedkeuring is aan je pakket gebonden, en zolang de tunnel loopt toont de statusbalk een blijvende indicator. Een tweede VPN die opkomt, deactiveert de eerste, want Android draait één actieve VPN tegelijk.
Die regel van één actieve laat mensen struikelen in tests. Je brengt je tunnel op terwijl een bedrijfsclient verbonden is en concludeert dat je code stuk is, terwijl het platform simpelweg van de andere client is overgestapt. Goedkeuringen kunnen later worden ingetrokken, en prepare() kan null teruggeven op apparaten waar de toestemmingsactiviteit ontbreekt, dus establish() moet nog steeds met fouten omgaan.
Verborgen API's en instellingsintents
Oudere antwoorden wijzen op com.android.internal-klassen en AIDL-interfaces die de ingebouwde client gebruikt. Ze zitten niet in de SDK, ze veranderen tussen releases zonder aankondiging, en appwinkels beschouwen die toegang als een risico. Rooten van het apparaat maakt ze ook niet stabiel, want root en toegang tot verborgen API's zijn onverwante problemen.
De ondersteunde navigatiehulp is Settings.ACTION_VPN_SETTINGS, waarvan de waarde android.net.vpn.SETTINGS is. Los die op voordat je hem start, omdat sommige OEM-builds die activiteit niet meeleveren, en val terug op geschreven stappen als het oplossen mislukt. Hij brengt de gebruiker naar het scherm en configureert niets.
Apparaateigenaar- en MDM-routes zijn de uitzondering die mensen meestal bedoelen. DevicePolicyManager kan een always-on VPN-pakket aanwijzen, en beheerde configuraties kunnen instellingen voorladen voor een client die ze ondersteunt, maar dat is nog steeds niet de publieke SDK die een PPTP-profiel schrijft.
Loop de beslissing door vanuit de gebruiker
Als je product verkeer moet dragen, plan dan VpnService plus een echte protocolstack, en begroot tijd voor de toestemmingsstroom en de regel van één VPN. Als het doel is verbinding te maken met een bestaand bedrijfsprofiel, is je werk begeleiding: deep-link naar het instellingenscherm, documenteer de velden, en laat de client van het platform het tunnelen doen. Als de app alleen een privaat eindpunt hoeft te bereiken, heeft hij helemaal geen eigen tunnel nodig.
Schrijf die beslissing op voordat je code schrijft, want de drie wegen hebben na de eerste sprint bijna niets gemeen.
Een laatste controle voordat je begint: zegt de eis dat onze app verbindt, of dat het apparaat verbindt? Het eerste is VpnService, het tweede is een profiel dat je niet kunt maken. Die zin goed krijgen is goedkoper dan welke refactor dan ook.