使用目标API 24链接到WebView中的本地文件的HTML链接 [英] HTML link to local file in WebView with target API 24

查看:148
本文介绍了使用目标API 24链接到WebView中的本地文件的HTML链接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果定位到API 24或更高版本,如何使用HTML链接导航到 WebView 中的本地文件(HTML页面)?

之前已经对此进行了讨论,解决方案使用 file:// URI方案.到目前为止有效的是使用

 < a href ="file:///android_asset/my_page.html">转到本地页面</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通过Intent.getData()在应用程序之外公开...mypackage.myapp W/System.err:位于org.chromium.android_webview.ResourcesContextWrapperFactory $ WebViewContextWrapper.startActivity(ResourcesContextWrapperFactory.java:121)mypackage.myapp W/System.err:位于org.chromium.android_webview.AwContentsClient.sendBrowsingIntent(AwContentsClient.java:203) 

根据文档,当一个应用程序向另一个应用程序公开 file:// Uri"时,抛出此错误.我不知道为什么会这样,因为根据日志,一切似乎都发生在 mypackage.myapp 内.

文档建议改为使用 content:// URI方案,但这不适用于HTML文件.

解决方案

以下解决方法(基于此答案)拦截 file:// URI在 WebView 中的加载,然后使用 WebView.loadUrl(...).这可以通过在传递给 WebView WebViewClient 中覆盖 WebView.shouldOverrideUrlLoading 来实现,例如初始化时.

由于API 24中对该方法进行了API更改,因此为了兼容,代码中有两个版本(从技术上讲,在API <24情况下,一个版本也可以像以前一样进行操作,请打开 WebView file:// URI,因为在运行API< 24的设备上不会引发该异常.

  if(android.os.Build.VERSION.SDK_INT> = 24){webView.setWebViewClient(new WebViewClient(){@Overridepublic boolean shouldOverrideUrlLoading(WebView webView,WebResourceRequest webResourceRequest){如果(webResourceRequest.getUrl().getScheme().equals("file")){webView.loadUrl(webResourceRequest.getUrl().toString());} 别的 {//如果URI未指向本地文件,请使用ACTION_VIEW Intent打开webView.getContext().startActivity(new Intent(Intent.ACTION_VIEW,webResourceRequest.getUrl()));}返回true;//在两种情况下,我们都是手动处理链接}});} 别的 {webView.setWebViewClient(new WebViewClient(){@Overridepublic boolean shouldOverrideUrlLoading(WebView webView,String url){如果(Uri.parse(url).getScheme().equals("file")){webView.loadUrl(url);} 别的 {//如果URI未指向本地文件,请使用ACTION_VIEW Intent打开webView.getContext().startActivity(new Intent(Intent.ACTION_VIEW,Uri.parse(url)));}返回true;//在两种情况下,我们都是手动处理链接}});} 

WebView 打开链接时出现异常的原因必须与 WebView 创建的 Intent 有关但我看不到它是否或如何暴露于另一个应用程序.

然后解决方法起作用是因为 WebView 对链接不执行任何操作(未创建 Intent ),而是单击链接时,应用程序获得控制权并将其传递给 WebView.loadUrl(...)来打开 file:// URI Direclty-似乎很好.

我假设(但不主张)关于安全性的考虑,这很好,因为URI仅用于加载指向该 WebView 的文件(如果出现问题,系统应抛出 FileUriExposedException ).

How can one use HTML links to navigate to local files (HTML pages) in WebView if targeting API 24 or higher?

This has been discussed before and solutions use the file:// URI scheme. What worked so far was using

<a href="file:///android_asset/my_page.html">Go to local page</a>

in an HTML file that is displayed in a WebView and clicking the link would load the local page app/src/main/assets/my_page.html.

However, starting from API 24, a FileUriExposedException is raised when clicking such a link. From 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)

According to the documentation, this is thrown when "an application exposes a file:// Uri to another app.". I wonder why this is the case, because according to the log everything seems to happen inside mypackage.myapp.

The documentation suggests using the content:// URI scheme instead, but this does not work in HTML files.

解决方案

The following workaround (based on this answer) intercepts the loading of a file:// URI in the WebView and then loads it directly by app code with WebView.loadUrl(...). This is possible by overriding WebView.shouldOverrideUrlLoading in a WebViewClient passed to the WebView, e.g. when initializing it.

As there was an API change for this method in API 24, for compatibility there are two versions in the code (technically in the API<24 case one could also do as before, letting WebView open the file:// URI because the exception is not raised on devices running API<24).

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

The reason why there is an exception when letting the WebView open the link must have something to do with the Intent created by the WebView but I don't see whether or how it is exposed to another app.

That the workaround works is then because the WebView does not do anything with the link (no Intent is created), instead, when the link is clicked, the app gets control and opens the file:// URI direclty by passing it to WebView.loadUrl(...) - which seems to be fine.

I assume (but do not claim) that regarding security this is fine because the URI is only used to load the file it points to in this single WebView (and if this was problematic the system should throw the FileUriExposedException).

这篇关于使用目标API 24链接到WebView中的本地文件的HTML链接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆