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);
Google セーフ ブラウジング サービス
より安全なブラウジング体験をユーザーに提供するために、WebView
使用して URL を検証する
Google セーフ ブラウジング、
これにより、ユーザーが特定の場所に移動しようとしたときに、
安全でない可能性があります。
EnableSafeBrowsing
のデフォルト値は true ですが、
セーフ ブラウジングを条件付きでのみ有効にする場合や、
無効にすることもできます。Android 8.0(API レベル 26)以降では、
setSafeBrowsingEnabled()
個々の WebView
オブジェクトのセーフ ブラウジングを切り替えます。
すべての WebView
オブジェクトでセーフ ブラウジングを無効にする場合
チェックを行うには、次の <meta-data>
要素をアプリの
次のとおりです。
<manifest> <application> <meta-data android:name="android.webkit.WebView.EnableSafeBrowsing" android:value="false" /> ... </application> </manifest>
プログラムによるアクションを定義する
WebView
のインスタンスが読み込もうとしたとき
既知の脅威として分類(デフォルトでは WebView
)
既知の脅威についてユーザーに警告するインタースティシャルを表示する。この画面では
ユーザーはこのまま URL を読み込むか
保護します。
Android 8.1(API レベル 27)以降をターゲットとする場合は、 既知の脅威にアプリがどう対応するかをプログラマティックに確認する方法 方法:
- アプリが既知の脅威を Safer に報告するかどうかを制御できます ブラウジング。
- 次のような特定のアクションを、アプリに自動的に実行させることができます。 安全なページに戻るたびに 既知の脅威に分類されます
次のコード スニペットは、アプリのインスタンスに
既知の攻撃に遭遇した後は、常に安全な状態に戻るWebView
脅威:
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!"); } } }); } }
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 を使用すると、
レンダラ プロセスが終了してもアプリの実行を継続できます。
特定のウェブページの読み込み中にレンダラがクラッシュした場合、
同じページを再度読み込むと、新しい 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
引数により、アプリは
システムによってレンダラのプロセスが維持されます。実際 優先度が低い場合
メモリ不足でレンダラ プロセスが強制終了される可能性が高くなる
対応できます。
メモリ不足の状況へのシステムの対応について詳しくは、以下をご覧ください。 プロセスとアプリ 説明します。