Anda dapat menyediakan konten berbasis web—seperti HTML, JavaScript, dan CSS—untuk aplikasi Anda untuk menggunakan yang Anda kompilasi secara statis ke dalam aplikasi, bukan daripada pengambilan melalui internet.
Konten dalam aplikasi tidak memerlukan akses internet atau menggunakan bandwidth pengguna. Jika
konten ini didesain khusus hanya untuk WebView
—artinya,
bergantung pada cara berkomunikasi dengan aplikasi asli—maka pengguna tidak dapat
memuatnya di {i>browser<i} web.
Namun, konten dalam aplikasi memiliki beberapa kelemahan. Memperbarui konten berbasis web memerlukan pengiriman update aplikasi baru, dan ada kemungkinan ketidakcocokan konten antara yang ada di situs web dan yang ada di aplikasi pada perangkat jika pengguna memiliki versi aplikasi yang sudah tidak berlaku.
WebViewAssetLoader
WebViewAssetLoader
adalah
cara yang fleksibel dan berperforma tinggi untuk memuat konten dalam aplikasi dengan
Objek WebView
. Class ini mendukung class
berikut ini:
- Memuat konten dengan URL HTTP(S) agar kompatibel dengan origin yang sama kebijakan kami.
- Memuat subresource seperti JavaScript, CSS, gambar, dan iframe.
Sertakan WebViewAssetLoader
dalam file aktivitas utama Anda. Berikut adalah
contoh pemuatan konten web sederhana dari folder aset:
Kotlin
private class LocalContentWebViewClient(private val assetLoader: WebViewAssetLoader) : WebViewClientCompat() { @RequiresApi(21) override fun shouldInterceptRequest( view: WebView, request: WebResourceRequest ): WebResourceResponse? { return assetLoader.shouldInterceptRequest(request.url) } // To support API < 21. override fun shouldInterceptRequest( view: WebView, url: String ): WebResourceResponse? { return assetLoader.shouldInterceptRequest(Uri.parse(url)) } }
Java
private static class LocalContentWebViewClient extends WebViewClientCompat { private final WebViewAssetLoader mAssetLoader; LocalContentWebViewClient(WebViewAssetLoader assetLoader) { mAssetLoader = assetLoader; } @Override @RequiresApi(21) public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { return mAssetLoader.shouldInterceptRequest(request.getUrl()); } @Override @SuppressWarnings("deprecation") // To support API < 21. public WebResourceResponse shouldInterceptRequest(WebView view, String url) { return mAssetLoader.shouldInterceptRequest(Uri.parse(url)); } }
Aplikasi Anda harus mengonfigurasi instance WebViewAssetLoader
agar sesuai dengan kebutuhannya. Tujuan
bagian berikutnya memiliki contoh.
Membuat aset dan resource dalam aplikasi
WebViewAssetLoader
bergantung pada
PathHandler
untuk memuat resource yang sesuai dengan jalur resource tertentu. Meskipun Anda
bisa mengimplementasikan antarmuka ini untuk mengambil sumber daya yang dibutuhkan aplikasi Anda,
Paket library Webkit
AssetsPathHandler
dan
ResourcesPathHandler
masing-masing untuk memuat aset dan resource Android.
Untuk memulai, buat aset dan resource untuk aplikasi Anda. Umumnya, hal-hal berikut berlaku:
- File teks seperti HTML, JavaScript, dan CSS termasuk dalam aset.
- Gambar dan file biner lainnya termasuk dalam resource.
Untuk menambahkan file web berbasis teks ke project, lakukan hal berikut:
- Di Android Studio, klik kanan app > src > folder utama lalu pilih New > Direktori.
- Beri nama folder "assets".
- Klik kanan folder assets, lalu klik New > File.
Masukkan
index.html
, lalu tekan tombol Return atau Tombol Enter. - Ulangi langkah sebelumnya untuk membuat {i>file<i} kosong untuk
stylesheet.css
. - Isi file kosong yang Anda buat dengan konten di dua kode berikutnya sampel.
```html
<!-- index.html content -->
<html>
<head>
<!-- Tip: Use relative URLs when referring to other in-app content to give
your app code the flexibility to change the scheme or domain as
necessary. -->
<link rel="stylesheet" href="/assets/stylesheet.css">
</head>
<body>
<p>This file is loaded from in-app content.</p>
<p><img src="/res/drawable/android_robot.png" alt="Android robot" width="100"></p>
</body>
</html>
```
```css
<!-- stylesheet.css content -->
body {
background-color: lightblue;
}
```
Untuk menambahkan file web berbasis gambar ke project Anda, lakukan hal berikut:
Unduh
Android_symbol_green_RGB.png
ke komputer lokal Anda.Ganti nama file menjadi
android_robot.png
.Pindahkan file secara manual ke direktori
main/res/drawable
project Anda di {i>hard drive<i} Anda.
Gambar 4 menunjukkan gambar yang Anda tambahkan dan teks dari contoh kode sebelumnya yang dirender dalam aplikasi.
Untuk menyelesaikan aplikasi, lakukan hal berikut:
Daftarkan pengendali dan konfigurasikan
AssetLoader
dengan menambahkan kode berikut ke metodeonCreate()
:Kotlin
val assetLoader = WebViewAssetLoader.Builder() .addPathHandler("/assets/", AssetsPathHandler(this)) .addPathHandler("/res/", ResourcesPathHandler(this)) .build() webView.webViewClient = LocalContentWebViewClient(assetLoader)
Java
final WebViewAssetLoader assetLoader = new WebViewAssetLoader.Builder() .addPathHandler("/assets/", new WebViewAssetLoader.AssetsPathHandler(this)) .addPathHandler("/res/", new WebViewAssetLoader.ResourcesPathHandler(this)) .build(); mWebView.setWebViewClient(new LocalContentWebViewClient(assetLoader));
Muat konten dengan menambahkan kode berikut ke metode
onCreate()
:Kotlin
webView.loadUrl("https://appassets.androidplatform.net/assets/index.html")
Java
mWebView.loadUrl("https://appassets.androidplatform.net/assets/index.html");
Gabungkan konten dalam aplikasi dengan referensi dari situs Anda
Aplikasi Anda mungkin perlu memuat campuran konten dalam aplikasi dan konten dari
internet, seperti halaman HTML dalam aplikasi yang diatur oleh CSS situs Anda.
WebViewAssetLoader
mendukung kasus penggunaan ini. Jika tidak ada
Instance PathHandler
dapat menemukan resource untuk jalur yang diberikan, WebView
jatuh
kembali memuat konten dari internet. Jika Anda mencampur konten dalam aplikasi dengan
resource dari situs Anda, jalur direktori reservasi, seperti /assets/
atau
/resources/
, untuk resource dalam aplikasi. Hindari menyimpan sumber daya apa pun dari
di lokasi tersebut.
Kotlin
val assetLoader = WebViewAssetLoader.Builder() .setDomain("example.com") // Replace this with your website's domain. .addPathHandler("/assets/", AssetsPathHandler(this)) .build() webView.webViewClient = LocalContentWebViewClient(assetLoader) val inAppHtmlUrl = "https://example.com/assets/index.html" webView.loadUrl(inAppHtmlUrl) val websiteUrl = "https://example.com/website/data.json" // JavaScript code to fetch() content from the same origin. val jsCode = "fetch('$websiteUrl')" + ".then(resp => resp.json())" + ".then(data => console.log(data));" webView.evaluateJavascript(jsCode, null)
Java
final WebViewAssetLoader assetLoader = new WebViewAssetLoader.Builder() .setDomain("example.com") // Replace this with your website's domain. .addPathHandler("/assets/", new AssetsPathHandler(this)) .build(); mWebView.setWebViewClient(new LocalContentWebViewClient(assetLoader)); String inAppHtmlUrl = "https://example.com/assets/index.html"; mWebView.loadUrl(inAppHtmlUrl); String websiteUrl = "https://example.com/website/data.json"; // JavaScript code to fetch() content from the same origin. String jsCode = "fetch('" + websiteUrl + "')" + ".then(resp => resp.json())" + ".then(data => console.log(data));"; mWebView.evaluateJavascript(jsCode, null);
Lihat demo WebView
di
GitHub
untuk contoh halaman HTML dalam aplikasi yang mengambil data JSON yang dihosting web.
loadDataWithBaseURL
Saat aplikasi Anda hanya perlu memuat halaman HTML dan tidak perlu mencegat
sub-sumber daya, pertimbangkan untuk menggunakan
loadDataWithBaseURL()
,
yang tidak memerlukan aset aplikasi. Anda dapat menggunakannya seperti yang ditunjukkan pada kode berikut
contoh:
Kotlin
val html = "<html><body><p>Hello world</p></body></html>" val baseUrl = "https://example.com/" webView.loadDataWithBaseURL(baseUrl, html, "text/html", null, baseUrl)
Java
String html = "<html><body><p>Hello world</p></body></html>"; String baseUrl = "https://example.com/"; mWebView.loadDataWithBaseURL(baseUrl, html, "text/html", null, baseUrl);
Pilih nilai argumen dengan cermat. Pertimbangkan hal berikut:
baseUrl
: ini adalah URL yang digunakan untuk memuat konten HTML Anda. Ini harus berupa URL HTTP(S).data
: ini adalah konten HTML yang ingin Anda tampilkan, sebagai string.mimeType
: kunci ini biasanya harus ditetapkan ketext/html
.encoding
: ini tidak digunakan jikabaseUrl
adalah URL HTTP(S), sehingga dapat ditetapkan kenull
.historyUrl
: ini ditetapkan ke nilai yang sama denganbaseUrl
.
Sebaiknya gunakan URL HTTP(S) sebagai baseUrl
, karena hal ini membantu
memastikan aplikasi Anda mematuhi kebijakan origin yang sama.
Jika Anda tidak dapat menemukan baseUrl
yang sesuai untuk konten Anda dan memilih untuk menggunakannya
loadData()
,
Anda harus mengenkode konten dengan
encoding persen
atau
Base64
encoding.
Kami sangat menyarankan untuk memilih encoding Base64 dan menggunakan Android API untuk
ini secara terprogram, seperti yang ditunjukkan dalam contoh kode berikut:
Kotlin
val encodedHtml: String = Base64.encodeToString(html.toByteArray(), Base64.NO_PADDING) webView.loadData(encodedHtml, mimeType, "base64")
Java
String encodedHtml = Base64.encodeToString(html.getBytes(), Base64.NO_PADDING); mWebView.loadData(encodedHtml, mimeType, "base64");
Hal yang perlu dihindari
Ada beberapa cara lain untuk memuat konten dalam aplikasi, tetapi kami sangat menyarankan terhadap mereka:
- URL
file://
dandata:
URL dianggap asal buram, artinya mereka tidak dapat memanfaatkan API web yang canggih sepertifetch()
atauXMLHttpRequest
.loadData()
secara internal menggunakandata:
URL, jadi sebaiknya Anda menggunakanWebViewAssetLoader
atauloadDataWithBaseURL()
saja. - Meskipun
WebSettings.setAllowFileAccessFromFileURLs()
danWebSettings.setAllowUniversalAccessFromFileURLs()
dapat mengatasi masalah dengan URLfile://
, sebaiknya jangan tetapkan ini untuktrue
karena hal itu membuat aplikasi Anda rentan terhadap operasi berbasis file eksploit. Sebaiknya tetapkan ini secara eksplisit kefalse
di semua level API untuk keamanan terkuat. - Untuk alasan yang sama, sebaiknya jangan gunakan
file://android_assets/
danfile://android_res/
URL.AssetsHandler
danResourcesHandler
kelas dimaksudkan sebagai pengganti langsung. - Hindari penggunaan
MIXED_CONTENT_ALWAYS_ALLOW
Setelan ini umumnya tidak diperlukan dan akan melemahkan keamanan aplikasi Anda. Sebaiknya muat konten dalam aplikasi melalui skema yang sama—HTTP atau HTTPS—sebagai sumber daya situs web dan penggunaanMIXED_CONTENT_COMPATIBILITY_MODE
atauMIXED_CONTENT_NEVER_ALLOW
, sebagaimana mestinya.