Vous touchez la ligne VPN dans Réglages, vous voyez un profil installé par quelqu’un d’autre, et vous commencez à chercher l’appel qui en ajoute un. Cet appel n’existe pas. Une application peut ouvrir son propre tunnel via VpnService, mais les entrées de cette liste appartiennent à la plateforme et au client qui les a créées. Savoir exactement où passe la limite vous épargne une semaine de chasse aux classes cachées.

Commencez par ce que montre l’écran Réglages

La liste VPN est un registre des profils installés par le système ou par un client d’un fabricant : PPTP, L2TP/IPsec, IKEv2, et les lignes qu’une application OEM ou un MDM a poussées. Chaque ligne porte une adresse de serveur, des identifiants et une implémentation de protocole qui vit hors de votre processus. Quand l’utilisateur touche Connecter à cet endroit, c’est le client de la plateforme qui monte le tunnel, pas votre code. C’est pourquoi la ligne survit à un redémarrage et pourquoi désinstaller votre application ne la retire jamais.

Du point de vue de l’utilisateur, la liste ressemble à une surface d’API, un endroit où ajouter un VPN devrait être à un intent de distance. Elle ne l’est pas. Les seuls points d’entrée publics qui la touchent sont des intents de navigation, et tout ce qui y écrit appartient à la plateforme ou à un composant privilégié.

Conséquence pratique : si un texte d’assistance dit aux utilisateurs d’ajouter le profil dans Réglages, votre application ne fait pas du tout partie de ce parcours.

Ce que VpnService vous donne vraiment

VpnService et VpnService.Builder décrivent un tunnel que votre application possède. Vous ajoutez des adresses, des routes, des serveurs DNS et une MTU, vous délimitez le trafic avec addAllowedApplication() ou addDisallowedApplication(), puis establish() renvoie un ParcelFileDescriptor pour une interface TUN. À partir de là, l’application lit des paquets IP et écrit des réponses, ce qui veut dire que le protocole est à vous, à implémenter ou à embarquer : OpenVPN, WireGuard, un transport maison.

Rien dans cette séquence ne parle PPTP, L2TP/IPsec ni IKEv2. Builder n’a aucun commutateur qui dise utilise le client L2TP du système, et il n’existe aucun rappel qui vous laisse piloter un profil que la plateforme possède déjà. C’est la vraie frontière, et c’est une frontière de conception, pas un manque de permissions.

Une application peut donc tout à fait être un client VPN sous Android. Elle ne peut simplement pas être un gestionnaire pour les clients fournis avec le téléphone.

La boîte de consentement n’est pas décorative

Comme votre tunnel peut capturer le trafic d’autres applications, le système fait approuver celui-ci explicitement par l’utilisateur. prepare() renvoie un Intent que vous devez lancer, l’approbation est liée à votre paquet, et tant que le tunnel est actif la barre d’état affiche un indicateur permanent. Un second VPN qui monte désactive le premier, car Android n’exécute qu’un seul VPN actif à la fois.

Cette règle du seul actif fait trébucher les gens en test. Vous montez votre tunnel alors qu’un client d’entreprise est connecté et vous concluez que votre code est cassé, alors que la plateforme a simplement basculé depuis l’autre client. Les approbations peuvent être révoquées plus tard, et prepare() peut renvoyer null sur des appareils où l’activité de consentement manque, donc establish() doit encore gérer l’échec.

API cachées et intents de réglages

Les réponses anciennes pointent vers des classes com.android.internal et des interfaces AIDL qu’utilise le client intégré. Elles ne sont pas dans le SDK, elles changent d’une version à l’autre sans préavis, et les boutiques d’applications considèrent cet accès comme un risque. Rooter l’appareil ne les rend pas stables non plus, car root et accès aux API cachées sont des problèmes sans rapport.

L’aide à la navigation prise en charge est Settings.ACTION_VPN_SETTINGS, dont la valeur est android.net.vpn.SETTINGS. Résolvez-la avant de la lancer, car certaines compilations OEM ne fournissent pas cette activité, et repliez-vous sur des étapes écrites quand la résolution échoue. Elle mène l’utilisateur à l’écran et ne configure rien.

Les chemins propriétaire d’appareil et MDM sont l’exception que les gens visent d’habitude. DevicePolicyManager peut désigner un paquet VPN toujours actif, et les configurations gérées peuvent précharger des réglages pour un client qui les prend en charge, mais ce n’est toujours pas le SDK public qui rédige un profil PPTP.

Parcourez la décision du côté de l’utilisateur

Si votre produit doit transporter du trafic, prévoyez VpnService plus une vraie pile de protocoles, et budgétez du temps pour le parcours de consentement et la règle du VPN unique. Si l’objectif est de se connecter à un profil d’entreprise existant, votre travail est le guidage : lien profond vers l’écran des réglages, documenter les champs, et laisser le client de la plateforme faire le tunnel. Si l’application doit seulement atteindre un point de terminaison privé, elle n’a pas besoin de son propre tunnel du tout.

Écrivez cette décision avant d’écrire du code, car les trois chemins n’ont presque rien en commun après le premier sprint.

Une dernière vérification avant de commencer : l’exigence dit-elle que notre application se connecte, ou que l’appareil se connecte ? La première est VpnService, la seconde est un profil que vous ne pouvez pas créer. Formuler correctement cette phrase coûte moins cher que n’importe quelle refonte.

Articles similaires