Um app nativo controla sua própria mídia: tela cheia, reprodução automática e áudio em segundo plano funcionam. Dentro de um WebView esse controle some. A tela cheia precisa de uma view nativa feita à mão pelo host; a reprodução automática é bloqueada a menos que o host ative duas flags ocultas de configuração; e o áudio em segundo plano morre assim que o app vai para segundo plano. Um runtime próprio do host oferece uma ponte de mídia: uma superfície de reprodução previsível em todos os dispositivos.
O WebView não consegue ir para tela cheia sozinho
No Android, requestFullscreen() do HTML não faz nada para um <video> a menos que o WebChromeClient do app sobrescreva onShowCustomView() e onHideCustomView(). O WebView entrega a superfície do vídeo ao host e espera; se o host não implementa o callback, o botão de tela cheia simplesmente não funciona. O comportamento entre versões é pior: desde o Android 4.0 o callback recebe uma classe interna privada, então detectar o fim ou conectar controles próprios exige reflexão e ramificação por versão.
O iOS força tela cheia ou silêncio
No iOS, o WKWebView deixa allowsInlineMediaPlayback como false por padrão, então mesmo um vídeo playsinline é arrancado para o player do sistema no instante em que começa. A reprodução automática também é limitada: com o mediaTypesRequiringUserActionForPlayback padrão, um autoplay silenciado ainda precisa de um gesto, então o padrão "vídeo como banner" trava em silêncio. O Picture-in-Picture só funciona se o player inline já for um AVPlayerViewController — e não pode ser ativado automaticamente ao segundo plano, porque um visibilitychange não é interação do usuário.
O que quebra quando a mídia está pela metade
- A tela cheia é um botão morto. Toque no Android e nada acontece a menos que o host tenha ligado
onShowCustomView. - O vídeo inline pula para tela cheia. O iOS ignora
playsinlinea menos que o host tenha fixado a flag na configuração — mudar depois falha em silêncio. - A reprodução automática trava. Sem gesto, sem reprodução; a única saída são duas flags nativas ocultas.
- O áudio em segundo plano morre. Ao segundo plano, a mídia do WebView pausa; PiP é o único caminho e não é automático.
- Caos entre versões. A classe interna do Android e as flags do iOS mudam em cada build do SO.
A solução do runtime
Um runtime próprio do host controla a mídia. O host implementa a entrega de tela cheia nativamente, expõe uma API de reprodução uniforme à página, fixa as flags de inline e autoplay uma vez na configuração, e faz a ponte do áudio em segundo plano para a sessão de mídia do SO. Uma superfície de mídia, todos os dispositivos, todas as versões — em vez de uma página que funciona no telefone do engenheiro e quebra no do usuário.
| Dimensão | WebView | Runtime próprio do host |
|---|---|---|
| Tela cheia | Morta a menos que o host sobrescreva onShowCustomView | Entrega dirigida pelo host |
| Reprodução inline iOS | Ignora playsinline por padrão | Flag fixada na configuração |
| Autoplay | Bloqueado sem gesto | Política previsível |
| Áudio em segundo plano | Pausa ao segundo plano | Ponte para sessão de mídia do SO |
| Picture-in-Picture | Não automático | Controlado pelo host |
| Entre versões | Quebra por build | Estável |
Um app nativo nunca perde o controle de sua mídia. Um WebView comum frequentemente sim. Um runtime entrega à página um player previsível — e mantém o áudio vivo ao segundo plano.
Fontes
- Android Developers — WebChromeClient#onShowCustomView — o callback que o host deve implementar para vídeo em tela cheia.
- webkit.org — Novas políticas de vídeo para iOS — por que o WebKit limita
playsinlinee o autoplay. - Apple Developer Forums — PiP e reprodução em segundo plano no WKWebView — engenheiro DTS sobre a entrega inline para PiP e os limites de
visibilitychange. - MDN — Guia de reprodução automática — as regras de gesto e autoplay silenciado que todo motor aplica.
- Thomas Visser — Vídeo em autoplay no WKWebView — as duas flags do WKWebView que fazem o autoplay inline funcionar.