Semplifica l'implementazione di WebView con Jetpack Webkit

Questa guida descrive i vantaggi della libreria Jetpack Webkit, spiega come funziona e come puoi implementarla nei tuoi progetti.

Panoramica

Le WebView sono una parte essenziale dello sviluppo di Android, ma a volte possono essere difficili da gestire a causa delle incoerenze nelle funzionalità tra le diverse versioni del sistema operativo Android. Ogni versione del sistema operativo Android fornisce un insieme fisso di API WebView. Poiché Android viene rilasciato con una frequenza inferiore rispetto a WebView, le API Android potrebbero non coprire tutte le funzionalità WebView disponibili. Ciò comporta un rilascio più lento delle funzionalità e un aumento dei costi di test.

Jetpack Webkit risolve questi problemi fungendo da livello di compatibilità e sfruttando l'APK WebView aggiornato sul dispositivo dell'utente. Contiene anche API nuove e moderne disponibili esclusivamente in questa libreria.

Perché usare Jetpack Webkit?

Oltre a offrire la compatibilità tra le versioni, Jetpack Webkit offre anche API nuove e moderne che possono semplificare lo sviluppo e migliorare la funzionalità della tua app:

  • Abilita l'autenticazione moderna: WebView può gestire senza problemi gli standard di autenticazione web moderni come WebAuthn, consentendo gli accessi basati su passkey. La libreria androidx.webkit ti offre il controllo completo di questa integrazione utilizzando il metodo WebSettingsCompat.setWebAuthenticationSupport, che puoi utilizzare per configurare il livello di supporto richiesto dalla tua app.

  • Migliora le prestazioni: ottimizza le prestazioni di WebView utilizzando API come setBackForwardCacheEnabled o riduci la latenza di navigazione utilizzando API di caricamento speculativo come prefetchUrlAsync e prerenderUrlAsync. Per ulteriori informazioni, vedi Caricamento speculativo in WebView.

  • Aumenta la stabilità: recupera i processi di rendering bloccati o che non rispondono senza causare arresti anomali. Per ulteriori informazioni, vedi WebViewRenderProcess#terminate.

  • Offre un controllo granulare sui dati di navigazione: per eliminare i dati di navigazione archiviati da WebView per origini specifiche, utilizza la classe WebStorageCompat.

  • Fornisce una navigazione delle pagine migliorata: sostituisci WebView.loadUrl con WebViewCompat.navigate per un controllo granulare della navigazione, la sostituzione delle voci della cronologia , il supporto dell'intestazione dello stato salvato e il monitoraggio del ciclo di vita correlato utilizzando NavigationListener. Per ulteriori informazioni, vedi Navigazione delle pagine migliorata con WebViewCompat.navigate.

  • Ottimizza la gestione dello stato: proteggi da TransactionTooLargeException impostando limiti massimi di byte durante la serializzazione dello stato. Per ulteriori informazioni, vedi Gestire in modo efficiente lo stato di WebView.

Informazioni sui componenti

Per utilizzare Jetpack Webkit in modo efficace, devi comprendere la relazione tra i seguenti componenti:

  • Android System WebView: si tratta del motore di rendering basato su Chromium che Google aggiorna regolarmente tramite il Google Play Store con la stessa frequenza di Chrome. Contiene le funzionalità più aggiornate e fornisce il codice di implementazione sottostante per tutte le API WebView.

  • API del framework (android.webkit): si tratta delle API fisse a una versione specifica del sistema operativo Android. Ad esempio, un'app su Android 10 può accedere solo alle API disponibili al momento del rilascio di questa versione. Pertanto, non può utilizzare le nuove funzionalità aggiunte all'APK WebView negli aggiornamenti più recenti. Ad esempio, per gestire un renderer che non risponde con WebView#getWebViewRenderProcess(), puoi chiamare questa API solo su Android 10 e versioni successive.

  • Libreria Jetpack Webkit (androidx.webkit): si tratta di una piccola libreria inclusa nell'applicazione. Questa libreria funge da ponte che chiama l'APK WebView, anziché le API definite nella piattaforma Android, che ha una versione del sistema operativo fissa. In questo modo, anche quando un'applicazione è installata su un dispositivo che esegue una versione precedente del sistema operativo, come Android 10, l'applicazione può utilizzare le funzionalità WebView più recenti. Ad esempio, WebViewCompat.getWebViewRenderProcess() funziona in modo simile all'API del framework, ma può essere chiamata anche su tutte le versioni del sistema operativo precedenti ad Android 10.

Se un'API è disponibile sia nel framework sia in Jetpack Webkit, ti consigliamo di scegliere la versione Jetpack Webkit. In questo modo, il comportamento e la compatibilità sono coerenti nella più ampia gamma di dispositivi.

Interazione tra Jetpack Webkit e APK

Le API in Jetpack Webkit sono implementate in due parti:

  • Jetpack Webkit statico: la libreria Jetpack Webkit statica contiene una minoranza del codice responsabile dell'implementazione dell'API.

  • APK WebView: l'APK WebView contiene la maggior parte del codice.

L'app chiama l'API Jetpack Webkit, che a sua volta chiama l'APK WebView.

Anche se controlli la versione di Jetpack Webkit nella tua app, non puoi controllare gli aggiornamenti dell'APK WebView sui dispositivi degli utenti. In genere, la maggior parte degli utenti ha versioni aggiornate dell'APK WebView, ma la tua app deve comunque fare attenzione a non chiamare le API non supportate da quella versione specifica dell'APK WebView.

Jetpack Webkit elimina anche la necessità di controllare manualmente le versioni di WebView. Per determinare se una funzionalità è disponibile, controlla la relativa costante della funzionalità. Ad esempio, WebViewFeature.WEB_AUTHENTICATION.

Come funzionano insieme

Jetpack Webkit colma il divario tra l'API del framework statico e l'APK WebView aggiornato di frequente. Quando utilizzi l'API Jetpack Webkit con il pattern di rilevamento delle funzionalità, la libreria esegue un controllo per verificare se la funzionalità è supportata dall'APK WebView installato sul dispositivo dell'utente. In questo modo, non è necessario controllare la versione del sistema operativo Android (framework).

Se l'APK WebView è una versione sufficientemente recente, la libreria richiama la funzionalità. In caso contrario, segnala che la funzionalità non è disponibile, impedendo l'arresto anomalo dell'app e consentendoti di gestire la situazione in modo appropriato.

Confrontare le API Jetpack Webkit e del framework

Questa sezione confronta i metodi di implementazione con e senza la libreria Jetpack Webkit:

Abilitare l'autenticazione moderna (WebAuthn)

Senza Jetpack Webkit

Non è possibile tramite le API del framework.

Con Jetpack Webkit

Sfrutta WebViewFeature.WEB_AUTHENTICATION per i controlli di compatibilità.

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

Eliminare i dati per un'origine (spazio di archiviazione specifico del sito)

Senza Jetpack Webkit

Nessuna API diretta per cancellare i dati di un'origine specifica. Spesso è necessario cancellare tutti i dati.

Con Jetpack Webkit

Utilizza le API di compatibilità per l'eliminazione precisa dei dati. Puoi utilizzare una delle seguenti opzioni:

WebStorageCompat.getInstance().deleteBrowsingData()

O

WebStorageCompat.getInstance().deleteBrowsingDataForSite()

Recuperare la versione di WebView

Senza Jetpack Webkit

Utilizza la classe del framework standard.

val webViewPackage = WebView.getCurrentWebViewPackage()

Con Jetpack Webkit

Utilizza il livello di compatibilità per un recupero più sicuro.

val webViewPackage = WebViewCompat.getCurrentWebViewPackage()

Gestire il renderer che non risponde (client del renderer)

Senza Jetpack Webkit

Utilizza il metodo del framework standard.

webView.setWebViewRenderProcessClient(myClient)

Con Jetpack Webkit

Utilizza WebViewCompat e un controllo delle funzionalità per impostare il client.

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

Per indicazioni sull'implementazione delle strategie di ripristino in caso di arresto anomalo, vedi Gestire la terminazione di WebView. Per i dettagli dell'API, consulta la documentazione di riferimento di androidx.webkit.

Gestire lo stato salvato e le dimensioni delle transazioni

L'API WebViewCompat.saveState consente di applicare limiti di byte e di eliminare la cronologia in avanti durante la serializzazione, impedendo gli arresti anomali di TransactionTooLargeException e mantenendo la cronologia di navigazione essenziale.

Senza Jetpack Webkit

Utilizza il metodo del framework standard, che serializza l'intero stack di navigazione senza limiti di dimensioni e può attivare TransactionTooLargeException se il payload supera il limite di transazione di 1 MB di Android.

webView.saveState(outState)

Con Jetpack Webkit

Utilizza WebViewCompat per applicare un limite massimo di byte o eliminare le voci di navigazione in avanti, proteggendo da overflow delle transazioni.

WebViewCompat.saveState(webView, outState, maxSizeBytes)

Per ulteriori informazioni, vedi Gestire in modo efficiente lo stato di WebView.

Per navigare tra le pagine web con il supporto per la sostituzione delle voci della cronologia, il supporto dell'intestazione dello stato salvato e i callback del ciclo di vita correlati, utilizza WebViewCompat.navigate anziché WebView.loadUrl.

Senza Jetpack Webkit

Utilizza WebView.loadUrl, che non supporta la sostituzione delle voci della cronologia o il monitoraggio dei callback del ciclo di vita correlati.

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

Con Jetpack Webkit

Utilizza WebViewCompat.navigate con NavigationParameters per sostituire le voci della cronologia, conservare le intestazioni personalizzate nello stato salvato e monitorare gli stati di navigazione.

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")
}

Per ulteriori informazioni sul monitoraggio della navigazione e sulla configurazione dei parametri, vedi Navigazione delle pagine migliorata con WebViewCompat.navigate.

Integrare Jetpack Webkit nel codice

L'utilizzo di Jetpack Webkit aumenta le funzionalità della classe WebView standard, ma non sostituisce completamente la classe WebView originale.

Puoi continuare a utilizzare la android.webkit.WebView classe. Puoi aggiungerla ai layout XML e ottenere un riferimento all'istanza nel codice. Per accedere alle funzionalità del framework standard, puoi comunque chiamare i metodi direttamente sull'istanza WebView o sul relativo oggetto delle impostazioni.

Per accedere alle funzionalità moderne, utilizza i metodi helper statici forniti da Jetpack Webkit, come WebViewCompat e WebSettingsCompat. Passa l'istanza WebView esistente a questi metodi.

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);
}

Implementare Jetpack Webkit

Per implementare Jetpack Webkit, segui questa procedura.

Passaggio 1: aggiungi la dipendenza

Nel file build.gradle.kts o build.gradle del modulo, includi la seguente dipendenza per aggiungere Jetpack Webkit:

Alla moda

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

Kotlin

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

Jetpack Webkit contiene wrapper sottili, quindi l'impatto sulle dimensioni dell'applicazione è minimo.

Passaggio 2: adotta il pattern di rilevamento delle funzionalità

Per evitare arresti anomali durante la chiamata delle API non disponibili, utilizza i controlli delle funzionalità. Ti consigliamo di racchiudere ogni chiamata API con un controllo delle funzionalità e di prendere in considerazione una logica di fallback per quando l'API non è disponibile.

Ti consigliamo di utilizzare il seguente pattern per utilizzare un'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.
}

Questo pattern contribuisce a garantire la robustezza dell'applicazione. Poiché il controllo delle funzionalità viene eseguito per primo, l'applicazione non si arresta in modo anomalo se la funzionalità non è disponibile. Il sovraccarico delle prestazioni del WebViewFeature#isFeatureSupported controllo è trascurabile.