載入應用程式內容

您可以提供網頁式內容,例如 HTML、JavaScript 和 CSS:以便您的應用程式使用靜態編譯成應用程式 而非透過網際網路擷取

應用程式內容不需要連上網際網路,也不需要耗用使用者的頻寬。如果 內容只為WebView設計,也就是說 這取決於與原生應用程式通訊,使用者不會意外 載入 Chrome 瀏覽器。

不過,應用程式內容有一些缺點。更新網頁式內容 必須發布新的應用程式更新, 網站內容與裝置上的應用程式內容結合 使用者的應用程式版本過舊

WebViewAssetLoader

WebViewAssetLoader是 能以靈活且有效率的方式,載入應用程式內容 WebView 物件。這個類別支援 包括:

  • 透過 HTTP(S) 網址載入內容以與相同來源相容 政策
  • 正在載入 JavaScript、CSS、圖片和 iframe 等子資源。

在主要活動檔案中加入 WebViewAssetLoader。以下是 從素材資源資料夾載入簡易網頁內容的範例:

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));
    }
}

您的應用程式必須根據自身需求設定 WebViewAssetLoader 例項。 下一節也有範例

建立應用程式內素材資源和資源

WebViewAssetLoader依賴 PathHandler 執行個體,載入與指定資源路徑相對應的資源。雖然你 就能實作這個介面,根據應用程式的需求來擷取資源, Webkit 程式庫套裝組合 AssetsPathHandler敬上 和 ResourcesPathHandler。 分別載入 Android 素材資源和資源

如要開始使用,請建立應用程式的素材資源和資源。一般而言, :

  • HTML、JavaScript 和 CSS 等文字檔案屬於素材資源。
  • 映像檔和其他二進位檔案屬於資源。

如要在專案中加入文字型網路檔案,請按照下列步驟操作:

  1. 在 Android Studio 中,於應用程式 > 上按一下滑鼠右鍵 >src >main 資料夾 然後選擇「New」(新增) > Directory
    顯示 Android Studio 建立目錄選單的圖片
    圖 1.為以下報表建立素材資源資料夾: 專案。
  2. 將資料夾命名為「assets」。
    顯示素材資源資料夾的圖片
    圖 2.為素材資源資料夾命名。
  3. 在「assets」資料夾上按一下滑鼠右鍵,然後依序點選「新增」>「新增」檔案。 輸入 index.html,然後按下 Return 鍵或 Enter 鍵。
  4. 重複上述步驟,為 stylesheet.css
  5. 在您建立的空白檔案中,填入接下來兩組程式碼中的內容 樣本。
```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;
}
```

如要在專案中新增圖片式網路檔案,請按照下列步驟操作:

  1. 下載 Android_symbol_green_RGB.png敬上 檔案複製到本機電腦

  2. 將檔案重新命名為 android_robot.png

  3. 手動將檔案移至專案的 main/res/drawable 目錄: 。

圖 4 顯示您新增的圖片以及上述程式碼範例中的文字 顯示在應用程式中的結果

顯示應用程式轉譯輸出內容的圖片
圖 4. 應用程式內 HTML 檔案和圖片檔 顯示在應用程式中的結果
,瞭解如何調查及移除這項存取權。

如要完成這個應用程式,請按照下列步驟操作:

  1. 註冊處理常式並設定 AssetLoader,方法是新增 將下列程式碼新增至 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. 將下列程式碼加入 onCreate() 方法,即可載入內容:

    Kotlin

    webView.loadUrl("https://appassets.androidplatform.net/assets/index.html")
    

    Java

    mWebView.loadUrl("https://appassets.androidplatform.net/assets/index.html");
    

結合應用程式內容和您網站上的資源

應用程式可能需要載入 例如由您網站 CSS 設定樣式的應用程式內 HTML 頁面。 WebViewAssetLoader 支援此用途。如果沒有註冊 PathHandler 執行個體可以找到指定路徑的資源,WebView 會下降 即可返回從網際網路載入內容。如果將應用程式內內容與 請保留網站資源的目錄路徑,例如 /assets//resources/,用於應用程式內資源。請避免儲存 打造更多專屬網站

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);

觀看以下網站的 WebView 示範: GitHub 範例,瞭解用於擷取網站代管 JSON 資料的應用程式內 HTML 網頁範例。

loadDataWithBaseURL

如果您的應用程式只需要載入 HTML 網頁,且不需要攔截 子資源,請考慮使用 loadDataWithBaseURL()、 這項操作不需要應用程式素材資源您可以使用,如以下程式碼所示 範例:

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);

請謹慎選擇引數值,請把握以下幾項重點:

  • baseUrl:這是 HTML 內容載入時使用的網址。這必須是 HTTP(S) 網址。
  • data:這是您要以字串形式顯示的 HTML 內容。
  • mimeType:通常必須設為 text/html
  • encoding:如果 baseUrl 是 HTTP(S) 網址,則不使用此方法,因此 已設為 null
  • historyUrl:這是與 baseUrl 相同的值。

我們強烈建議您使用 HTTP(S) 網址做為 baseUrl,這有助於 請確保您的應用程式遵循相同來源政策。

如果找不到適合內容的baseUrl,且想要使用 loadData(), 你就必須使用 百分比編碼Base64 編碼。 強烈建議選用 Base64 編碼,並使用 Android API 進行編碼 以程式輔助的方式建構內容,如以下程式碼範例所示:

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");

應避免的事項

你可以透過多種方式載入應用程式內容,但我們強烈建議你 針對他們:

  • 系統會將 file:// 個網址和 data: 網址視為不透明來源。 因此他們無法運用各種強大的網路 API,例如 fetch()XMLHttpRequestloadData() 內部使用 data: 網址,因此建議使用 WebViewAssetLoaderloadDataWithBaseURL()
  • 雖然 WebSettings.setAllowFileAccessFromFileURLs()敬上 和 WebSettings.setAllowUniversalAccessFromFileURLs()。 可協助解決 file:// 個網址的問題,因此建議您不要設定 導致這些事件傳送給 true,因為這樣會導致應用程式容易遭受檔案型攻擊 入侵建議您在所有 API 級別中明確地將這些屬性設為 false。 以獲得最強大的安全防護
  • 基於相同的理由,我們建議不要使用 file://android_assets/file://android_res/ 個網址。AssetsHandlerResourcesHandler 類別的用途是直接取代。
  • 避免使用 MIXED_CONTENT_ALWAYS_ALLOW。 一般來說,這項設定並非必要,會降低應用程式的安全性。 我們建議透過 HTTP 或 HTTPS—做為網站的資源 MIXED_CONTENT_COMPATIBILITY_MODE敬上 或 MIXED_CONTENT_NEVER_ALLOW, 。