【问题标题】:Android WebView (4.4) Converts Custom URLAndroid WebView (4.4) 转换自定义URL
【发布时间】:2016-04-14 15:55:51
【问题描述】:

我有一个应用程序大量使用 Android WebView 来显示我的自定义 HTML 内容。最新的 Android 更新 (4.4/Kit-Kat/SDK-19) 采用了重新设计的 WebView

我的一位使用 Nexus 5 的用户报告了一个问题,即某些链接会导致应用崩溃。我在 4.4 模拟器中运行并调试到我的WebViewClientshouldOverrideUrlLoading() 方法。在所有先前测试过的 Android 版本(2.2-4.3)上,传递给方法的 url String 包含我的自定义 url,其中包含“/”字符。在 4.4 中,完全相同的链接现在有“\”字符。

这对我来说没有任何意义。我加载的 HTML 完全相同,所以不知何故新的WebView 将我所有的斜杠都转换成了反斜杠。

为什么新的WebView 会这样做?

【问题讨论】:

    标签: android android-webview android-4.4-kitkat


    【解决方案1】:

    URL 处理的变化是一个已知问题。详情请参阅migration guide

    在这种特殊情况下的行为将取决于您的基本 URL 的方案是什么,根据您的描述,我猜您的基本 URL 的方案是“http(s)://”,在这种情况下 Chromium WebView 执行URL normalization.

    在这种情况下,您可能需要考虑使用 URI class 来处理 Classic 和 Chromium WebView 之间的差异。

    【讨论】:

    • 最初我接受了我自己的答案,因为它是我问题的直接答案,但是这个答案帮助了我其他一些地方,因为 4.4正在处理我的自定义网址。所以谢谢!
    【解决方案2】:

    我做了更多的调试,发现我实际上把问题颠倒了。原来WebView 的旧版本做了URL 的转换,而不是新版本。

    我将格式与此类似的 HTML 加载到WebView

        <a href="this\\is\\my\\custom\\path">link</a>
    

    我使用双反斜杠作为分隔符,稍后在单击链接时解析数据。在旧版本的WebView 中,它会将我的双反斜杠字符转换为正斜杠。自从我在那个代码中已经很久了,我忘记了我调整了我的代码以使用正斜杠而不是原始 HTML 中的反斜杠。

    WebView 的新版本保留了我的自定义 URL 不变,为我提供了与原始 HTML 完全相同的字符串。所以原来旧的WebView 不是新的问题。

    【讨论】:

    【解决方案3】:

    新的 WebView 在请求资源和解析使用自定义 URL 方案的链接时应用了额外的限制。例如,如果您实现了诸如 shouldOverrideUrlLoading() 或 shouldInterceptRequest() 之类的回调,那么 WebView 只会针对有效的 URL 调用它们。

    如果您使用自定义 URL 方案或基本 URL,并注意到您的应用收到的对这些回调的调用较少或无法在 Android 4.4 上加载资源,请确保请求指定符合 RFC 3986 的有效 URL。

    例如,新的 WebView 可能不会为这样的链接调用您的 shouldOverrideUrlLoading() 方法:

    显示个人资料 用户点击此类链接的结果可能会有所不同:

    如果您通过调用 loadData() 或 loadDataWithBaseURL() 并使用无效或空的基本 URL 加载页面,那么您将不会收到页面上此类链接的 shouldOverrideUrlLoading() 回调。 注意:当您使用 loadDataWithBaseURL() 并且基础 URL 无效或设置为 null 时,您正在加载的内容中的所有链接都必须是绝对链接。

    如果您通过调用 loadUrl() 加载页面或使用 loadDataWithBaseURL() 提供了有效的基本 URL,那么您将收到页面上此类链接的 shouldOverrideUrlLoading() 回调,但您收到的 URL 将是绝对的,相对于当前页面。例如,您收到的 URL 将是“http://www.example.com/showProfile”,而不仅仅是“showProfile”。 您可以使用自定义方案,而不是如上所示在链接中使用简单字符串:

    <a href="example-app:showProfile">Show Profile</a>
    

    然后您可以在 shouldOverrideUrlLoading() 方法中处理此 URL,如下所示:

    // The URL scheme should be non-hierarchical (no trailing slashes)
      private static final String APP_SCHEME = "example-app:";
    
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        if (url.startsWith(APP_SCHEME)) {
            urlData = URLDecoder.decode(url.substring(APP_SCHEME.length()), "UTF-8");
           respondToData(urlData);
            return true;
        }
        return false;
    }
    

    如果您无法更改 HTML,那么您可以使用 loadDataWithBaseURL() 并设置由自定义方案和有效主机组成的基本 URL,例如“example-app:///”。例如:

    webView.loadDataWithBaseURL("example-app://example.co.uk/", HTML_DATA,
        null, "UTF-8", null);
    

    有效的主机名应符合 RFC 3986,并且在末尾包含尾部斜杠很重要,否则,来自加载页面的任何请求都可能被丢弃。

    【讨论】:

      【解决方案4】:

      为了避免4.4以下的webview将反斜杠转换为正斜杠,我只是转义我的url,然后在Java代码中,使用URI.decode来获取真正的url。这对我有用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-04-08
        相关资源
        最近更新 更多