WhatsApp - Contornando problemas com o WebView

Problema

Quando um usuário abre um Link enviado através da API oficial do WhatsApp em um aparelho Android, os seguintes problema são apresentados:

  1. Popups nativos do sistema operacional, que deveriam ser abertos em elementos de entrada de dados (<input>), como calendário, seletor de hora e seletor de cores não funcionam, impedindo o preenchimento destes campos.

  2. Não há suporte para captura de fotos diretamente da câmera em elementos de upload (< input type="file">). Ao invés de abrir a câmera, ele abre a galeria do celular.

Este não é um problema que ocorre exclusivamente com o Latromi, mas sim com qualquer página HTML, como pode ser observado nessa simulação:

Causa

Em Outubro de 2025, a Meta mudou a forma como links são abertos em mensagens automatizadas recebidas pelo WhatsApp, enviadas através da API oficial. Ao invés da página ser aberta no navegador do usuário, ela é aberta em um navegador embarcado no WhatsApp, uma componente conhecido como WebView.

O objetivo da implementação do WebView, é trazer mais segurança para os usuários, uma vez que a Meta passa a ter mais controle sobre o quê a página pode fazer, mitigando golpes e ataques cibernéticos.

No entanto, a implementação do WebView da Meta para o Android, apresenta estes problemas.

No iPhone o problema não acontece, porque ele só aceita o WebView produzido pela própria Apple, e que tem total suporte à comunicação com o sistema operacional. Já no caso do Android, ao que tudo indica, a Meta criou o seu próprio WebView para manter compatibilidade com aparelhos mais antigos.

Solução

Por enquanto, a única solução para contornar este problema, é instruir o usuário a abrir a página no navegador, seguindo as instruções oficiais WhatsApp

Mas como sabemos que não é fácil comunicar isso aos usuários, criamos um código JavaScript que faz o seguinte:

  1. Identifica que o acesso está sendo feito através de um componente WebView do WhatsApp para Android.

  2. Se sim, cobre a página com um elemento que contém instruções para o usuário abrir a página no navegador.

Este código pode ser usado no JavaScript Público e cobrir todos os Formulários ou ser carregado apenas nos Formulários onde for necessário fazer este tratamento:

(function () {

    // Adiciona Callbacks no Formulário
    latromi.formManager.setOnFormCreatedCallback(onFormCreated);
    latromi.formManager.setOnEventFiringCallback(onEventFiring);
    latromi.formManager.setOnFieldValueChangedCallback(onFieldValueChanged);

    // Ocorre logo após o form ser inicializado
    function onFormCreated(ev) {
        // Se a página foi carregada no WebView desenvolvido pela meta para o Android, 
        // obriga o usuário a abrir a página no navegador. Isso foi necessário para
        // manter o funcionamento adequado dos componentes input que usam a interface
        // do aparelho (date, datetime-local, etc) e também para permitir que o campo 
        // de upload abra diretamente a camera. No Apple, este problema não ocorre.
        const ua = navigator.userAgent || "";
        if (ua.includes('WA4A')) {
            createInstruction();
        }
        
    }

    // Ocorre quando um evento é disparado no Form
    function onEventFiring(ev) { }

    // Ocorre quando o valor de um campo é alterado no Form
    function onFieldValueChanged(ev) { }
    
    function createInstruction() {
        const instructionElement = document.createElement('div');
        instructionElement.style.margin = '1.25rem';
        instructionElement.innerHTML = `
        <h2 style="font-weight: 700; font-size:1.25rem">Ação Necessária</h2>
        <p>Para continuar, você precisa abrir essa página <strong>fora do WhatsApp</strong>. Siga estas etapas:</p>
        <ol>
            <li style="margin-bottom:0.5rem">Toque no ícone <i class="fa fa-ellipsis-v" aria-hidden="true"></i> no canto superior direito da tela.</li>
            <li style="margin-bottom:0.5rem">Em seguida, toque em <strong>Abrir no navegador</strong></li>
        <ol>
        `;
               
        const instructionContainer = document.createElement('div');
        instructionContainer.style.position = 'absolute';
        instructionContainer.style.top = 0;
        instructionContainer.style.left = 0;
        instructionContainer.style.right = 0;
        instructionContainer.style.bottom = 0;
        instructionContainer.style.backgroundColor = 'White';
        instructionContainer.appendChild(instructionElement);
        
        // Adiciona a seta
        instructionElement.style.marginRight = '4rem';
        instructionContainer.style.backgroundColor = 'White';
        instructionContainer.appendChild(instructionElement);
        instructionContainer.style.backgroundPositionX = 'right';
        instructionContainer.style.backgroundPositionY = '20px';
        instructionContainer.style.backgroundRepeat = 'no-repeat';
        instructionContainer.style.backgroundImage = "url('data:image/png;base64,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MIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMIBMMAAAAAAAAAAAAABG9V9kCbwRK7b0uAAAAABJRU5ErkJggg==')";
        instructionContainer.style.backgroundSize = '3.75rem';
        
        // Adiciona instruções na página
        document.body.appendChild(instructionContainer);
    }

    // Todas as funções acima são "privadas", e não podem ser chamadas externamente.
    // As únicas funções que podem ser chamadas externamente são as que compões o resultado a seguir:
    return {
        test: function() { }
    }
})();

O resultado será este:

1 curtida