アプリ内コンテンツを読み込む

ウェブベースのコンテンツ(HTML、JavaScript、 CSS - 静的にコンパイルしてアプリに インターネットで取得するよりも はるかに効率的です

アプリ内コンテンツは、インターネット アクセスを必要としないため、ユーザーの帯域幅を消費しません。条件 コンテンツが WebView 専用に設計されている(つまり、 ネイティブ アプリとの通信に依存しているため、ユーザーが誤って ウェブブラウザで読み込みます。

ただし、アプリ内コンテンツには欠点もあります。ウェブベースのコンテンツの更新 新しいアプリ アップデートを配信することが求められ、情報が一致しない可能性がある ウェブサイトのコンテンツとアプリのコンテンツの間に 違いがあることに ユーザーが使用しているアプリのバージョンが古い

WebViewAssetLoader

WebViewAssetLoader: アプリ内コンテンツを柔軟かつ効率的に読み込む方法を WebView オブジェクト。このクラスは、 次のとおりです。

メイン アクティビティ ファイルに WebViewAssetLoader を含めます。以下は、 アセット フォルダからシンプルなウェブ コンテンツを読み込む例:

KotlinJava
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))
   
}
}
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 フォルダ 次に、[新規 >ディレクトリをご覧ください。 <ph type="x-smartling-placeholder">
    </ph> Android Studio のディレクトリ作成メニューを示す画像 <ph type="x-smartling-placeholder">
    </ph> 図 1.アセット フォルダを できます。
  2. フォルダに「assets」という名前を付けます。
    アセット フォルダを示す画像
    図 2. アセット フォルダに名前を付けます。
  3. assets フォルダを右クリックして、[新規] >File を使用します。 「index.html」と入力して Return キーを押します。 Enter キーを押します。 <ph type="x-smartling-placeholder">
  4. 前の手順を繰り返して、Cloud Storage バケットの空のファイルを stylesheet.css
  5. 次の 2 つのコードで、作成した空のファイルにコンテンツを入力します。 提供します
```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() メソッドに追加します。

    KotlinJava
    val assetLoader = WebViewAssetLoader.Builder()
                           
    .addPathHandler("/assets/", AssetsPathHandler(this))
                           
    .addPathHandler("/res/", ResourcesPathHandler(this))
                           
    .build()
    webView
    .webViewClient = LocalContentWebViewClient(assetLoader)
    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() メソッドに追加して、コンテンツを読み込みます。

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

アプリ内コンテンツとウェブサイトのリソースを組み合わせる

場合によっては、アプリ内のコンテンツと たとえばウェブサイトの CSS でスタイル設定されたアプリ内 HTML ページなど)です。 WebViewAssetLoader はこのユースケースをサポートします。登録済みの PathHandler 個のインスタンスが指定されたパスのリソースを検出できる(WebView がフォール) コンテンツの読み込みに戻りますアプリ内コンテンツと ディレクトリ パス(/assets//resources/: アプリ内リソース用。Cloud Storage バケットのリソースを それらのロケーションで ウェブサイトにアクセスする必要があります

KotlinJava
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)
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() アプリアセットは不要です次のコードのように使用できます。 サンプル:

KotlinJava
val html = "<html><body><p>Hello world</p></body></html>"
val baseUrl = "https://example.com/"

webView
.loadDataWithBaseURL(baseUrl, html, "text/html", null, baseUrl)
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 コンテンツが読み込まれる URL。名前は HTTP(S) URL。
  • data: これは文字列として表示する HTML コンテンツです。
  • mimeType: 通常、これは text/html に設定する必要があります。
  • encoding: baseUrl が HTTP(S) URL の場合は使用しないため、 null に設定。
  • historyUrl: baseUrl と同じ値に設定されます。

baseUrl として HTTP(S) URL を使用することを強くおすすめします。これにより、 アプリが同一オリジン ポリシーに準拠していることを確認する。

コンテンツに適した baseUrl が見つからず、 loadData(), 独自の暗号鍵でコンテンツをエンコード パーセント エンコード または Base64 ありません。 Base64 エンコードを選択し、Android API を使用してエンコードすることを強くおすすめします。 これをプログラムで行うようにします。次のコードサンプルをご覧ください。

KotlinJava
val encodedHtml: String = Base64.encodeToString(html.toByteArray(), Base64.NO_PADDING)

webView
.loadData(encodedHtml, mimeType, "base64")
String encodedHtml = Base64.encodeToString(html.getBytes(), Base64.NO_PADDING);

mWebView
.loadData(encodedHtml, mimeType, "base64");

非推奨事項

アプリ内コンテンツを読み込む方法は他にもいくつかありますが、 対抗できます。

  • file:// URL と data: URL は不透明オリジンと見なされます。 つまり、次のような強力なウェブ API を fetch() または XMLHttpRequestloadData() では内部で data: 個の URL が使用されるため、 代わりに WebViewAssetLoader または loadDataWithBaseURL() を使用してください。
  • ただし、 WebSettings.setAllowFileAccessFromFileURLs() および WebSettings.setAllowUniversalAccessFromFileURLs() file:// の URL の問題を回避できます。このような設定は、 変更すると、アプリがファイルベースに対して脆弱になるため、true 保護します。すべての API レベルで、これらを明示的に false に設定することをおすすめします。 セキュリティを強化します
  • 同じ理由で、file://android_assets/file://android_res/ 件の URL。AssetsHandlerResourcesHandler 一時的な置換を目的としています
  • 使用を避けるべき表現: MIXED_CONTENT_ALWAYS_ALLOW。 通常、この設定は必要ないため、アプリのセキュリティが低下します。 アプリ内コンテンツの読み込みには、同じスキーム(HTTP または 使用し、Google のインフラストラクチャで MIXED_CONTENT_COMPATIBILITY_MODE または MIXED_CONTENT_NEVER_ALLOW, あります。