Simplifica la implementación de WebView con Jetpack Webkit

En esta guía, se describen los beneficios de la biblioteca de Jetpack Webkit, se explica cómo funciona y se indica cómo puedes implementarla en tus proyectos.

Descripción general

Los WebView son una parte esencial del desarrollo de Android, pero a veces pueden ser difíciles de administrar debido a las incoherencias en las funciones en las diferentes versiones del SO Android. Cada versión del SO Android proporciona un conjunto fijo de APIs de WebView. Debido a que Android se lanza con una cadencia más lenta que WebView, es posible que las APIs de Android no abarquen todas las funciones disponibles de WebView. Esto genera un lanzamiento de funciones más lento y mayores costos de pruebas.

Jetpack Webkit resuelve estos problemas actuando como una capa de compatibilidad y aprovechando el APK de WebView actualizado en el dispositivo del usuario. También contiene APIs nuevas y modernas que están disponibles exclusivamente en esta biblioteca.

¿Por qué usar Jetpack Webkit?

Además de ofrecer compatibilidad entre versiones, Jetpack Webkit también ofrece APIs nuevas y modernas que pueden simplificar el desarrollo y mejorar la funcionalidad de tu app:

  • Habilita la autenticación moderna: WebView puede controlar sin problemas los estándares de autenticación web modernos, como WebAuthn, lo que permite el acceso con llaves de acceso. La biblioteca de androidx.webkit te brinda control total sobre esta integración a través del método WebSettingsCompat.setWebAuthenticationSupport(), que puedes usar para configurar el nivel de compatibilidad que requiere tu app.

  • Mejora el rendimiento: Ajusta el rendimiento de WebView para los casos de uso de tu app con APIs como prefetchUrlAsync, prerenderUrlAsync y setBackForwardCacheEnabled.

  • Aumenta la estabilidad: Recupera los procesos del renderizador que se detuvieron o no responden sin que se produzca un bloqueo. Para obtener más información, consulta WebViewRenderProcess#terminate().

  • Ofrece un control detallado sobre los datos de navegación: Para borrar los datos de navegación que WebView almacena para orígenes específicos, usa la clase WebStorageCompat.

Comprende los componentes

Para usar Jetpack Webkit de manera eficaz, debes comprender la relación entre los siguientes componentes:

  • Android System WebView: Es el motor de renderización basado en Chromium que Google actualiza periódicamente a través de Google Play Store con la misma cadencia que Chrome. Contiene las funciones más actualizadas y proporciona el código de implementación subyacente para todas las APIs de WebView.

  • APIs de framework (android.webkit): Son las APIs que se fijan a una versión específica del SO Android. Por ejemplo, una app en Android 10 solo puede acceder a las APIs que estaban disponibles cuando se lanzó esa versión. Por lo tanto, no puede usar las funciones nuevas que se agregaron al APK de WebView en las actualizaciones más recientes. Por ejemplo, para obtener un identificador en un renderizador que no responde con WebView#getWebViewRenderProcess(), solo puedes llamar a este en Android 10 y versiones posteriores.

  • Biblioteca de Jetpack Webkit (androidx.webkit): Es una biblioteca pequeña incluida en tu aplicación. Esta biblioteca actúa como un puente que llama al APK de WebView, en lugar de llamar a las APIs definidas en la plataforma de Android, que tiene una versión de SO fija. De esta manera, incluso cuando una aplicación se instala en un dispositivo que ejecuta una versión anterior del SO, como Android 10, la aplicación puede usar las funciones más recientes de WebView. Por ejemplo, WebViewCompat.getWebViewRenderProcess() funciona de manera similar a la API de Framework, excepto que también se puede llamar en todas las versiones del SO anteriores a Android 10.

Si una API está disponible tanto en el framework como en Jetpack Webkit, te recomendamos que elijas la versión de Jetpack Webkit. Esto ayuda a garantizar un comportamiento y una compatibilidad coherentes en la mayor cantidad de dispositivos posible.

Interacción entre Jetpack Webkit y APK

Las APIs de Jetpack Webkit se implementan en dos partes:

  • Static Jetpack Webkit: La biblioteca estática de Jetpack Webkit contiene una minoría del código responsable de implementar la API.

  • APK de WebView: El APK de WebView contiene la mayor parte del código.

Tu app llama a la API de Jetpack Webkit, que luego llama al APK de WebView.

Si bien controlas la versión de Jetpack Webkit en tu app, no puedes controlar las actualizaciones del APK de WebView en los dispositivos de los usuarios. En general, la mayoría de los usuarios tienen versiones actualizadas del APK de WebView, pero tu app debe tener cuidado de no llamar a las APIs que esa versión en particular del APK de WebView no admite.

Jetpack Webkit también abstrae la necesidad de verificar las versiones de WebView de forma manual. Para determinar si una función está disponible, verifica su constante de función. Por ejemplo, WebViewFeature.WEB_AUTHENTICATION.

Cómo funcionan en conjunto

Jetpack Webkit une la brecha entre la API de Framework estática y el APK de WebView que se actualiza con frecuencia. Cuando usas la API de Jetpack Webkit con el patrón de detección de funciones, la biblioteca realiza una verificación para ver si el APK de WebView instalado en el dispositivo del usuario admite la función. Esto proporciona el beneficio de no tener que verificar la versión del SO (framework) de Android.

Si el APK de WebView tiene una versión lo suficientemente reciente, la biblioteca invoca la función. De lo contrario, informa que la función no está disponible, lo que evita que tu app falle y te permite controlar la situación de forma correcta.

Compara las APIs de Jetpack Webkit y Framework

En esta sección, se comparan los métodos de implementación con y sin la biblioteca de Jetpack Webkit:

Habilita la autenticación moderna (WebAuthn)

Sin Jetpack Webkit

No es posible a través de las APIs del framework.

Con Jetpack Webkit

Aprovecha WebViewFeature.WEB_AUTHENTICATION para las verificaciones de compatibilidad.

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

Cómo borrar datos de un origen (almacenamiento específico del sitio)

Sin Jetpack WebKit

No hay una API directa para borrar datos de orígenes específicos. A menudo, requiere borrar todos los datos.

Con Jetpack WebKit

Usa APIs de compatibilidad para borrar datos con precisión. Puedes usar cualquiera de las siguientes opciones:

WebStorageCompat.getInstance().deleteBrowsingData()

O

WebStorageCompat.getInstance().deleteBrowsingDataForSite()

Obtén la versión de WebView

Sin Jetpack WebKit

Usa la clase de framework estándar.

val webViewPackage = WebView.getCurrentWebViewPackage()

Con Jetpack WebKit

Usa la capa de compatibilidad para una recuperación más segura.

val webViewPackage = WebViewCompat.getCurrentWebViewPackage()

Cómo controlar el procesador que no responde (cliente del procesador)

Sin Jetpack WebKit

Usa el método estándar del framework.

webView.setWebViewRenderProcessClient(myClient)

Con Jetpack WebKit

Usa WebViewCompat y una verificación de funciones para configurar el cliente.

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

Para obtener más información, consulta la documentación de referencia de androidx.webkit.

Integra Jetpack Webkit en tu código

El uso de Jetpack Webkit aumenta las capacidades de la clase WebView estándar, pero no reemplaza por completo la clase WebView original.

Puedes seguir usando la clase android.webkit.WebView. Puedes agregarlo a tus diseños XML y obtener una referencia a la instancia en tu código. Para acceder a las funciones estándar del framework, puedes seguir llamando a los métodos directamente en la instancia de WebView o en su objeto de configuración.

Para acceder a las funciones modernas, usa los métodos auxiliares estáticos que proporciona Jetpack Webkit, como WebViewCompat y WebSettingsCompat. Pasas tu instancia de WebView existente a estos 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);
}

Implementa Jetpack Webkit

Para implementar Jetpack Webkit, usa el siguiente procedimiento.

Paso 1: Agrega la dependencia

En el archivo build.gradle.kts o build.gradle de tu módulo, incluye la siguiente dependencia para agregar Jetpack Webkit:

Groovy

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

Kotlin

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

Jetpack Webkit contiene wrappers delgados, por lo que el impacto en el tamaño de tu aplicación es mínimo.

Paso 2: Adopta el patrón de detección de funciones

Para evitar fallas cuando se invocan APIs no disponibles, usa verificaciones de funciones. Recomendamos incluir cada invocación de API en una verificación de funciones y, posiblemente, considerar una lógica de resguardo para cuando la API no esté disponible.

Recomendamos el siguiente patrón para usar una API de WebView moderna:

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

// In your Kotlin code where you configure your WebView
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.
}

Este patrón ayuda a garantizar que la aplicación sea sólida. Dado que la verificación de funciones se ejecuta primero, la aplicación no falla si la función no está disponible. La sobrecarga de rendimiento de la verificación de WebViewFeature#isFeatureSupported() es insignificante.