Android 提供多種 API
WebView
在應用程式中顯示網路內容的物件
本頁面說明如何將這些 API 與 WebView
搭配使用
物件,提升應用程式的穩定性和安全性。
版本 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
物件則會使用
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
例項嘗試載入
已由 Google 歸類為已知威脅,預設WebView
顯示插頁式廣告,警告使用者留意已知威脅。這個畫面提供了
使用者可以選擇載入網址 或返回之前的網頁
安全。
如果您指定 Android 8.1 (API 級別 27) 以上版本,就可以定義 透過程式輔助方式,應用程式如何回應下列已知威脅 方式:
- 您可以控管應用程式是否要將已知的威脅回報給「安全」應用程式 瀏覽。
- 您可以讓應用程式自動執行特定動作,例如 就像回到線上安全 — 每次遇到網址相同的 已歸類為已知威脅
下列程式碼片段說明如何指示應用程式的
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 地理位置 API
如果應用程式指定 Android 6.0 (API 級別 23) 以上版本,Geolocation API
僅支援安全來源,例如 HTTPS。向
針對不安全來源上的 Geolocation API 會自動拒絕,不必叫用
對應的 onGeolocationPermissionsShowPrompt()
方法。
停用指標收集功能
「WebView
」能夠將匿名診斷資料上傳至
並徵得使用者同意。收集個別應用程式的資料
針對每個要例項化 WebView
的每個應用程式。如果不想使用這個
方法是在資訊清單的
<application>
元素:
<manifest> <application> ... <meta-data android:name="android.webkit.WebView.MetricsOptOut" android:value="true" /> </application> </manifest>
只有在使用者同意同時的情況下,才會從應用程式上傳資料 應用程式未停用進一步瞭解如何停用診斷資料 報告,請參閱「WebView 中的使用者隱私」 報表。
終止處理 API
Termination Handling 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; } }
轉譯器重要性 API
當 WebView
物件出現時
於
多程序模式,就能靈活地處理應用程式
記憶體不足的情況您可以使用
在 Android 8.0 版中,為指派給特定轉譯器的特定轉譯器設定優先順序政策
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
引數表示應用程式不在乎
系統會持續運作轉譯器程序事實上,這個優先級較低的層級
導致轉譯器程序在記憶體不足中遭終止
情境。
如要進一步瞭解系統如何處理記憶體不足的情況,請參見 程序與應用程式 生命週期。