Simplifique a implementação do WebView com o Jetpack Webkit

Este guia descreve os benefícios da biblioteca Jetpack Webkit, explica como ela funciona e como você pode implementá-la nos seus projetos.

Visão geral

As WebViews são uma parte essencial do desenvolvimento do Android, mas às vezes podem ser difíceis de gerenciar devido a inconsistências nos recursos em diferentes versões do SO Android. Cada versão do SO Android fornece um conjunto fixo de APIs WebView. Como o Android é lançado em uma cadência mais lenta do que a WebView, as APIs do Android podem não abranger todos os recursos disponíveis da WebView. Isso leva a uma implantação mais lenta de recursos e a custos de teste maiores.

O Jetpack Webkit resolve esses problemas atuando como uma camada de compatibilidade e aproveitando o APK da WebView atualizado no dispositivo do usuário. Ele também contém APIs novas e modernas que estão disponíveis exclusivamente nessa biblioteca.

Por que usar o Jetpack Webkit?

Além de oferecer compatibilidade entre versões, o Jetpack Webkit também oferece APIs novas e modernas que podem simplificar o desenvolvimento e melhorar a funcionalidade do seu app:

  • Permite a autenticação moderna: a WebView pode processar perfeitamente padrões modernos de autenticação na Web , como o WebAuthn, permitindo logins baseados em chaves de acesso. A biblioteca androidx.webkit oferece controle total sobre essa integração usando o método WebSettingsCompat.setWebAuthenticationSupport, que pode ser usado para configurar o nível de suporte necessário para seu app.

  • Melhora a performance: ajuste a performance da WebView usando APIs como setBackForwardCacheEnabled ou reduza a latência de navegação usando APIs de carregamento especulativo, como prefetchUrlAsync e prerenderUrlAsync. Para mais informações, consulte Carregamento especulativo na WebView.

  • Aumenta a estabilidade: recupere processos de renderização paralisados ou sem resposta sem falhas. Para mais informações, consulte WebViewRenderProcess#terminate.

  • Oferece controle granular sobre os dados de navegação: para excluir dados de navegação armazenados pela WebView para origens específicas, use a classe WebStorageCompat.

  • Fornece navegação nas páginas aprimorada: substitua WebView.loadUrl por WebViewCompat.navigate para controle de navegação refinado, substituição de entrada de histórico , suporte a cabeçalho de estado salvo e rastreamento de ciclo de vida correlacionado usando NavigationListener. Para mais informações, consulte Navegação aprimorada na página com WebViewCompat.navigate.

  • Otimiza o gerenciamento de estado: proteja contra TransactionTooLargeException definindo limites máximos de bytes durante a serialização de estado. Para mais informações, consulte Gerenciar o estado da WebView de maneira eficiente.

Noções básicas sobre os componentes

Para usar o Jetpack Webkit de maneira eficaz, você precisa entender a relação entre os seguintes componentes:

  • WebView do sistema Android: é o mecanismo de renderização baseado no Chromium que o Google atualiza regularmente pela Google Play Store na mesma cadência do Chrome. Ele contém os recursos mais atualizados e fornece o código de implementação subjacente para todas as APIs WebView.

  • APIs do framework (android.webkit): são as APIs fixadas em uma versão específica do SO Android. Por exemplo, um app no Android 10 só pode acessar as APIs que estavam disponíveis quando essa versão foi lançada. Portanto, ele não pode usar novos recursos adicionados ao APK da WebView em atualizações mais recentes. Por exemplo, para controlar um renderizador sem resposta com WebView#getWebViewRenderProcess(), só é possível chamar isso no Android 10 e versões mais recentes.

  • Biblioteca Jetpack Webkit (androidx.webkit): é uma pequena biblioteca agrupada no seu aplicativo. Essa biblioteca atua como uma ponte que chama o APK da WebView, em vez de chamar as APIs definidas na plataforma Android, que tem uma versão fixa do SO. Dessa forma, mesmo quando um aplicativo é instalado em um dispositivo que executa uma versão mais antiga do SO, como o Android 10, o aplicativo pode usar os recursos mais recentes da WebView. Por exemplo, WebViewCompat.getWebViewRenderProcess() funciona de maneira semelhante à API do framework, mas também pode ser chamado em todas as versões do SO anteriores ao Android 10.

Se uma API estiver disponível no framework e no Jetpack Webkit, recomendamos que você escolha a versão do Jetpack Webkit. Isso ajuda a garantir um comportamento e uma compatibilidade consistentes na maior variedade de dispositivos.

Interação do Jetpack Webkit e do APK

As APIs no Jetpack Webkit são implementadas em duas partes:

  • Jetpack Webkit estático: a biblioteca estática do Jetpack Webkit contém uma minoria do código responsável pela implementação da API.

  • APK da WebView: o APK da WebView contém a maior parte do código.

Seu app chama a API Jetpack Webkit, que então chama o APK da WebView.

Embora você controle a versão do Jetpack Webkit no seu app, não é possível controlar as atualizações do APK da WebView nos dispositivos dos usuários. Geralmente, a maioria dos usuários tem versões atualizadas do APK da WebView, mas seu app ainda precisa ter cuidado para não chamar APIs que essa versão específica do APK da WebView não oferece suporte.

O Jetpack Webkit também abstrai a necessidade de verificar manualmente as versões da WebView. Para determinar se um recurso está disponível, verifique a constante dele. Por exemplo, WebViewFeature.WEB_AUTHENTICATION.

Como eles funcionam juntos

O Jetpack Webkit preenche a lacuna entre a API do framework estático e o APK da WebView atualizado com frequência. Ao usar a API Jetpack Webkit com o padrão de detecção de recursos, a biblioteca realiza uma verificação para saber se o recurso é compatível com o APK da WebView instalado no dispositivo do usuário. Isso oferece o benefício de não precisar verificar a versão do SO Android (framework).

Se o APK da WebView for uma versão recente, a biblioteca vai invocar o recurso. Caso contrário, ele informa que o recurso não está disponível, impedindo que o app falhe e permitindo que você lide com a situação de maneira adequada.

Comparar as APIs do Jetpack Webkit e do framework

Esta seção compara métodos de implementação com e sem a biblioteca Jetpack Webkit:

Ativar a autenticação moderna (WebAuthn)

Sem o Jetpack Webkit

Não é possível usar APIs do framework.

Com o Jetpack Webkit

Aproveita WebViewFeature.WEB_AUTHENTICATION para verificações de compatibilidade.

if (WebViewFeature.isFeatureSupported(WebViewFeature.WEB_AUTHENTICATION)) {
  WebSettingsCompat.setWebAuthenticationSupport(
      webView.settings,
      WebSettingsCompat.WEB_AUTHENTICATION_SUPPORT_FOR_APP
  )
}

Excluir dados de uma origem (armazenamento específico do site)

Sem o Jetpack Webkit

Não há API direta para limpar dados de origem específicos. Muitas vezes, é necessário limpar todos os dados.

Com o Jetpack Webkit

Usa APIs de compatibilidade para exclusão precisa de dados. Você pode usar uma das seguintes opções:

WebStorageCompat.getInstance().deleteBrowsingData()

Ou

WebStorageCompat.getInstance().deleteBrowsingDataForSite()

Receber a versão da WebView

Sem o Jetpack Webkit

Usa a classe de framework padrão.

val webViewPackage = WebView.getCurrentWebViewPackage()

Com o Jetpack Webkit

Usa a camada de compatibilidade para uma recuperação mais segura.

val webViewPackage = WebViewCompat.getCurrentWebViewPackage()

Processar renderizador sem resposta (cliente de renderizador)

Sem o Jetpack Webkit

Usa o método de framework padrão.

webView.setWebViewRenderProcessClient(myClient)

Com o Jetpack Webkit

Usa WebViewCompat e uma verificação de recursos para definir o cliente.

if (WebViewFeature.isFeatureSupported(WebViewFeature.WEB_VIEW_RENDERER_CLIENT_BASIC_USAGE)) {
  WebViewCompat.setWebViewRenderProcessClient(webView, myClient)
}

Para orientações sobre como implementar estratégias de recuperação de falhas, consulte Processar a finalização da WebView. Para detalhes da API, consulte a androidx.webkit documentação de referência.

Gerenciar o estado salvo e o tamanho da transação

A API WebViewCompat.saveState permite aplicar limites de bytes e remover o histórico de encaminhamento durante a serialização, evitando falhas de TransactionTooLargeException e preservando o histórico de navegação essencial.

Sem o Jetpack Webkit

Usa o método de framework padrão, que serializa toda a pilha de navegação sem limites de tamanho e pode acionar TransactionTooLargeException se o payload exceder o limite de transação de 1 MB do Android.

webView.saveState(outState)

Com o Jetpack Webkit

Usa WebViewCompat para aplicar um limite máximo de bytes ou descartar entradas de navegação de encaminhamento, protegendo contra estouros de transação.

WebViewCompat.saveState(webView, outState, maxSizeBytes)

Para mais informações, consulte Gerenciar o estado da WebView de maneira eficiente.

Para navegar em páginas da Web com suporte à substituição de entrada de histórico, suporte a cabeçalho de estado salvo e callbacks de ciclo de vida correlacionados, use WebViewCompat.navigate em vez de WebView.loadUrl.

Sem o Jetpack Webkit

Usa WebView.loadUrl, que não oferece suporte à substituição de entrada de histórico ou ao rastreamento de callback de ciclo de vida correlacionado.

webView.loadUrl("https://www.example.com")

Com o Jetpack Webkit

Usa WebViewCompat.navigate com NavigationParameters para substituir entradas de histórico, preservar cabeçalhos personalizados no estado salvo e rastrear estados de navegação.

if (WebViewFeature.isFeatureSupported(WebViewFeature.WEBVIEW_NAVIGATE_EXPERIMENTAL_V1)) {
  val params = NavigationParameters.Builder()
      .setShouldReplaceCurrentEntry(true)
      .build()
  val navigation = WebViewCompat.navigate(webView, "https://www.example.com", params)
} else {
  webView.loadUrl("https://www.example.com")
}

Para mais informações sobre o rastreamento de navegação e a configuração de parâmetros, consulte Navegação aprimorada na página com WebViewCompat.navigate.

Integrar o Jetpack Webkit ao seu código

O uso do Jetpack Webkit aumenta os recursos da classe WebView padrão, mas não substitui totalmente a classe WebView original.

Você pode continuar usando a android.webkit.WebView classe. É possível adicioná-la aos layouts XML e receber uma referência à instância no seu código. Para acessar recursos de framework padrão, ainda é possível chamar métodos diretamente na instância da WebView ou no objeto de configurações.

Para acessar recursos modernos, use os métodos auxiliares estáticos fornecidos pelo Jetpack Webkit, como WebViewCompat e WebSettingsCompat. Transmita a instância da WebView atual para esses métodos.

Kotlin

import android.webkit.WebView
import androidx.webkit.WebSettingsCompat
import androidx.webkit.WebViewFeature

// You still get your WebView instance the standard way.
val webView: WebView = findViewById(R.id.my_webview)

// To enable a modern feature, you pass that instance to a Jetpack Webkit helper.
if (WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK)) {
    WebSettingsCompat.setForceDark(webView.settings, WebSettingsCompat.FORCE_DARK_ON)
}

Java

import android.webkit.WebView;
import androidx.webkit.WebSettingsCompat;
import androidx.webkit.WebViewFeature;

// You still get your WebView instance the standard way.
WebView webView = findViewById(R.id.my_webview);

// To enable a modern feature, you pass that instance to a Jetpack Webkit helper.
if (WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK)) {
    WebSettingsCompat.setForceDark(webView.settings, WebSettingsCompat.FORCE_DARK_ON);
}

Implementar o Jetpack Webkit

Para implementar o Jetpack Webkit, use o procedimento a seguir.

Etapa 1: adicionar a dependência

No arquivo build.gradle.kts ou build.gradle do módulo, inclua a seguinte dependência para adicionar o Jetpack Webkit:

Groovy

dependencies {
    implementation "androidx.webkit:webkit:1.16.0"
}

Kotlin

dependencies {
    implementation("androidx.webkit:webkit:1.16.0")
}

O Jetpack Webkit contém wrappers finos, então o impacto no tamanho do aplicativo é mínimo.

Etapa 2: adotar o padrão de detecção de recursos

Para evitar falhas ao invocar APIs indisponíveis, use verificações de recursos. Recomendamos envolver cada invocação de API com uma verificação de recursos e, possivelmente, considerar a lógica de fallback para quando a API não estiver disponível.

Recomendamos o seguinte padrão para usar uma API WebView moderna:

Kotlin

import android.webkit.WebView
import androidx.webkit.WebSettingsCompat
import androidx.webkit.WebViewFeature

val webView: WebView = findViewById(R.id.my_webview)

// Before you use a modern API, first check if it is supported.
if (WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK)) {
    // If the check passes, it is safe to call the API.
    WebSettingsCompat.setForceDark(webView.settings, WebSettingsCompat.FORCE_DARK_ON)
} else {
    // Optionally, provide a fallback for older WebView versions.
}

Java

import android.webkit.WebView;
import androidx.webkit.WebSettingsCompat;
import androidx.webkit.WebViewFeature;

WebView webView = findViewById(R.id.my_webview);

// Before you use a modern API, first check if it is supported.
if (WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK)) {
    // If the check passes, it is safe to call the API.
    WebSettingsCompat.setForceDark(webView.getSettings(), WebSettingsCompat.FORCE_DARK_ON);
} else {
    // Optionally, provide a fallback for older WebView versions.
}

Esse padrão ajuda a garantir que o aplicativo seja robusto. Como a verificação de recursos é executada primeiro, o aplicativo não falha se o recurso não estiver disponível. A sobrecarga de performance da WebViewFeature#isFeatureSupported verificação é insignificante.