WebView オブジェクトを管理する

Android には、アプリの管理に役立つ API がいくつか用意されています。 WebView アプリでウェブ コンテンツを表示するオブジェクト。

このページでは、これらの API を使用して WebView を操作する方法について説明します。 アプリの安定性とセキュリティが向上します。

Version API

Android 7.0(API レベル 24)以降、ユーザーはいくつかの選択肢の中から ウェブ コンテンツを表示するためのさまざまなパッケージを WebView オブジェクトで提供しています。 AndroidX.webkit ライブラリには getCurrentWebViewPackage() ウェブを表示しているパッケージに関連する情報を取得するメソッド おすすめしますこの方法は、発生したエラーだけを分析する場合に便利です。 アプリが特定のパッケージのパッケージを使用してウェブ コンテンツを表示しようとしたとき WebView の実装。

このメソッドを使用するには、次のコード スニペットに示すロジックを追加します。

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);
<ph type="x-smartling-placeholder">

Google セーフ ブラウジング サービス

より安全なブラウジング体験をユーザーに提供するために、WebView 使用して URL を検証する Google セーフ ブラウジング、 これにより、ユーザーが特定の場所に移動しようとしたときに、 安全でない可能性があります。

EnableSafeBrowsing のデフォルト値は true ですが、 セーフ ブラウジングを条件付きでのみ有効にする場合や、 無効にすることもできます。Android 8.0(API レベル 26)以降では、 setSafeBrowsingEnabled() 個々の WebView オブジェクトのセーフ ブラウジングを切り替えます。

すべての WebView オブジェクトでセーフ ブラウジングを無効にする場合 チェックを行うには、次の <meta-data> 要素をアプリの 次のとおりです。

<ph type="x-smartling-placeholder">
<manifest>
    <application>
        <meta-data android:name="android.webkit.WebView.EnableSafeBrowsing"
                   android:value="false" />
        ...
    </application>
</manifest>
<ph type="x-smartling-placeholder">

プログラムによるアクションを定義する

WebView のインスタンスが読み込もうとしたとき 既知の脅威として分類(デフォルトでは WebView) 既知の脅威についてユーザーに警告するインタースティシャルを表示する。この画面では ユーザーはこのまま URL を読み込むか 保護します。

Android 8.1(API レベル 27)以降をターゲットとする場合は、 既知の脅威にアプリがどう対応するかをプログラマティックに確認する方法 方法:

  • アプリが既知の脅威を Safer に報告するかどうかを制御できます ブラウジング。
  • 次のような特定のアクションを、アプリに自動的に実行させることができます。 安全なページに戻るたびに 既知の脅威に分類されます
で確認できます。 <ph type="x-smartling-placeholder">

次のコード スニペットは、アプリのインスタンスに 既知の攻撃に遭遇した後は、常に安全な状態に戻るWebView 脅威:

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

Android 6.0(API レベル 23)以降を対象とするアプリの場合、Geolocation API は、HTTPS などの安全なオリジンでのみサポートされます。Pod への 保護されていないオリジンでの Geolocation API が、呼び出しなしで自動的に拒否される 対応する onGeolocationPermissionsShowPrompt() メソッド。

指標の収集を無効にする

WebView は匿名の診断データをアップロードできます: Google に送られます。データはアプリ単位で収集されます WebView をインスタンス化するアプリごとに 1 つずつ呼び出します。この通知を受け取らないように 機能を使用するには、マニフェストの <application> 要素:

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

データがアプリからアップロードされるのは、ユーザーが同意した場合、かつ オプトアウトしません。診断データを無効にする方法について詳しくは、 WebView でのユーザーのプライバシー、 レポートをご覧ください。

Termination Handling API

Termination Handling API は、API 呼び出しのレンダラ プロセスが WebView システムがレンダラを強制終了して再利用するためか、 メモリ不足が原因で発生することがあります。この API を使用すると、 レンダラ プロセスが終了してもアプリの実行を継続できます。

<ph type="x-smartling-placeholder">

特定のウェブページの読み込み中にレンダラがクラッシュした場合、 同じページを再度読み込むと、新しい WebView オブジェクトが レンダリングがクラッシュする場合も同じです。

次のコード スニペットは、 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;
    }
}

Renderer Importance API

WebView オブジェクトの場合 運用する マルチプロセス モードでは、マルチプロセス モードを使用すると、 メモリ不足の状況に陥ります。Renderer Importance API を使用すると、 Android 8.0: 特定の ID に割り当てられたレンダラの優先度ポリシーを設定する WebView オブジェクト。特に、インフラストラクチャの主要な部分を レンダリングの際に、アプリの依存関係を表示するレンダラが WebView オブジェクトは強制終了されます。たとえば、 WebView オブジェクトが長時間表示されないことが想定されているため、 システムがレンダラが使用していたメモリを回収できます。

レンダラに優先度を割り当てる方法を示したコード スニペットを以下に示します。 WebViewオブジェクトに関連付けられたプロセス

Kotlin

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

Java

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

この特定のスニペットでは、レンダラの優先度は以下と同じです。 設定されます。true 引数を指定することでレンダラの優先度が下がり、 RENDERER_PRIORITY_WAIVED 関連する WebView オブジェクトが表示されなくなるとトリガーされます。その他の true 引数により、アプリは システムによってレンダラのプロセスが維持されます。実際 優先度が低い場合 メモリ不足でレンダラ プロセスが強制終了される可能性が高くなる 対応できます。

<ph type="x-smartling-placeholder">

メモリ不足の状況へのシステムの対応について詳しくは、以下をご覧ください。 プロセスとアプリ 説明します