Memuat konten dalam aplikasi

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:

  1. Di Android Studio, klik kanan app > src > folder utama lalu pilih New > Direktori.
    Gambar yang menampilkan menu buat direktori Android Studio
    Gambar 1. Buat folder aset untuk proyek.
  2. Beri nama folder "assets".
    Gambar yang menampilkan folder aset
    Gambar 2. Beri nama folder aset.
  3. Klik kanan folder assets, lalu klik New > File. Masukkan index.html, lalu tekan tombol Return atau Tombol Enter.
  4. Ulangi langkah sebelumnya untuk membuat {i>file<i} kosong untuk stylesheet.css.
  5. 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:

  1. Unduh Android_symbol_green_RGB.png ke komputer lokal Anda.

  2. Ganti nama file menjadi android_robot.png.

  3. 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.

Gambar yang menunjukkan output yang dirender oleh aplikasi
Gambar 4. File HTML dan file gambar dalam aplikasi yang dirender dalam aplikasi.

Untuk menyelesaikan aplikasi, lakukan hal berikut:

  1. Daftarkan pengendali dan konfigurasikan AssetLoader dengan menambahkan kode berikut ke metode onCreate():

    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));
    
  2. 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 ke text/html.
  • encoding: ini tidak digunakan jika baseUrl adalah URL HTTP(S), sehingga dapat ditetapkan ke null.
  • historyUrl: ini ditetapkan ke nilai yang sama dengan baseUrl.

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:// dan data: URL dianggap asal buram, artinya mereka tidak dapat memanfaatkan API web yang canggih seperti fetch() atau XMLHttpRequest. loadData() secara internal menggunakan data: URL, jadi sebaiknya Anda menggunakan WebViewAssetLoader atau loadDataWithBaseURL() saja.
  • Meskipun WebSettings.setAllowFileAccessFromFileURLs() dan WebSettings.setAllowUniversalAccessFromFileURLs() dapat mengatasi masalah dengan URL file://, sebaiknya jangan tetapkan ini untuk true karena hal itu membuat aplikasi Anda rentan terhadap operasi berbasis file eksploit. Sebaiknya tetapkan ini secara eksplisit ke false di semua level API untuk keamanan terkuat.
  • Untuk alasan yang sama, sebaiknya jangan gunakan file://android_assets/ dan file://android_res/ URL. AssetsHandler dan ResourcesHandler 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 penggunaan MIXED_CONTENT_COMPATIBILITY_MODE atau MIXED_CONTENT_NEVER_ALLOW, sebagaimana mestinya.