WebView-Objekte verwalten

Android bietet mehrere APIs, mit denen Sie die WebView-Objekte verwalten können, die Webinhalte in Ihrer App anzeigen.

Auf dieser Seite wird beschrieben, wie Sie diese APIs verwenden können, um effektiver mit WebView-Objekten zu arbeiten und so die Stabilität und Sicherheit Ihrer App zu verbessern.

Version API

Ab Android 7.0 (API-Level 24) können Nutzer zwischen mehreren verschiedenen Paketen auswählen, um Webinhalte in einem WebView-Objekt anzuzeigen. Die Jetpack Webkit Bibliothek enthält die getCurrentWebViewPackage() Methode zum Abrufen von Informationen zum Paket, das Webinhalte in Ihrer App anzeigt. Diese Methode ist nützlich, wenn Sie Fehler analysieren, die nur auftreten, wenn Ihre App versucht, Webinhalte mit einer bestimmten Paketimplementierung von WebView anzuzeigen.

Wenn Sie diese Methode verwenden möchten, fügen Sie die im folgenden Code-Snippet gezeigte Logik hinzu:

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

Google Safe Browsing Service

Um Ihren Nutzern ein sichereres Surferlebnis zu bieten, werden URLs in WebView Objekten mit Google Safe Browsingüberprüft. So kann Ihre App Nutzern eine Warnung anzeigen, wenn sie versuchen, zu einer potenziell unsicheren Website zu navigieren.

Der Standardwert von EnableSafeBrowsing ist zwar „true“, es gibt aber Fälle, in denen Sie Safe Browsing nur bedingt aktivieren oder deaktivieren möchten. Unter Android 8.0 (API-Level 26) und höher kann Safe Browsing mit setSafeBrowsingEnabled() für ein einzelnes WebView Objekt aktiviert oder deaktiviert werden.

Wenn alle WebView-Objekte von Safe Browsing -Prüfungen ausgeschlossen werden sollen, fügen Sie der Manifestdatei Ihrer App das folgende <meta-data>-Element hinzu:

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

Programmatische Aktionen definieren

Wenn eine Instanz von WebView versucht, eine Seite zu laden, die von Google als bekannte Bedrohung eingestuft wird, wird in WebView standardmäßig ein Interstitial angezeigt, in dem Nutzer vor der bekannten Bedrohung gewarnt werden. Auf diesem Bildschirm können Nutzer die URL trotzdem laden oder zu einer vorherigen sicheren Seite zurückkehren.

Wenn Sie Android 8.1 (API-Level 27) oder höher verwenden, können Sie programmatisch definieren, wie Ihre App auf eine bekannte Bedrohung reagiert. Dazu haben Sie folgende Möglichkeiten:

  • Sie können festlegen, ob Ihre App bekannte Bedrohungen an Safe Browsing meldet.
  • Sie können festlegen, dass Ihre App automatisch eine bestimmte Aktion ausführt, z. B. zur Sicherheit zurückkehren, wenn sie auf eine URL stößt, die als bekannte Bedrohung eingestuft wird.

Die folgenden Code-Snippets zeigen, wie Sie die WebView-Instanzen Ihrer App anweisen, nach dem Auftreten einer bekannten Bedrohung immer zur Sicherheit zurückzukehren:

MyWebActivity.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();
        }
    }
}

HTML5 Geolocation API

Bei Apps, die auf Android 6.0 (API-Level 23) und höher ausgerichtet sind, wird die Geolocation API nur für sichere Ursprünge wie HTTPS unterstützt. Alle Anfragen an die Geolocation API für nicht sichere Ursprünge werden automatisch abgelehnt, ohne dass die entsprechende Methode onGeolocationPermissionsShowPrompt() aufgerufen wird.

Erfassung von Messwerten deaktivieren

WebView kann anonyme Diagnosedaten an Google hochladen, wenn der Nutzer seine Einwilligung gibt. Die Daten werden für jede App, die eine WebView-Instanz erstellt, auf App-Basis erfasst. Sie können diese Funktion deaktivieren, indem Sie das folgende Tag im Manifest's <application> Element erstellen:

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

Daten werden nur dann von einer App hochgeladen, wenn der Nutzer seine Einwilligung gibt und die App die Funktion nicht deaktiviert. Weitere Informationen zum Deaktivieren der Berichterstellung von Diagnosedaten finden Sie unter Datenschutz der Nutzer in der WebView Berichterstellung.

Termination Handling API

Die Termination Handling API verarbeitet Fälle, in denen der Renderer-Prozess für ein WebView-Objekt beendet wird, entweder weil das System den Renderer beendet, um benötigten Arbeitsspeicher freizugeben, oder weil der Renderer-Prozess abstürzt. Mit dieser API kann Ihre App weiter ausgeführt werden, auch wenn der Renderer-Prozess beendet wird.

Wenn ein Renderer beim Laden einer bestimmten Webseite abstürzt, kann der Versuch, dieselbe Seite noch einmal zu laden, dazu führen, dass ein neues WebView-Objekt dasselbe Rendering-Absturzverhalten zeigt.

Das folgende Code-Snippet zeigt, wie Sie diese API in einer Activity verwenden:

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

Renderer Importance API

Wenn WebView Objekte im Mehrprozessmodus ausgeführt werden, haben Sie einige Flexibilität bei der Verarbeitung von Situationen, in denen der Arbeitsspeicher knapp wird. Mit der Renderer Importance API, die in Android 8.0 eingeführt wurde, können Sie eine Prioritätsrichtlinie für den Renderer festlegen, der einem bestimmten WebView-Objekt zugewiesen ist. Insbesondere kann es sinnvoll sein, dass der Hauptteil Ihrer App weiter ausgeführt wird, wenn ein Renderer beendet wird, der die WebView-Objekte Ihrer App anzeigt. Das kann beispielsweise der Fall sein, wenn Sie erwarten, dass das WebView-Objekt längere Zeit nicht angezeigt wird, sodass das System Arbeitsspeicher freigeben kann, der vom Renderer verwendet wurde.

Das folgende Code-Snippet zeigt, wie Sie dem Renderer-Prozess, der mit den WebView-Objekten Ihrer App verknüpft ist, eine Priorität zuweisen:

Kotlin

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

Java

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

In diesem Snippet ist die Priorität des Renderers dieselbe wie die Standardpriorität für die App oder an diese gebunden. Das Argument true verringert die Priorität des Renderers auf RENDERER_PRIORITY_WAIVED, wenn das zugehörige WebView-Objekt nicht mehr sichtbar ist. Mit anderen Worten: Ein true-Argument gibt an, dass es Ihrer App egal ist, ob das System den Renderer-Prozess aktiv hält. Tatsächlich ist es bei dieser niedrigeren Priorität wahrscheinlich, dass der Renderer-Prozess in Situationen, in denen der Arbeitsspeicher knapp wird, beendet wird.

Weitere Informationen dazu, wie das System mit Situationen umgeht, in denen der Arbeitsspeicher knapp wird, finden Sie unter Prozesse und App Lebenszyklus.