Skip to main content
Não existe SDK nativo para iOS ou Android hoje — quando existir, esta página aponta para ele. Até lá, o caminho para um app nativo é abrir, dentro de uma WebView, a mesma página que você já usaria num navegador: com o Web SDK montado via npm ou CDN, ou com o iframe próprio. Nada nessa página muda por rodar numa WebView; o que muda é a permissão que o seu app precisa conceder para a câmera, o microfone e a geolocalização funcionarem dentro dela. Ao final deste guia, a página abre dentro da WebView do seu app e a captura de documento, a prova de vida e a coleta de geolocalização têm acesso ao que cada uma precisa.

Por que a permissão não vem sozinha

Um navegador pede câmera, microfone e localização ao usuário quando a página chama getUserMedia ou navigator.geolocation. Uma WebView embutida no seu app não pede: por padrão, ela nega em silêncio, mesmo a página declarando a permissão corretamente — o que o Web SDK já faz no iframe que ele cria (allow="camera; microphone; geolocation; fullscreen", ver segurança). Sem o passo nativo abaixo, a captura e a coleta de localização falham sem nenhum erro que a sua página consiga tratar.

iOS — WKWebView

Declare os três textos de uso no Info.plist e implemente o delegado que autoriza câmera e microfone:
Info.plist
requestMediaCapturePermissionFor existe a partir do iOS 15 e cobre câmera e microfone. Sem o delegado, a WKWebView recusa a concessão por padrão, mesmo com as chaves do Info.plist presentes. getUserMedia em si só funciona em WKWebView de app de terceiro a partir do iOS 14.3; abaixo disso a API não existe na página.
Geolocalização não passa por delegado nenhum: a WKWebView não tem um método equivalente ao requestMediaCapturePermissionFor para navigator.geolocation hoje. Quem pede a autorização de localização ao sistema é o próprio WebKit — seu app não chama nada —, mas só faz isso com a chave NSLocationWhenInUseUsageDescription presente no Info.plist. Sem ela, o pedido nunca é feito e a página trava esperando uma posição que nunca chega, sem erro nenhum. Passe um timeout explícito em getCurrentPosition/watchPosition para não depender de detectar isso pelo travamento.

Android — WebView

Declare as permissões no AndroidManifest.xml, peça a permissão em tempo de execução ao usuário (Android 6.0+ exige isso independentemente da WebView) e conceda no WebChromeClient. Câmera e microfone passam por onPermissionRequest; geolocalização é um método separado, onGeolocationPermissionsShowPrompt, e precisa da própria configuração ligada no WebSettings:
AndroidManifest.xml
Conceder aqui sem a permissão de runtime concedida ao app não libera nada: são duas camadas separadas, e as duas precisam estar de acordo. E sem setGeolocationEnabled(true), onGeolocationPermissionsShowPrompt nunca dispara.

Framework híbrido (React Native, Flutter e afins)

O mecanismo por baixo é o mesmo dos dois itens acima — o wrapper só decide como ele expõe isso. Confira na documentação da versão do wrapper que você usa como conceder a permissão de mídia da WebView nos dois sistemas; nem toda versão cobre iOS e Android da mesma forma. No iOS, getUserMedia não funciona quando a página é servida por um esquema de URL customizado em vez de https:// ou http://localhost — é limitação da própria WKWebView, não do wrapper. Confirme qual esquema a versão do seu wrapper usa antes de depurar a permissão.
A falha muda por plataforma e por capacidade, e vale saber qual é qual antes de abrir um chamado:
  • Android, câmera sem onPermissionRequest: erro imediato (NotAllowedError) — o default do WebChromeClient é negar.
  • Android, geolocalização sem onGeolocationPermissionsShowPrompt: nenhum erro. O callback nunca é chamado, e a chamada trava até o timeout que a página passar — ou para sempre, se ela não passar nenhum.
  • iOS, câmera sem o delegado: a WKWebView mostra o prompt do próprio sistema e funciona sem código nenhum, contanto que a chave do Info.plist esteja presente.
  • iOS, geolocalização sem a chave do Info.plist: o mesmo travamento silencioso do Android, por um motivo diferente (veja o aviso acima).
Nas duas plataformas, “passo nativo ausente” e “titular recusou a permissão” chegam à página como o mesmo erro na maioria dos casos. Confirme o lado nativo antes de tratar a ausência de coleta como recusa do titular.

Iframe próprio

Se a página que a WebView abre não carrega o Web SDK, veja o que muda no tratamento de eventos.