Gestisci oggetti WebView

Android mette a disposizione diverse API per aiutarti a gestire WebView oggetti che mostrano contenuti web nella tua app.

In questa pagina viene descritto come utilizzare queste API per lavorare con WebView oggetti in modo più efficace, migliorando stabilità e sicurezza dell'app.

API Version

A partire da Android 7.0 (livello API 24), gli utenti possono scegliere tra diverse diversi pacchetti per la visualizzazione di contenuti web in un oggetto WebView. L'app AndroidX.webkit include getCurrentWebViewPackage() per recuperare le informazioni relative al pacchetto che mostra contenuti nella tua app. Questo metodo è utile per analizzare errori che si verificano solo quando la tua app tenta di visualizzare contenuti web utilizzando il metodo implementazione di WebView.

Per utilizzare questo metodo, aggiungi la logica mostrata nel seguente snippet di codice:

Kotlin

val webViewPackageInfo = WebViewCompat.getCurrentWebViewPackage(appContext)
Log.d("MY_APP_TAG", "WebView version: ${webViewPackageInfo.versionName}")

Java

PackageInfo webViewPackageInfo = WebViewCompat.getCurrentWebViewPackage(appContext);
Log.d("MY_APP_TAG", "WebView version: " + webViewPackageInfo.versionName);

Servizio Google Navigazione sicura

Per offrire ai tuoi utenti un'esperienza di navigazione più sicura, WebView per verificare gli URL utilizzando Google Navigazione sicura, che consente alla tua app di mostrare un avviso agli utenti quando tentano di accedere a un sito web potenzialmente non sicuro.

Sebbene il valore predefinito di EnableSafeBrowsing sia true, potresti voler attivare Navigazione sicura solo in modo condizionale disabilitarlo. Android 8.0 (livello API 26) e versioni successive supporta l'utilizzo di setSafeBrowsingEnabled() per attivare/disattivare Navigazione sicura per un singolo oggetto WebView.

Se vuoi disattivare Navigazione sicura per tutti gli oggetti WebView controlli, aggiungi il seguente elemento <meta-data> al file manifest:

<manifest>
    <application>
        <meta-data android:name="android.webkit.WebView.EnableSafeBrowsing"
                   android:value="false" />
        ...
    </application>
</manifest>

Definisci le azioni di pubblicità programmatica

Quando un'istanza di WebView tenta di caricare una pagina che classificata da Google come minaccia nota, WebView per impostazione predefinita mostra un interstitial che avvisa gli utenti della minaccia nota. Questa schermata fornisce agli utenti la possibilità di caricare comunque l'URL o di tornare a una pagina precedente in tutta sicurezza.

Se scegli come target Android 8.1 (livello API 27) o versioni successive, puoi definire in modo programmatico il modo in cui la tua app risponde a una minaccia nota nei seguenti modi:

  • Puoi controllare se la tua app segnala minacce note a Safe Navigazione.
  • Puoi impostare la tua app in modo che esegua automaticamente una determinata azione, ad esempio come tornare in un luogo sicuro, ogni volta che rileva un URL classificata come minaccia nota.
di Gemini Advanced.

I seguenti snippet di codice mostrano come indicare alle istanze dell'app WebView per tornare sempre in sicurezza dopo aver riscontrato un minaccia:

MiaWebActivity.java

Kotlin

private lateinit var superSafeWebView: WebView
private var safeBrowsingIsInitialized: Boolean = false

// ...

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    superSafeWebView = WebView(this)
    superSafeWebView.webViewClient = MyWebViewClient()
    safeBrowsingIsInitialized = false

    if (WebViewFeature.isFeatureSupported(WebViewFeature.START_SAFE_BROWSING)) {
        WebViewCompat.startSafeBrowsing(this, ValueCallback<Boolean> { success ->
            safeBrowsingIsInitialized = true
            if (!success) {
                Log.e("MY_APP_TAG", "Unable to initialize Safe Browsing!")
            }
        })
    }
}

Java

private WebView superSafeWebView;
private boolean safeBrowsingIsInitialized;

// ...

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    superSafeWebView = new WebView(this);
    superSafeWebView.setWebViewClient(new MyWebViewClient());
    safeBrowsingIsInitialized = false;

    if (WebViewFeature.isFeatureSupported(WebViewFeature.START_SAFE_BROWSING)) {
        WebViewCompat.startSafeBrowsing(this, new ValueCallback<Boolean>() {
            @Override
            public void onReceiveValue(Boolean success) {
                safeBrowsingIsInitialized = true;
                if (!success) {
                    Log.e("MY_APP_TAG", "Unable to initialize Safe Browsing!");
                }
            }
        });
    }
}

MyWebViewClient.java

Kotlin

class MyWebViewClient : WebViewClientCompat() {
    // Automatically go "back to safety" when attempting to load a website that
    // Google identifies as a known threat. An instance of WebView calls this
    // method only after Safe Browsing is initialized, so there's no conditional
    // logic needed here.
    override fun onSafeBrowsingHit(
            view: WebView,
            request: WebResourceRequest,
            threatType: Int,
            callback: SafeBrowsingResponseCompat
    ) {
        // The "true" argument indicates that your app reports incidents like
        // this one to Safe Browsing.
        if (WebViewFeature.isFeatureSupported(WebViewFeature.SAFE_BROWSING_RESPONSE_BACK_TO_SAFETY)) {
            callback.backToSafety(true)
            Toast.makeText(view.context, "Unsafe web page blocked.", Toast.LENGTH_LONG).show()
        }
    }
}

Java

public class MyWebViewClient extends WebViewClientCompat {
    // Automatically go "back to safety" when attempting to load a website that
    // Google identifies as a known threat. An instance of WebView calls this
    // method only after Safe Browsing is initialized, so there's no conditional
    // logic needed here.
    @Override
    public void onSafeBrowsingHit(WebView view, WebResourceRequest request,
            int threatType, SafeBrowsingResponseCompat callback) {
        // The "true" argument indicates that your app reports incidents like
        // this one to Safe Browsing.
        if (WebViewFeature.isFeatureSupported(WebViewFeature.SAFE_BROWSING_RESPONSE_BACK_TO_SAFETY)) {
            callback.backToSafety(true);
            Toast.makeText(view.getContext(), "Unsafe web page blocked.",
                    Toast.LENGTH_LONG).show();
        }
    }
}

API HTML5 Geolocation

Per le app che hanno come target Android 6.0 (livello API 23) e versioni successive, l'API Geolocation è supportato solo su origini sicure, come HTTPS. Qualsiasi richiesta inviata a L'API Geolocation su origini non sicure viene negata automaticamente senza richiamare il metodo onGeolocationPermissionsShowPrompt() corrispondente.

Disattiva la raccolta delle metriche

WebView può caricare dati diagnostici anonimi su Google quando l'utente dà il proprio consenso. I dati vengono raccolti per singola app per ogni app che crea un'istanza per un WebView. Puoi disattivare questa opzione creando il seguente tag nel file manifest <application> elemento:

<manifest>
    <application>
    ...
    <meta-data android:name="android.webkit.WebView.MetricsOptOut"
               android:value="true" />
    </application>
</manifest>

I dati vengono caricati da un'app solo se l'utente acconsente e l'app non effettua la disattivazione. Per ulteriori informazioni sulla disattivazione dei dati diagnostici Per i report, consulta Privacy degli utenti in WebView i report.

API Termination handling

L'API Finish handling gestisce i casi in cui il renderer elabora un WebView scompare, perché il sistema termina il renderer per recuperare necessaria o perché il processo del renderer si arresta in modo anomalo. Utilizzando questa API, consente all'app di continuare a essere eseguita, anche se il processo del renderer non viene più visualizzato.

Se un renderer si arresta in modo anomalo durante il caricamento di una pagina web specifica, se viene caricata di nuovo la stessa pagina, è possibile che un nuovo oggetto WebView lo stesso comportamento di arresto anomalo del rendering.

Il seguente snippet di codice illustra come utilizzare questa API in un Activity:

Kotlin

    
inner class MyRendererTrackingWebViewClient : WebViewClient() {
    private var mWebView: WebView? = null

    override fun onRenderProcessGone(view: WebView, detail: RenderProcessGoneDetail): Boolean {
        if (!detail.didCrash()) {
            // Renderer is killed because the system ran out of memory. The app
            // can recover gracefully by creating a new WebView instance in the
            // foreground.
            Log.e("MY_APP_TAG", ("System killed the WebView rendering process " +
                "to reclaim memory. Recreating..."))

            mWebView?.also { webView ->
                val webViewContainer: ViewGroup = findViewById(R.id.my_web_view_container)
                webViewContainer.removeView(webView)
                webView.destroy()
                mWebView = null
            }

            // By this point, the instance variable "mWebView" is guaranteed to
            // be null, so it's safe to reinitialize it.

            return true // The app continues executing.
        }

        // Renderer crashes because of an internal error, such as a memory
        // access violation.
        Log.e("MY_APP_TAG", "The WebView rendering process crashed!")

        // In this example, the app itself crashes after detecting that the
        // renderer crashed. If you handle the crash more gracefully and let
        // your app continue executing, you must destroy the current WebView
        // instance, specify logic for how the app continues executing, and
        // return "true" instead.
        return false
    }
}

Java

public class MyRendererTrackingWebViewClient extends WebViewClient {
    private WebView mWebView;

    @Override
    public boolean onRenderProcessGone(WebView view,
            RenderProcessGoneDetail detail) {
        if (!detail.didCrash()) {
            // Renderer is killed because the system ran out of memory. The app
            // can recover gracefully by creating a new WebView instance in the
            // foreground.
            Log.e("MY_APP_TAG", "System killed the WebView rendering process " +
                    "to reclaim memory. Recreating...");

            if (mWebView != null) {
                ViewGroup webViewContainer =
                        (ViewGroup) findViewById(R.id.my_web_view_container);
                webViewContainer.removeView(mWebView);
                mWebView.destroy();
                mWebView = null;
            }

            // By this point, the instance variable "mWebView" is guaranteed to
            // be null, so it's safe to reinitialize it.

            return true; // The app continues executing.
        }

        // Renderer crashes because of an internal error, such as a memory
        // access violation.
        Log.e("MY_APP_TAG", "The WebView rendering process crashed!");

        // In this example, the app itself crashes after detecting that the
        // renderer crashed. If you handle the crash more gracefully and let
        // your app continue executing, you must destroy the current WebView
        // instance, specify logic for how the app continues executing, and
        // return "true" instead.
        return false;
    }
}

API Renderer Importance

Quando WebView oggetti operano modalità multiprocesso, hai una certa flessibilità nel modo in cui la tua app gestisce situazioni di esaurimento della memoria. Puoi usare l'API Renderer Importance, introdotta in Android 8.0, per impostare un criterio di priorità per il renderer assegnato a un determinato renderer WebView oggetto. In particolare, potresti volere che la parte principale di continuare l'esecuzione quando un renderer che visualizza WebView oggetti sono terminati. Potresti farlo, ad esempio, se l'oggetto WebView non verrà mostrato per molto tempo, in modo che può recuperare la memoria utilizzata dal renderer.

Il seguente snippet di codice mostra come assegnare una priorità al renderer processo associato agli oggetti WebView dell'app:

Kotlin

val myWebView: WebView = ...
myWebView.setRendererPriorityPolicy(RENDERER_PRIORITY_BOUND, true)

Java

WebView myWebView;
myWebView.setRendererPriorityPolicy(RENDERER_PRIORITY_BOUND, true);

In questo particolare snippet, la priorità del renderer è la stessa della la priorità predefinita per l'app. true diminuisce la priorità del renderer a RENDERER_PRIORITY_WAIVED quando l'oggetto WebView associato non è più visibile. In altre parole, un argomento true indica che alla tua app non è importante se il sistema mantiene attivo il processo di rendering. Di fatto, questo livello di priorità inferiore è probabile che il processo del renderer venga interrotto in memoria in situazioni diverse.

Per scoprire di più su come il sistema gestisce le situazioni in cui la memoria è insufficiente, vedi Processi e app del ciclo di vita.