我有一个应用程序,它使用
WebView
向用户显示一些本地 html。该应用程序在过去两年中运行良好,但最近我收到太多报告称该应用程序显示某种错误,如下所示:
"Web page not available The web page at data:text/html; charset=utf-8;charset=utf-8;base64, could not be loaded because: net::ERR_INVALID_RESPONSE"
显然 Android 或 WebView 中发生了一些变化,并且确实发生了,doc 说:
更严格的UTF-8解码器在Android 9中,Java的UTF-8解码器 语言更加严格,遵循Unicode标准。
所以,我尝试用base64编码加载我的数据来解决这个问题。
String encodedHtml = Base64.encodeToString(resource.getBytes(), Base64.NO_WRAP);
loadDataWithBaseURL(basePath, encodedHtml, "text/html; charset=utf-8", "base64", null);
但是这个方法只是打印原始的base64字符串。所以我尝试了这个:
loadData(encodedHtml, "text/html; charset=utf-8", "base64");
它显示 html 没有任何问题。
但是,我需要使用
loadDataWithBaseURL
这样我就可以对 html 进行后期处理,例如。加载CSS、字体等。
那么
loadData
和loadDataWithBaseURL
之间有什么区别,导致其中一个显示html,另一个显示原始base64字符串?
文档说(强调)
如果基础 URL 使用 data 方案,则此方法相当于调用 loadData(),并且historyUrl 被忽略,并且数据将被视为 data: URL 的一部分,包括内容必须经过 URL 编码或Base64 编码。 如果基本 URL 使用任何其他方案,则数据将作为纯字符串(即不是数据 URL 的一部分)加载到 WebView 中,并且字符串中的任何 URL 编码实体将不会被解码。
这听起来好像没有办法提供像
https://example.com
这样的网站的基本 URL,不幸的是。
我可以通过使用 html 基本标签来解决这个问题,因此链接/图像/等中的相对 URL 。仍然可以工作。
String header = "<head> <base href='" + myBaseUrl + "'> </head>";
String encodedHtml = Base64.encodeToString((header + resource).getBytes(), Base64.NO_WRAP);
webview.loadData(encodedHtml, "text/html; charset=utf-8", "base64");
我在没有标题的情况下解决了(Kotlin)。
这是一个 bug 或者是 base64 的问题。
webview
.loadDataWithBaseURL(
"http://baseurl.com/",
data?.fromBase64(),
"text/html; charset=utf-8",
"UTF-8",
null
)
fromBase64() -> https://stackoverflow.com/a/64892843/1064316