Android 4.4 (API level 19) memperkenalkan versi baru WebView
yang didasarkan pada Chromium. Perubahan ini mengupgrade dukungan performa dan standar WebView
untuk HTML5, CSS3, dan JavaScript guna mencocokkan dengan versi browser web terbaru. Setiap aplikasi yang menggunakan WebView
akan mewarisi upgrade versi tersebut jika dijalankan di Android 4.4 dan yang lebih tinggi.
Dokumen ini menjelaskan perubahan tambahan yang perlu Anda perhatikan untuk WebView
jika Anda menetapkan targetSdkVersion
ke "19" atau yang lebih tinggi.
Catatan: Jika targetSdkVersion
Anda ditetapkan ke "18" atau yang lebih rendah, WebView
akan beroperasi dalam "quirks mode" untuk menghindari beberapa perubahan perilaku yang dijelaskan di bawah, sebaik mungkin—sambil tetap memberikan aplikasi Anda upgrade standar performa dan web.
Namun, perhatikan bahwa tata letak kolom tunggal dan sempit dan tingkat zoom default tidak didukung sama sekali di Android 4.4, dan mungkin ada perbedaan perilaku yang belum teridentifikasi, jadi pastikan untuk menguji aplikasi Anda di Android 4.4 atau yang lebih tinggi, meskipun Anda tetap menetapkan targetSdkVersion
ke "18" atau yang lebih rendah.
Untuk membantu Anda mengatasi masalah yang mungkin Anda temui saat memigrasikan aplikasi ke WebView
di Android 4.4, Anda dapat mengaktifkan debug jarak jauh melalui Chrome di desktop dengan memanggil setWebContentsDebuggingEnabled()
.
Fitur baru di WebView
ini memungkinkan Anda memeriksa dan menganalisis konten web, skrip, dan aktivitas jaringan saat dijalankan dalam WebView
. Untuk informasi selengkapnya, lihat Proses Debug Jarak Jauh di Android.
Perubahan Agen-Pengguna
Jika Anda menayangkan konten ke WebView
berdasarkan agen-pengguna, harap perhatikan bahwa string agen-pengguna telah berubah sedikit dan sekarang menyertakan versi Chrome:
Mozilla/5.0 (Linux; Android 4.4; Nexus 4 Build/KRT16H) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Mobile Safari/537.36
Jika Anda perlu mengambil agen-pengguna, tetapi tidak ingin menyimpannya untuk aplikasi atau tidak ingin membuat instance WebView
, Anda harus menggunakan metode statis, getDefaultUserAgent()
. Namun, jika Anda ingin mengganti string agen-pengguna di WebView
, Anda dapat menggunakan getUserAgentString()
.
Multi-threading dan Pemblokiran Thread
Jika Anda memanggil metode di WebView
dari thread apa pun selain UI thread aplikasi Anda, hal ini dapat menyebabkan hasil yang tidak diharapkan. Misalnya, jika aplikasi Anda menggunakan beberapa thread, Anda dapat menggunakan metode runOnUiThread()
untuk memastikan kode berjalan di UI thread:
Kotlin
runOnUiThread { // Code for WebView goes here }
Java
runOnUiThread(new Runnable() { @Override public void run() { // Code for WebView goes here } });
Selain itu, pastikan Anda tidak pernah memblokir UI thread. Situasi saat beberapa aplikasi membuat kesalahan ini adalah saat menunggu callback JavaScript. Misalnya, jangan menggunakan kode seperti ini:
Kotlin
// This code is BAD and will block the UI thread webView.loadUrl("javascript:fn()") while (result == null) { Thread.sleep(100) }
Java
// This code is BAD and will block the UI thread webView.loadUrl("javascript:fn()"); while(result == null) { Thread.sleep(100); }
Sebagai gantinya, Anda dapat menggunakan metode baru, evaluateJavascript()
, untuk menjalankan JavaScript secara asinkron.
Penanganan URL Kustom
WebView
yang baru menerapkan pembatasan tambahan saat meminta resource dan menyelesaikan link yang menggunakan skema URL kustom. Misalnya, jika Anda menerapkan callback seperti shouldOverrideUrlLoading()
atau shouldInterceptRequest()
, maka WebView
akan memanggil ketiganya hanya untuk URL yang valid.
Jika Anda menggunakan skema URL kustom atau URL dasar dan melihat bahwa aplikasi menerima panggilan yang lebih sedikit ke callback ini atau gagal memuat resource di Android 4.4, pastikan bahwa permintaan menentukan URL yang valid yang sesuai dengan RFC 3986.
Misalnya, WebView
yang baru mungkin tidak memanggil metode shouldOverrideUrlLoading()
Anda untuk link seperti ini:
<a href="showProfile">Show Profile</a>
Hasil dari pengguna yang mengklik link tersebut dapat bervariasi:
- Jika Anda memuat halaman dengan memanggil
loadData()
atauloadDataWithBaseURL()
dengan URL dasar yang tidak valid atau null, maka Anda tidak akan menerima callbackshouldOverrideUrlLoading()
untuk jenis link ini di halaman.Catatan: Jika Anda menggunakan
loadDataWithBaseURL()
dan URL dasarnya tidak valid atau ditetapkan ke null, semua link dalam konten yang Anda muat harus absolut. - Jika Anda memuat halaman dengan memanggil
loadUrl()
atau memberikan URL dasar yang valid denganloadDataWithBaseURL()
, maka Anda akan menerima callbackshouldOverrideUrlLoading()
untuk jenis link ini pada halaman, tetapi URL yang Anda terima akan berupa URL absolut, relatif terhadap halaman saat ini. Misalnya, URL yang Anda terima akan berupa"http://www.example.com/showProfile"
, bukan hanya"showProfile"
.
Daripada menggunakan string simpel di link seperti yang ditunjukkan di atas, Anda dapat menggunakan skema kustom seperti berikut:
<a href="example-app:showProfile">Show Profile</a>
Anda kemudian dapat menangani URL ini di metode shouldOverrideUrlLoading()
Anda seperti ini:
Kotlin
// The URL scheme should be non-hierarchical (no trailing slashes) const val APP_SCHEME = "example-app:" override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean { return if (url?.startsWith(APP_SCHEME) == true) { urlData = URLDecoder.decode(url.substring(APP_SCHEME.length), "UTF-8") respondToData(urlData) true } else { false } }
Java
// The URL scheme should be non-hierarchical (no trailing slashes) private static final String APP_SCHEME = "example-app:"; @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if (url.startsWith(APP_SCHEME)) { urlData = URLDecoder.decode(url.substring(APP_SCHEME.length()), "UTF-8"); respondToData(urlData); return true; } return false; }
Jika Anda tidak dapat mengubah HTML, Anda mungkin dapat menggunakan loadDataWithBaseURL()
dan menetapkan URL dasar yang terdiri dari skema kustom dan host yang valid, seperti "example-app://<valid_host_name>/"
. Contoh:
Kotlin
webView.loadDataWithBaseURL("example-app://example.co.uk/", HTML_DATA, null, "UTF-8", null)
Java
webView.loadDataWithBaseURL("example-app://example.co.uk/", HTML_DATA, null, "UTF-8", null);
Nama host yang valid harus sesuai dengan RFC 3986 dan penting untuk menyertakan garis miring di bagian akhir, jika tidak, permintaan apa pun dari halaman yang dimuat dapat dibuang.
Perubahan Area Pandang
Area pandang target-densitydpi tidak didukung lagi.
Sebelumnya, WebView
mendukung properti area pandang bernama target-densitydpi
untuk membantu halaman web menentukan kepadatan layar yang diinginkan. Properti ini tidak lagi didukung dan Anda harus melakukan migrasi menggunakan solusi standar dengan gambar dan CSS seperti yang dibahas dalam UI Pixel-Perfect di WebView.
Area pandang diperbesar saat kecil
Sebelumnya, jika Anda menetapkan lebar area pandang dengan nilai kurang dari atau sama dengan "320", maka area pandang akan ditetapkan ke "lebar perangkat", dan jika Anda menetapkan tinggi area pandang dengan nilai kurang dari atau sama dengan tinggi WebView
, maka area pandang akan ditetapkan ke "tinggi-perangkat". Namun, saat berjalan di WebView
baru, nilai lebar atau tinggi akan dipatuhi dan WebView
diperbesar untuk mengisi lebar layar.
Beberapa tag area pandang tidak didukung
Sebelumnya, jika Anda menyertakan beberapa tag area pandang di halaman web, WebView
akan menggabungkan properti dari semua tag.
Pada WebView
baru, hanya area pandang terakhir yang digunakan dan area pandang lainnya akan diabaikan.
Zoom default tidak digunakan lagi
Metode getDefaultZoom()
dan setDefaultZoom()
untuk mendapatkan dan menetapkan tingkat zoom awal pada halaman tidak lagi didukung, dan sebaiknya Anda menentukan area pandang yang sesuai di halaman web.
Perhatian: API ini tidak didukung sama sekali di Android 4.4 dan yang lebih tinggi. Meskipun targetSdkVersion
Anda disetel ke "18" atau yang lebih rendah, API ini tidak berpengaruh.
Untuk informasi tentang cara menentukan properti area pandang di HTML, baca Pixel-Perfect UI di WebView.
Jika Anda tidak dapat menetapkan lebar area pandang dalam HTML, panggil setUseWideViewPort()
untuk memastikan halaman diberi area pandang yang lebih luas. Contoh:
Kotlin
webView.settings.apply { useWideViewPort = true loadWithOverviewMode = true }
Java
WebSettings settings = webView.getSettings(); settings.setUseWideViewPort(true); settings.setLoadWithOverviewMode(true);
Perubahan Gaya
Latar belakang CSS singkat mengganti ukuran-latar
Chrome dan browser lainnya telah berperilaku seperti ini untuk sementara waktu, tetapi sekarang WebView
juga akan mengganti setelan CSS untuk background-size
jika Anda juga menentukan gaya background
. Misalnya, ukuran di bawah ini akan disetel ulang ke nilai default:
.some-class { background-size: contain; background: url('images/image.png') no-repeat; }
Cara memperbaikinya adalah dengan mengganti kedua properti tersebut.
.some-class { background: url('images/image.png') no-repeat; background-size: contain; }
Ukuran berbentuk piksel CSS, bukan piksel layar
Sebelumnya, parameter ukuran seperti window.outerWidth
dan window.outerHeight
menampilkan nilai dalam piksel layar yang sebenarnya.
Pada WebView
baru, ini akan menampilkan nilai berdasarkan piksel CSS.
Secara umum, mencoba dan menghitung ukuran fisik dalam piksel untuk menentukan ukuran elemen atau penghitungan lainnya merupakan praktik yang tidak baik. Namun, jika Anda telah menonaktifkan zoom dan skala awal ditetapkan ke 1,0, Anda dapat menggunakan window.devicePixelRatio
untuk mendapatkan skala, lalu kalikan nilai piksel CSS dengan nilai tersebut. Sebaliknya, Anda juga dapat membuat JavaScript binding untuk mengkueri ukuran piksel dari WebView
itu sendiri.
Untuk informasi selengkapnya, lihat quirksmode.org.
NARROW_COLUMNS dan SINGLE_COLUMN tidak didukung lagi
Nilai NARROW_COLUMNS
untuk WebSettings.LayoutAlgorithm
tidak didukung lagi di versi WebView
baru.
Perhatian: API ini tidak didukung sama sekali di Android 4.4 dan yang lebih tinggi. Meskipun targetSdkVersion
Anda disetel ke "18" atau yang lebih rendah, API ini tidak berpengaruh.
Anda dapat menangani perubahan ini dengan cara berikut:
- Ubah gaya aplikasi Anda:
Jika Anda memiliki kontrol terhadap HTML dan CSS pada halaman, Anda mungkin mendapati bahwa mengubah desain konten Anda mungkin merupakan pendekatan yang paling dapat diandalkan. Misalnya, untuk layar yang mencantumkan lisensi, Anda dapat menggabungkan teks dalam tag
<pre>
, yang dapat Anda lakukan dengan gaya berikut:<pre style="word-wrap: break-word; white-space: pre-wrap;">
Hal ini dapat sangat membantu jika Anda belum menentukan properti area pandang untuk halaman Anda.
- Gunakan algoritme tata letak
TEXT_AUTOSIZING
baru:Jika Anda menggunakan kolom sempit sebagai cara untuk membuat spektrum situs desktop yang lebih luas menjadi lebih mudah dibaca di perangkat seluler dan Anda tidak dapat mengubah konten HTML, algoritme
TEXT_AUTOSIZING
baru dapat menjadi alternatif yang sesuai untukNARROW_COLUMNS
.
Selain itu, nilai SINGLE_COLUMN
—yang sebelumnya tidak digunakan lagi — juga tidak didukung lagi di versi baru WebView
.
Menangani Peristiwa Sentuh di JavaScript
Jika halaman web Anda secara langsung menangani peristiwa sentuh di WebView
, pastikan Anda juga menangani peristiwa touchcancel
. Ada beberapa skenario di mana touchcancel
akan dipanggil, yang dapat menyebabkan masalah jika tidak diterima:
- Sebuah elemen disentuh (sehingga
touchstart
dantouchmove
akan dipanggil) dan halaman di-scroll, akan menyebabkantouchcancel
dimunculkan. - Sebuah elemen disentuh (
touchstart
dipanggil), tetapievent.preventDefault()
tidak dipanggil, sehingga mengakibatkantouchcancel
dimunculkan pada waktu yang tepat (sehinggaWebView
mengasumsikan bahwa Anda tidak ingin menggunakan peristiwa sentuh).