Tocchi la riga VPN nelle Impostazioni, vedi un profilo installato da qualcun altro e inizi a cercare la chiamata che ne aggiunge uno. Quella chiamata non esiste. Un'app può aprire un tunnel proprio tramite VpnService, ma le voci di quell'elenco appartengono alla piattaforma e al client che le ha create. Sapere esattamente dove passa il confine ti risparmia una settimana di caccia alle classi nascoste.

Parti da ciò che mostra la schermata Impostazioni

L'elenco VPN è un registro dei profili installati dal sistema o da un client di un produttore: PPTP, L2TP/IPsec, IKEv2 e le righe spinte da un'app OEM o da un MDM. Ogni riga porta un indirizzo di server, credenziali e un'implementazione di protocollo che vive fuori dal tuo processo. Quando l'utente tocca Connetti lì, è il client della piattaforma ad alzare il tunnel, non il tuo codice. Per questo la riga sopravvive a un riavvio e per questo disinstallare la tua app non la rimuove mai.

Dal lato dell'utente l'elenco sembra una superficie API, un posto dove aggiungere una VPN dovrebbe essere a un intent di distanza. Non lo è. Gli unici punti di ingresso pubblici che la toccano sono intent di navigazione, e tutto ciò che vi scrive appartiene alla piattaforma o a un componente privilegiato.

Conseguenza pratica: se un testo di assistenza dice agli utenti di aggiungere il profilo nelle Impostazioni, la tua app non fa affatto parte di quel flusso.

Cosa ti dà davvero VpnService

VpnService e VpnService.Builder descrivono un tunnel che appartiene alla tua app. Aggiungi indirizzi, rotte, server DNS e una MTU, delimiti il traffico con addAllowedApplication() o addDisallowedApplication(), poi establish() restituisce un ParcelFileDescriptor per un'interfaccia TUN. Da quel punto l'app legge pacchetti IP e scrive risposte, il che significa che il protocollo è tuo da implementare o incorporare: OpenVPN, WireGuard, un trasporto personalizzato.

Niente in quella sequenza parla PPTP, L2TP/IPsec o IKEv2. Builder non ha alcun interruttore che dica usa il client L2TP di sistema, e non esiste alcun callback che ti permetta di pilotare un profilo che la piattaforma possiede già. Questo è il confine reale, ed è un confine di progetto, non una lacuna nei permessi.

Quindi un'app può benissimo essere un client VPN su Android. Solo che non può essere un gestore per i client forniti con il telefono.

La finestra di consenso non è decorazione

Poiché il tuo tunnel può catturare il traffico di altre app, il sistema fa approvare esplicitamente dall'utente. prepare() restituisce un Intent che devi lanciare, l'approvazione è legata al tuo pacchetto, e finché il tunnel è attivo la barra di stato mostra un indicatore permanente. Un secondo VPN che sale disattiva il primo, perché Android esegue un solo VPN attivo alla volta.

Questa regola dell'unico attivo fa inciampare la gente nei test. Alzi il tuo tunnel mentre un client aziendale è connesso e concludi che il tuo codice è rotto, quando la piattaforma è semplicemente passata dall'altro client. Le approvazioni possono essere revocate in seguito, e prepare() può restituire null su dispositivi dove manca l'attività di consenso, quindi establish() deve comunque gestire il fallimento.

API nascoste e intent delle impostazioni

Le risposte più vecchie puntano a classi com.android.internal e interfacce AIDL usate dal client integrato. Non sono nell'SDK, cambiano tra le versioni senza preavviso e gli store di app trattano quell'accesso come un rischio. Anche il root del dispositivo non le rende stabili, perché root e accesso alle API nascoste sono problemi non correlati.

L'aiuto di navigazione supportato è Settings.ACTION_VPN_SETTINGS, il cui valore è android.net.vpn.SETTINGS. Risolvilo prima di lanciarlo, perché alcune build OEM non includono quell'attività, e passa a passaggi scritti quando la risoluzione fallisce. Porta l'utente alla schermata e non configura nulla.

I percorsi proprietario del dispositivo e MDM sono l'eccezione che la gente di solito intende. DevicePolicyManager può designare un pacchetto VPN sempre attivo, e le configurazioni gestite possono precaricare impostazioni per un client che le supporta, ma non è ancora l'SDK pubblico che redige un profilo PPTP.

Percorri la decisione dal lato dell'utente

Se il tuo prodotto deve trasportare traffico, pianifica VpnService più uno stack di protocolli reale, e metti in budget tempo per il flusso di consenso e la regola del VPN unico. Se l'obiettivo è collegarsi a un profilo aziendale esistente, il tuo lavoro è la guida: link diretto alla schermata delle impostazioni, documenta i campi e lascia che il client della piattaforma faccia il tunnel. Se l'app deve solo raggiungere un endpoint privato, non ha affatto bisogno di un tunnel proprio.

Scrivi quella decisione prima di scrivere codice, perché le tre strade non hanno quasi nulla in comune dopo il primo sprint.

Un ultimo controllo prima di iniziare: il requisito dice che si collega la nostra app o che si collega il dispositivo? Il primo è VpnService, il secondo è un profilo che non puoi creare. Azzeccare quella frase costa meno di qualsiasi refactoring.

Articoli correlati