我的应用程序大量使用Android WebView
来显示我的自定义HTML内容。最新的Android更新(4.4 / Kit-Kat / SDK-19)采用了重新设计的WebView
。
我的一位使用Nexus 5的用户报告了某些链接导致应用崩溃的问题。我在4.4模拟器中运行并调试到我的WebViewClient
的{{1}}方法。在之前测试过的所有Android版本(2.2-4.3)中,传入方法的网址shouldOverrideUrlLoading()
都有我的自定义网址,其中包含“/”字符。在4.4中,完全相同的链接现在有“\”字符。
这对我没有任何意义。我加载完全相同的HTML,所以不知何故新的String
将我的所有斜杠转换为反斜杠。
为什么新的WebView
会这样做?
答案 0 :(得分:1)
我做了更多调试,发现我实际上已经解决了这个问题。原来WebView
的旧版本完成了URL
的转换,而不是新转换。
我将带有与此类似格式的HTML加载到WebView
:
<a href="this\\is\\my\\custom\\path">link</a>
我使用双反斜杠作为分隔符,并在单击链接后解析数据。在旧版本的WebView
中,它将我的双反斜杠字符转换为正斜杠。自从我进入该代码以来已经很久了,我忘记了我调整了我的代码以使用正斜杠而不是原始HTML中的反斜杠。
WebView
的新版本保留了我的自定义URL
,为我提供了与原始HTML完全相同的字符串。结果旧的WebView
是问题,而不是新问题。
答案 1 :(得分:1)
网址处理的变化是一个已知问题。有关详细信息,请参阅migration guide。
此特定情况下的行为将取决于您的基本URL的方案,从您描述的内容我猜测您的基本URL的方案是“http(s)://”,在这种情况下,Chromium WebView执行URL normalization
在这种情况下,您可能需要考虑使用URI class来处理Classic和Chromium WebView之间的差异。
答案 2 :(得分:0)
要避免webview下面4.4将反斜杠转换为正斜杠,我只是转义我的url,然后在Java代码中,使用URI.decode获取真正的url。这对我有用。
答案 3 :(得分:0)
在请求资源和解析使用自定义URL方案的链接时,新WebView会应用其他限制。例如,如果实现了诸如shouldOverrideUrlLoading()或shouldInterceptRequest()之类的回调,则WebView仅针对有效URL调用它们。
如果您使用的是自定义网址方案或基本网址,并注意到您的应用接收的回调次数较少或无法在Android 4.4上加载资源,请确保请求指定符合RFC 3986的有效网址。< / p>
例如,新的WebView可能不会为这样的链接调用你的shouldOverrideUrlLoading()方法:
显示个人资料 用户点击此类链接的结果可能会有所不同:
如果通过使用无效或空基URL调用loadData()或loadDataWithBaseURL()来加载页面,那么您将不会在页面上收到此类链接的shouldOverrideUrlLoading()回调。 注意:当您使用loadDataWithBaseURL()并且基本URL无效或设置为null时,您加载的内容中的所有链接都必须是绝对的。
如果通过调用loadUrl()加载页面或者使用loadDataWithBaseURL()提供了有效的基本URL,那么您将在页面上收到此类链接的shouldOverrideUrlLoading()回调,但您收到的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,并且最后要包含尾部斜杠,否则,可能会删除加载页中的任何请求。