Você publicou uma build nova, passou para a VPN, e a mesma tela parou de carregar. No Android 9 e posteriores a explicação mais comum é mais sem graça: a plataforma recusa HTTP simples para apps que miram a API 28 ou superior, e a VPN só mudou contexto suficiente para expor isso. O erro que você vê depende do cliente HTTP, por isso ele tão raramente diz cleartext.

O que essa falha realmente é

A partir do Android 9 a plataforma bloqueia cleartext por padrão assim que um app mira o nível de API 28 ou superior. A plataforma rejeita a requisição para um endereço HTTP simples antes que um único pacote saia do aparelho. Qual erro você vê depende da biblioteca HTTP: às vezes uma falha de rede genérica, às vezes um timeout, às vezes uma mensagem que nomeia cleartext sem rodeios. O que ela nunca faz é chegar ao seu servidor. O Android documenta o padrão e a alternativa limitada por domínio no seu guia de configuração de segurança.

Um navegador no mesmo aparelho ainda consegue carregar a página, e essa é a pista que a maioria das pessoas perde. Navegadores não estão sujeitos à política de segurança de rede do seu app.

Por que a VPN leva a culpa

Normalmente três coisas mudam ao mesmo tempo. O app pode resolver outro nome de host depois que a VPN conecta, o aparelho pode ser novo com uma build mais recente, ou a própria build pode ter passado para um nível de API de destino que ativa o padrão. A VPN é visível e o SDK de destino não é, então a VPN fica com o chamado.

Compare os níveis de destino das builds antiga e nova antes de mexer na configuração de rede. Um app que mira 27 ou menos está isento, e isso explica todo relato do tipo «no meu celular antigo funciona».

Onde o sinalizador do Expo realmente fica

Num projeto Expo gerenciado, adicionar uma configuração a app.json não edita um manifesto do Android, porque o manifesto é produzido pelo prebuild e pelas builds de desenvolvimento. É o plugin de configuração que grava a definição nessa etapa. O caminho suportado é expo-build-properties, configurado na configuração do app com a opção cleartext sob android.

{
  "plugins": [
    ["expo-build-properties", {
      "android": { "usesCleartextTraffic": true }
    }]
  ]
}

O trecho só define a opção do plugin; o manifesto é produzido depois. Rode um prebuild ou uma build nova do cliente de desenvolvimento e, antes de retestar, inspecione o AndroidManifest.xml gerado em busca de android:usesCleartextTraffic, porque um recarregamento só de JS mantém o manifesto antigo. Alinhe a versão do plugin ao SDK do Expo em que o projeto roda. As opções de plugin mudam entre versões, e um trecho copiado de outro SDK é uma fonte confiável de no-ops silenciosos.

O fluxo bare e a opção mais estreita

Para React Native bare o equivalente é android:usesCleartextTraffic no elemento application, ou uma configuração de segurança de rede que permita cleartext apenas para domínios nomeados. A forma limitada por domínio é a preferível, porque permite a API interna e deixa todo o resto em HTTPS. Ela também documenta sua própria lista de exceções, e é essa a parte que um revisor vai questionar.

Nenhuma das duas abordagens muda o padrão da plataforma para nada que você não tenha nomeado.

Primeiro prove pelo log do aparelho

Antes de editar a configuração, obtenha a falha exata. adb logcat num aparelho conectado mostra a recusa de cleartext da plataforma e nomeia o componente que a levantou. Um socket recusado, um nome que não resolve ou um handshake TLS mal-sucedido apontam para outro lugar completamente, e ativar cleartext só enfraqueceria o app sem motivo.

Depois mantenha a produção honesta. Cleartext é aceitável para um endpoint de laboratório que não pode oferecer TLS, e só pelo menor tempo que você conseguir planejar. Se a API pode encerrar TLS dentro da rede privada, ponha o certificado no repositório de confiança do aparelho e deixe cleartext desativado, porque o túnel cifra o caminho até a sua saída e nada além.

Quando o endpoint responder em HTTPS, remova a permissão, reconstrua e teste na VPN e em Wi-Fi comum na mesma sessão. A resolução de nomes pode diferir entre esses dois caminhos, e só o par diz qual está falando a verdade.

Artigos relacionados