3

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

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

这对我来说没有任何意义。我加载的 HTML 完全相同,所以新的以某种方式将WebView我所有的斜杠都转换为反斜杠。

为什么新人WebView会这样做?

4

4 回答 4

1

URL 处理的更改是一个已知问题。有关更多详细信息,请参阅迁移指南

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

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

于 2013-11-13T11:19:05.837 回答
1

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

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

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

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

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

于 2013-11-11T18:51:55.690 回答
1

新的 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 并且在末尾包含尾部斜杠很重要,否则,来自加载页面的任何请求都可能被丢弃。

于 2016-04-14T07:55:51.270 回答
0

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

于 2015-05-05T15:54:08.517 回答