如果定位到API 24或更高版本,如何使用HTML链接导航到WebView
中的本地文件(HTML页面)?
之前已经讨论过,解决方案使用file://
URI方案。
到目前为止工作的是
<a href="file:///android_asset/my_page.html">Go to local page</a>
在WebView
中显示的HTML文件中,点击该链接会加载本地页面app/src/main/assets/my_page.html
。
但是,从API 24开始,单击此类链接时会引发FileUriExposedException。来自logcat:
mypackage.myapp W/System.err: android.os.FileUriExposedException: file:///android_asset/my_page.html exposed beyond app through Intent.getData()
...
mypackage.myapp W/System.err: at org.chromium.android_webview.ResourcesContextWrapperFactory$WebViewContextWrapper.startActivity(ResourcesContextWrapperFactory.java:121)
mypackage.myapp W/System.err: at org.chromium.android_webview.AwContentsClient.sendBrowsingIntent(AwContentsClient.java:203)
根据文档,当“应用程序将file://
Uri暴露给另一个应用程序时,会抛出此错误。”我想知道为什么会这样,因为根据日志,一切似乎都发生在mypackage.myapp
内。
文档建议使用content://
URI方案,但这在HTML文件中不起作用。
答案 0 :(得分:3)
以下解决方法(基于this answer)拦截file://
中WebView
URI的加载,然后使用WebView.loadUrl(...)
的应用代码直接加载它。这可以通过覆盖传递给WebView.shouldOverrideUrlLoading
的{{1}}中的WebViewClient
来实现,例如初始化时。
由于API 24中的此方法有API更改,为了兼容性,代码中有两个版本(技术上在API&lt; 24情况下,也可以像以前一样,让WebView
打开{{ 1}} URI,因为在运行API&lt; 24)的设备上不会引发异常。
WebView
让file://
打开链接时出现异常的原因必须与if (android.os.Build.VERSION.SDK_INT >= 24) {
webView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView webView, WebResourceRequest webResourceRequest) {
if (webResourceRequest.getUrl().getScheme().equals("file")) {
webView.loadUrl(webResourceRequest.getUrl().toString());
} else {
// If the URI is not pointing to a local file, open with an ACTION_VIEW Intent
webView.getContext().startActivity(new Intent(Intent.ACTION_VIEW, webResourceRequest.getUrl()));
}
return true; // in both cases we handle the link manually
}
});
} else {
webView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView webView, String url) {
if (Uri.parse(url).getScheme().equals("file")) {
webView.loadUrl(url);
} else {
// If the URI is not pointing to a local file, open with an ACTION_VIEW Intent
webView.getContext().startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
}
return true; // in both cases we handle the link manually
}
});
}
创建的WebView
有关,但我不知道是否或如何它暴露给另一个应用程序。
解决方法的工作原理是因为Intent
对链接没有任何作用(没有创建WebView
),而是在点击链接时,应用程序获得控制权并打开{ {1}} URI direclty将其传递给WebView
- 这似乎没问题。
我假设(但不要求)关于安全性这很好,因为URI仅用于加载它指向的单个Intent
中的文件(如果这是有问题的,系统应抛出{ {1}})。
答案 1 :(得分:0)
如果您需要加载其他页面,我从不在HTML中链接:
<a href="file:///android_asset/my_page.html">Go to local page</a>
我这样链接是因为我的地图结构看起来像this:
<a href="my_page.html">Go to local page</a>
您只需在MainActivity.java中使用该方法即可:
private class MyBrowser extends WebViewClient {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith("tel:") || url.startsWith("sms:") || url.startsWith("smsto:") || url.startsWith("mailto:") || url.startsWith("mms:") || url.startsWith("mmsto:") || url.startsWith("market:")) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(intent);
return true;
}
else {
view.loadUrl(url);
return true;
}
}
}
如果您有任何问题或仍然无法解决,请告诉我