Dentro de um WebView, uma página que pede a câmera ou a localização precisa passar por duas portas separadas — a permissão do SO e a permissão do WebView — e no Android o padrão é negar a segunda se o app não implementar o callback. Pior ainda, o WebView do Android dá ao app contenedor o controle total do tratamento de permissões web, sem o consentimento por site de um navegador de verdade: uma vez concedida a permissão do SO, o app pode compartilhar a localização ou a câmera com qualquer página do WebView sem aviso. No iOS, o WKWebView acrescenta um segundo aviso além do do app, e navegadores integrados como TikTok e Instagram não têm suporte oficial. Um runtime próprio do host oferece um único intermediário de permissões que alinha o consentimento nativo e web, aplica concessões por origem, exige contexto seguro e mostra um só aviso consistente.

Duas portas, e a segunda diz não por padrão

No Android, uma página que chama getUserMedia ou navigator.geolocation esbarra em duas verificações. Primeiro a permissão do SO — CÂMERA, RECORD_AUDIO ou localização declarados no manifest e concedidos em runtime (API 23+). Depois a permissão do WebView: mesmo com a concessão do SO, a página chega ao app como WebChromeClient.onPermissionRequest (câmera/mic) ou onGeolocationPermissionsShowPrompt (localização), e a resposta padrão é não. Se você não implementar o callback, o sintoma é desconcertante — permissão concedida, getUserMedia chamado, nada acontece, sem diálogo, uma promessa rejeitada. A localização só é chamada para origens seguras em apps voltados ao Android 7.0+, então uma página HTTP é negada antes de qualquer toque.

Sem consentimento por site, diferente de um navegador

Um estudo de 2025 sobre a execução de permissões web no WebView do Android mostra a brecha estrutural: navegadores tradicionais avisam por site e deixam o usuário conceder ou negar cada um, mas o WebView do Android delega a decisão inteira ao app contenedor. Se o app implementa o callback, ele pode conceder ou negar para qualquer origem, e não há memória por site nem controle visível ao usuário. O risco mais fundo é que, uma vez concedida a permissão de localização do SO ao app, o app pode entregar essa localização a qualquer site carregado no WebView sem outro consentimento do usuário — o usuário não vê qual página acessa o quê. Os desenvolvedores precisam construir essa UX de consentimento eles mesmos, ou ela não existe.

iOS: um segundo aviso, e rebaixamentos silenciosos

No iOS, o acesso a câmera e microfone do WKWebView exige que o app implemente requestMediaCapturePermissionFor (iOS 15+) e os entitlements correspondentes; antes disso, o WebRTC simplesmente não estava disponível no WKWebView. Mesmo implementado, o usuário vê dois avisos — um do app, um do site — e a solução documentada é o app pular o segundo via um delegate, o que significa que a escolha por página do usuário é decidida pelo app, não pela página. Quando a página é carregada por um custom scheme handler, o aviso mostra o nome do app como origem, o que confunde os usuários. Navegadores integrados (Instagram, TikTok) trazem restrições adicionais e UI quebrada e não têm suporte explícito.

O que você perde sem um intermediário de permissões

  • Uma única fonte de verdade. Os estados de permissão nativos e web vivem em lugares diferentes; divergem e se contradizem.
  • Controle por origem. O WebView do Android não tem memória de concessão por site; o app concede tudo ou nega tudo.
  • Visibilidade para o usuário. O usuário não sabe qual página acessa a câmera ou a localização, porque o consentimento vive no código do app.
  • Contexto seguro obrigatório. Uma página HTTP perde a localização em silêncio no Android moderno, sem razão visível.
  • Um aviso consistente. O iOS avisa duas vezes; os navegadores integrados quebram por completo.

A solução do runtime

Um runtime próprio do host oferece um único intermediário de permissões abaixo da página. Ele mantém um armazenamento de consentimento unificado para nativo e web, aplica concessões por origem como um navegador, exige contexto seguro antes de oferecer qualquer API sensível, e apresenta um só aviso consistente e legível que nomeia a página e o recurso. A concessão do SO do app e o pedido web da página são reconciliados em um só lugar, assim o consentimento é visível, revogável e nunca é compartilhado em silêncio com uma origem desconhecida.

DimensãoWebViewRuntime próprio do host
Modelo de consentimentoO app decide tudo, sem memória por siteArmazenamento unificado, concessões por origem
Porta 2 no AndroidonPermissionRequest nega por padrãoIntermediário concede por origem, visível
Avisos no iOSDois avisos, o app pode pular o do siteUm só aviso consistente
Contexto seguroLocalização HTTP negada em silêncioObrigatório, explicado
Visibilidade para o usuárioNão se vê qual página acessa o quêO aviso nomeia página e recurso
Navegadores integradosSem suporte, UI quebradaUm runtime, suporte em todo lugar

Um navegador conquista confiança fazendo a pergunta certa, para a parte certa, no momento certo. Um WebView de fábrica empurra essa decisão para um código de app opaco e depois diz não por padrão. Um runtime recupera o contrato de consentimento do navegador — por origem, visível e revogável — assim uma página que precisa da câmera recebe um aviso que o usuário realmente entende.

Fontes