ウェブベースのコンテンツ(HTML、JavaScript、 CSS - 静的にコンパイルしてアプリに インターネットで取得するよりも はるかに効率的です
アプリ内コンテンツは、インターネット アクセスを必要としないため、ユーザーの帯域幅を消費しません。条件
コンテンツが WebView
専用に設計されている(つまり、
ネイティブ アプリとの通信に依存しているため、ユーザーが誤って
ウェブブラウザで読み込みます。
ただし、アプリ内コンテンツには欠点もあります。ウェブベースのコンテンツの更新 新しいアプリ アップデートを配信することが求められ、情報が一致しない可能性がある ウェブサイトのコンテンツとアプリのコンテンツの間に 違いがあることに ユーザーが使用しているアプリのバージョンが古い
WebViewAssetLoader
WebViewAssetLoader
:
アプリ内コンテンツを柔軟かつ効率的に読み込む方法を
WebView
オブジェクト。このクラスは、
次のとおりです。
- 同一オリジンとの互換性を確保するために HTTP(S) URL を使用してコンテンツを読み込む に関するポリシーに準拠する必要があります。
- JavaScript、CSS、画像、iframe などのサブリソースを読み込む。
メイン アクティビティ ファイルに WebViewAssetLoader
を含めます。以下は、
アセット フォルダからシンプルなウェブ コンテンツを読み込む例:
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 などのテキスト ファイルは、アセットに属します。
- 画像やその他のバイナリ ファイルはリソースに属します。
テキストベースのウェブ ファイルをプロジェクトに追加する手順は次のとおりです。
- Android Studio でアプリを右クリックして、src >main フォルダ
次に、[新規 >ディレクトリをご覧ください。
<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> 図 1.アセット フォルダを できます。 - フォルダに「assets」という名前を付けます。
図 2. アセット フォルダに名前を付けます。 - assets フォルダを右クリックして、[新規] >File を使用します。
「
index.html
」と入力して Return キーを押します。 Enter キーを押します。 <ph type="x-smartling-placeholder"></ph> <ph type="x-smartling-placeholder">
</ph> 図 3. index.html
を作成する 表示されます。 - 前の手順を繰り返して、Cloud Storage バケットの空のファイルを
stylesheet.css
。 - 次の 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;
}
```
画像ベースのウェブファイルをプロジェクトに追加する手順は次のとおりです。
ダウンロード:
Android_symbol_green_RGB.png
ローカルマシンにコピーされます。ファイル名を
android_robot.png
に変更します。プロジェクトの
main/res/drawable
ディレクトリにファイルを手動で移動します。 できます。
図 4 は、追加した画像と上記のコードサンプルのテキストを示しています。 表示されます。

アプリを完成させるには、次の手順を行います。
ハンドラを登録し、
AssetLoader
次のコードをonCreate()
メソッドに追加します。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));次のコードを
onCreate()
メソッドに追加して、コンテンツを読み込みます。
アプリ内コンテンツとウェブサイトのリソースを組み合わせる
場合によっては、アプリ内のコンテンツと
たとえばウェブサイトの CSS でスタイル設定されたアプリ内 HTML ページなど)です。
WebViewAssetLoader
はこのユースケースをサポートします。登録済みの
PathHandler
個のインスタンスが指定されたパスのリソースを検出できる(WebView
がフォール)
コンテンツの読み込みに戻りますアプリ内コンテンツと
ディレクトリ パス(/assets/
や
/resources/
: アプリ内リソース用。Cloud Storage バケットのリソースを
それらのロケーションで
ウェブサイトにアクセスする必要があります
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()
アプリアセットは不要です次のコードのように使用できます。
サンプル:
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 を使用してエンコードすることを強くおすすめします。
これをプログラムで行うようにします。次のコードサンプルをご覧ください。
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()
またはXMLHttpRequest
。loadData()
では内部でdata:
個の URL が使用されるため、 代わりにWebViewAssetLoader
またはloadDataWithBaseURL()
を使用してください。- ただし、
WebSettings.setAllowFileAccessFromFileURLs()
およびWebSettings.setAllowUniversalAccessFromFileURLs()
file://
の URL の問題を回避できます。このような設定は、 変更すると、アプリがファイルベースに対して脆弱になるため、true
保護します。すべての API レベルで、これらを明示的にfalse
に設定することをおすすめします。 セキュリティを強化します - 同じ理由で、
file://android_assets/
とfile://android_res/
件の URL。AssetsHandler
とResourcesHandler
一時的な置換を目的としています - 使用を避けるべき表現:
MIXED_CONTENT_ALWAYS_ALLOW
。 通常、この設定は必要ないため、アプリのセキュリティが低下します。 アプリ内コンテンツの読み込みには、同じスキーム(HTTP または 使用し、Google のインフラストラクチャでMIXED_CONTENT_COMPATIBILITY_MODE
またはMIXED_CONTENT_NEVER_ALLOW
, あります。