【问题标题】:HTML link to local file in WebView with target API 24使用目标 API 24 指向 WebView 中本地文件的 HTML 链接
【发布时间】:2017-07-07 20:45:24
【问题描述】:

如果针对 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 文件。

【问题讨论】:

    标签: android android-webview


    【解决方案1】:

    以下解决方法(基于this answer)拦截file:// URI 在WebView 中的加载,然后通过应用代码直接通过WebView.loadUrl(...) 加载它。这可以通过在传递给WebViewWebViewClient 中覆盖WebView.shouldOverrideUrlLoading 来实现,例如初始化时。

    由于 API 24 中此方法的 API 有所更改,为了兼容性,代码中有两个版本(技术上,在 APIWebView 打开 file:// URI因为在运行 API

    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打开链接时出现异常的原因一定与WebView创建的Intent有关,但我不知道它是否或如何暴露给另一个应用程序.

    解决方法之所以有效,是因为WebView 不对链接做任何事情(没有创建Intent),而是在单击链接时,应用程序获得控制权并打开file:// URI 目录通过将其传递给WebView.loadUrl(...) - 这似乎很好。

    我假设(但不声称)关于安全性这很好,因为 URI 仅用于加载它在单个 WebView 中指向的文件(如果这是有问题的,系统应该抛出 FileUriExposedException )。

    【讨论】:

    • 你救了我的命,你太棒了!
    【解决方案2】:

    如果您需要加载其他页面,我从不以这种方式链接 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;
            }
        }
    }
    

    如果您有任何问题或仍然无法使用,请告诉我

    【讨论】:

      猜你喜欢
      • 2013-01-10
      • 2017-06-06
      • 2011-05-12
      • 2016-07-15
      • 2010-11-10
      • 1970-01-01
      • 2014-09-22
      • 1970-01-01
      • 2014-02-12
      相关资源
      最近更新 更多