您可以提供基于网络的内容,如 HTML、JavaScript 和 CSS - 供应用使用,而您将其静态编译到应用中 而不是通过互联网提取
应用内的内容不需要接入互联网,也不会占用用户的带宽。如果
该内容仅面向WebView
而设计,也就是说,
取决于与本机应用的通信,因此用户不可能
将其加载到网络浏览器中。
不过,应用内的内容也有一些缺点。更新基于网络的内容 需要发布新的应用更新,并且有可能出现不一致的情况 网站上的内容与设备上应用中的内容之间 用户使用应用版本过旧。
WebViewAssetLoader
WebViewAssetLoader
是
一种灵活、高效的方法
WebView
对象。此类支持
以下:
- 使用 HTTP(S) 网址加载内容,以便与同源兼容 政策。
- 加载 JavaScript、CSS、图片和 iframe 等子资源。
将 WebViewAssetLoader
添加到主 activity 文件中。以下是
从资源文件夹加载简单网页内容的示例:
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 等文本文件都属于 assets。
- 映像和其他二进制文件属于资源。
如需向项目添加基于文本的 Web 文件,请执行以下操作:
- 在 Android Studio 中,右键点击 app >src >main 文件夹 然后选择新建 >目录。 <ph type="x-smartling-placeholder">
- 将该文件夹命名为“assets”。
- 右键点击 assets 文件夹,然后点击新建 >文件。
输入
index.html
,然后按回车键或 Enter 键。 <ph type="x-smartling-placeholder"> - 重复执行上一步,为
stylesheet.css
。 - 使用下面两个代码中的内容填充您创建的空文件 示例。
```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;
}
```
如需向项目中添加基于图片的 Web 文件,请执行以下操作:
下载
Android_symbol_green_RGB.png
复制到您的本地机器将文件重命名为
android_robot.png
。手动将文件移入项目的
main/res/drawable
目录中 您的硬盘。
图 4 显示了您添加的图片以及上述代码示例中的文本 在应用中呈现
如需完成该应用,请执行以下操作:
注册处理程序并配置
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));
将以下代码添加到
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 页面示例。
使用基准网址加载数据
当您的应用只需要加载 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:
个网址被视为不透明来源, 这意味着它们无法利用强大的 Web API,fetch()
或XMLHttpRequest
。loadData()
在内部使用data:
网址,因此我们建议您使用WebViewAssetLoader
或loadDataWithBaseURL()
。- 虽然
WebSettings.setAllowFileAccessFromFileURLs()
和WebSettings.setAllowUniversalAccessFromFileURLs()
可以解决file://
网址的问题,我们建议不要将 以便将其告知true
,因为这样做会导致您的应用容易受到文件级攻击 漏洞。我们建议在所有 API 级别上将这些级别明确设置为false
,从而获得最强大的安全机制。 - 出于同样的原因,我们建议不要使用
file://android_assets/
和file://android_res/
个网址。AssetsHandler
和ResourcesHandler
而是直接替换。 - 避免使用
MIXED_CONTENT_ALWAYS_ALLOW
。 此设置通常不是必需的,而且会降低应用的安全性。 我们建议您通过相同的协议(HTTP 或 HTTPS - 作为您网站的资源,并使用MIXED_CONTENT_COMPATIBILITY_MODE
或MIXED_CONTENT_NEVER_ALLOW
, 视情况而定。