L’app Expo échoue en HTTP sous Android 9 : c’est le cleartext, pas le VPN
Un build Expo qui appelle une API HTTP simple échoue sous Android 9 et au-delà. Le tunnel est innocent : l’indicateur cleartext appartient à la configuration du build.
Vous avez livré un nouveau build, êtes passé sur le VPN, et le même écran a cessé de se charger. Sous Android 9 et au-delà, l’explication la plus courante est plus terne : la plateforme refuse le HTTP simple aux applications qui ciblent l’API 28 ou plus, et le VPN n’a changé que juste assez de contexte pour le révéler. L’erreur que vous voyez dépend du client HTTP, c’est pourquoi elle dit si rarement cleartext.
Ce qu’est réellement cette panne
À partir d’Android 9, la plateforme bloque le cleartext par défaut dès qu’une application cible le niveau d’API 28 ou supérieur. La plateforme rejette la requête vers une adresse HTTP simple avant qu’un seul paquet ne quitte l’appareil. L’erreur que vous voyez dépend de la bibliothèque HTTP : parfois un échec réseau générique, parfois un délai dépassé, parfois un message qui nomme cleartext sans détour. Ce qu’elle ne fait jamais, c’est atteindre votre serveur. Android documente le comportement par défaut et l’alternative limitée au domaine dans son guide de configuration de sécurité.
Un navigateur sur le même appareil peut encore charger la page, et c’est l’indice que la plupart des gens manquent. Les navigateurs ne sont pas soumis à la politique de sécurité réseau de votre application.
Pourquoi le VPN est mis en cause
Trois choses changent généralement en même temps. L’application peut résoudre un autre nom d’hôte après la connexion du VPN, l’appareil peut être neuf avec un build plus récent, ou le build lui-même a pu passer à un niveau d’API cible qui déclenche le comportement par défaut. Le VPN est visible et le SDK cible ne l’est pas, donc le VPN prend le ticket.
Comparez les niveaux cibles de l’ancien et du nouveau build avant de toucher à la configuration réseau. Une application qui cible 27 ou moins en est exemptée, ce qui explique tous les rapports du type « ça marche sur mon vieux téléphone ».
Où atterrit réellement l’indicateur Expo
Dans un projet Expo géré, ajouter un réglage à app.json ne modifie pas un manifeste Android, car ce sont le prebuild et les builds de développement qui produisent le manifeste. C’est un plugin de configuration qui écrit le réglage à cette étape. La voie prise en charge est expo-build-properties, configuré dans la configuration de l’application avec l’option cleartext sous android.
{
"plugins": [
["expo-build-properties", {
"android": { "usesCleartextTraffic": true }
}]
]
}L’extrait ne fait que définir l’option du plugin ; le manifeste est produit plus tard. Lancez un prebuild ou un build neuf du client de développement, puis, avant de retester, inspectez l’AndroidManifest.xml généré pour android:usesCleartextTraffic, car un rechargement purement JS conserve l’ancien manifeste. Alignez la version du plugin sur le SDK Expo avec lequel le projet tourne. Les options de plugin évoluent d’une version à l’autre, et un extrait copié depuis un autre SDK est une source fiable de no-ops silencieux.
Le flux bare et l’option plus étroite
Pour React Native bare, l’équivalent est android:usesCleartextTraffic sur l’élément application, ou une configuration de sécurité réseau qui n’autorise le cleartext que pour des domaines nommés. La forme limitée au domaine est celle à préférer, car elle autorise l’API interne et laisse tout le reste en HTTPS. Elle documente aussi sa propre liste d’exceptions, et c’est précisément la partie sur laquelle un relecteur posera des questions.
Aucune des deux approches ne change le comportement par défaut de la plateforme pour ce que vous n’avez pas nommé.
Prouvez-le d’abord avec le journal de l’appareil
Avant de modifier la configuration, obtenez la panne exacte. adb logcat sur un appareil connecté montre le rejet cleartext de la plateforme et nomme le composant qui l’a provoqué. Une socket refusée, un nom qui ne se résout pas ou une poignée de main TLS ratée pointent ailleurs, et activer le cleartext ne ferait qu’affaiblir l’application pour rien.
Ensuite, gardez la production honnête. Le cleartext est acceptable pour un point de labo qui ne peut pas offrir TLS, et seulement pour la période la plus courte que vous pouvez planifier. Si l’API peut terminer TLS à l’intérieur du réseau privé, mettez le certificat dans le magasin de confiance de l’appareil et laissez le cleartext désactivé, car le tunnel chiffre le chemin jusqu’à sa sortie et rien au-delà.
Dès que le point répond en HTTPS, retirez l’autorisation, reconstruisez et testez sur le VPN et sur un Wi-Fi ordinaire dans la même session. La résolution de noms peut différer entre ces deux chemins, et seule la paire vous dit lequel dit la vérité.