Android memberikan beberapa API untuk membantu Anda mengelola objek WebView
yang menampilkan konten web di aplikasi Anda.
Halaman ini menjelaskan cara menggunakan API tersebut untuk bekerja lebih efektif dengan
objek WebView
, meningkatkan
stabilitas serta keamanan aplikasi Anda.
Version API
Mulai Android 7.0 (API level 24), pengguna dapat memilih beberapa
paket berbeda untuk menampilkan konten web
di
objek WebView
. Library AndroidX
webkit menyertakan metode
getCurrentWebViewPackage()
untuk mengambil informasi terkait
paket yang menampilkan konten web di aplikasi Anda. Metode ini akan
berguna khususnya saat menganalisis error yang terjadi hanya ketika aplikasi Anda mencoba menampilkan konten
web menggunakan implementasi paket tertentu dari
WebView
.
Untuk menggunakan metode ini, tambahkan logika yang ditampilkan dalam cuplikan kode berikut:
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);
Catatan:
Metode
getCurrentWebViewPackage()
dapat menampilkan null
jika perangkat disiapkan dengan tidak benar,
tidak mendukung penggunaan WebView
(seperti perangkat Wear OS), atau kekurangan
implementasi WebView
yang dapat diupdate, seperti pada Android 4.4 (API level
19) dan versi sebelumnya.
Layanan Google Safe Browsing
Untuk memberikan pengalaman penjelajahan yang lebih aman kepada pengguna,
objek WebView
memverifikasi URL menggunakan
Google Safe Browsing,
yang memungkinkan aplikasi Anda menampilkan peringatan kepada pengguna saat mereka
mencoba membuka situs yang berpotensi tidak aman.
Meskipun nilai default EnableSafeBrowsing
adalah true, terkadang ada kasus
saat Anda mungkin hanya ingin mengaktifkan Safe Browsing secara kondisional atau menonaktifkannya. Android 8.0 (API level 26)
dan yang lebih baru mendukung penggunaan
setSafeBrowsingEnabled()
untuk mengatur setelan Safe Browsing pada setiap
objek WebView
.
WebView
tidak diikutkan pemeriksaan Safe Browsing, Anda dapat melakukannya dengan menambahkan elemen <meta-data>
berikut ke file manifes aplikasi:
<manifest> <application> <meta-data android:name="android.webkit.WebView.EnableSafeBrowsing" android:value="false" /> ... </application> </manifest>
Menentukan tindakan terprogram
Saat instance
WebView
berupaya memuat halaman yang telah diklasifikasikan oleh
Google sebagai ancaman yang diketahui, WebView
secara default akan menampilkan
interstisial yang memperingatkan pengguna ancaman yang diketahui tersebut. Layar ini memberikan opsi
kepada pengguna untuk tetap memuat URL atau kembali ke halaman sebelumnya yang aman.
Jika menargetkan Android 8.1 (API level 27) atau yang lebih tinggi, Anda dapat menentukan secara terprogram cara aplikasi merespons ancaman yang dikenal:
- Anda dapat mengontrol apakah aplikasi akan melaporkan ancaman yang diketahui ke Safe Browsing.
- Anda dapat mengatur agar aplikasi otomatis menjalankan tindakan tertentu—seperti kembali ke halaman yang aman—setiap kali menemukan URL yang diklasifikasikan sebagai ancaman yang diketahui.
Catatan: Untuk perlindungan optimal terhadap ancaman yang diketahui, tunggu
hingga Anda telah memulai Safe Browsing sebelum memanggil
metode loadUrl()
objek WebView
.
Cuplikan kode berikut menunjukkan cara menginstruksikan instance
WebView
aplikasi Anda agar selalu kembali ke halaman aman setelah menemui
ancaman yang diketahui:
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 has identified 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 has identified 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
Untuk aplikasi yang menargetkan Android 6.0 (API level 23) dan yang lebih tinggi, Geolocation API hanya didukung
di sumber yang aman, seperti HTTPS. Setiap permintaan ke Geolocation API di sumber yang tidak aman akan
otomatis ditolak tanpa memanggil metode
onGeolocationPermissionsShowPrompt()
yang sesuai.
Memilih tidak ikut pengumpulan metrik
WebView
memiliki kemampuan untuk mengupload data diagnostik anonim ke Google saat pengguna telah
memberikan persetujuannya. Data dikumpulkan per aplikasi untuk setiap aplikasi yang telah membuat instance
WebView
. Anda dapat memilih tidak ikut fitur ini dengan membuat tag berikut di elemen
<application>
manifes:
<manifest> <application> ... <meta-data android:name="android.webkit.WebView.MetricsOptOut" android:value="true" /> </application> </manifest>
Data hanya akan diupload dari aplikasi jika pengguna telah mengizinkan dan aplikasi belum keluar dar fitur ini.
Termination Handling API
API ini menangani kasus saat proses perender untuk
objek WebView
hilang, baik karena sistem menghentikan perender untuk mengklaim kembali memori yang sangat dibutuhkan atau karena proses
perender itu sendiri error. Dengan menggunakan API ini, Anda mengizinkan aplikasi untuk terus
mengeksekusi, meskipun proses perender telah hilang.
Perhatian: Jika aplikasi Anda terus mengeksekusi setelah
proses perender hilang, instance
WebView
terkait tidak akan bisa digunakan kembali, terlepas dari apakah proses
perender telah dihentikan atau error. Aplikasi Anda harus menghapus instance dari hierarki
tampilan dan mengakhiri instance untuk terus mengeksekusi. Selanjutnya, aplikasi Anda harus
membuat instance WebView
yang sepenuhnya baru untuk melanjutkan
rendering halaman web.
Perhatikan bahwa, jika perender tidak bekerja saat memuat halaman web tertentu,
mencoba memuat halaman yang sama lagi dapat menyebabkan objek
WebView
baru menampilkan perilaku
error rendering yang sama.
Cuplikan kode berikut mengilustrasikan cara menggunakan API ini:
Kotlin
inner class MyRendererTrackingWebViewClient : WebViewClient() { private var mWebView: WebView? = null override fun onRenderProcessGone(view: WebView, detail: RenderProcessGoneDetail): Boolean { if (!detail.didCrash()) { // Renderer was 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 crashed 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 choose to handle the crash more gracefully // and allow your app to continue executing, you should 1) destroy the // current WebView instance, 2) specify logic for how the app can // continue executing, and 3) 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 was 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 crashed 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 choose to handle the crash more gracefully // and allow your app to continue executing, you should 1) destroy the // current WebView instance, 2) specify logic for how the app can // continue executing, and 3) return "true" instead. return false; } }
Renderer Importance API
Karena objek WebView
beroperasi dalam mode
multiproses, Anda akan memiliki beberapa fleksibilitas dalam cara aplikasi menangani situasi
kehabisan memori. Anda dapat menggunakan Renderer Importance API, yang diperkenalkan di Android 8.0,
guna menetapkan kebijakan prioritas untuk perender yang ditetapkan ke
objek WebView
tertentu. Secara khusus, Anda mungkin ingin
bagian utama aplikasi terus berjalan saat perender yang menampilkan
objek WebView
aplikasi sudah dihentikan. Anda mungkin melakukan hal ini,
misalnya, jika berharap untuk tidak menampilkan objek WebView
selama jangka waktu yang panjang sehingga sistem dapat mengklaim kembali memori yang
digunakan perender.
Cuplikan kode berikut menunjukkan cara menetapkan prioritas ke proses
perender yang terkait dengan objek WebView
aplikasi Anda:
Kotlin
val myWebView: WebView = ... myWebView.setRendererPriorityPolicy(RENDERER_PRIORITY_BOUND, true)
Java
WebView myWebView; myWebView.setRendererPriorityPolicy(RENDERER_PRIORITY_BOUND, true);
Dalam cuplikan khusus ini, prioritas perender sama dengan (atau
"terikat pada") prioritas default untuk aplikasi.
Argumen true
akan menurunkan prioritas perender menjadi
RENDERER_PRIORITY_WAIVED
saat objek WebView
terkait tidak lagi terlihat. Dengan
kata lain, argumen true
menunjukkan bahwa aplikasi Anda tidak peduli
apakah sistem menjaga proses perender tetap aktif atau tidak. Bahkan, tingkat prioritas
yang lebih rendah ini memungkinkan proses perender dihentikan dalam
situasi kehabisan memori.
Peringatan: Untuk mempertahankan stabilitas aplikasi, Anda tidak boleh
mengubah kebijakan prioritas perender untuk objek WebView
kecuali Anda juga menggunakan Termination Handle API
untuk menentukan cara WebView
bereaksi saat perender
yang terkait menghilang.
Untuk mempelajari lebih lanjut cara sistem menangani situasi memori rendah, lihat Proses dan Siklus Hidup Aplikasi.