Android WebView 第一次失败
Android WebView failing only the very first time
我有一个显示本地资产网站的 Android 应用程序,它只有 1 个 activity 具有常见的 webview:
我正在使用 WebViewAssetLoader 作为提供文件的本地方式,我面临的问题是当它第一次安装时无法加载内容WebView,如果我终止该应用程序并再次 运行 它可以完美运行(但我不能要求用户这样做),而且如果该应用程序是由 Android studio 第二次安装,它可以运行,但是如果该应用程序从未安装过,它总是失败。
这是logcat
的结果
2019-11-18 16:58:40.439 21492-21492/? E/Zygote: isWhitelistProcess - Process is Whitelisted
2019-11-18 16:58:40.439 21492-21492/? E/Zygote: accessInfo : 1
2019-11-18 16:58:40.628 21492-21544/com.my.app.dev.debug E/GraphicsEnv: Failed to get gpu service
2019-11-18 16:58:40.805 21492-21492/com.my.app.dev.debug E/chromium: [ERROR:filesystem_posix.cc(89)] stat /data/user/0/com.my.app.dev.debug/cache/WebView/Crashpad: No such file or directory (2)
2019-11-18 16:58:40.805 21492-21492/com.my.app.dev.debug E/chromium: [ERROR:filesystem_posix.cc(62)] mkdir /data/user/0/com.my.app.dev.debug/cache/WebView/Crashpad: No such file or directory (2)
2019-11-18 16:58:45.237 21492-21658/com.my.app.dev.debug E/AssetHelper: Unable to open asset path: dist/
这是加载 WebView 的代码
private fun initializeWebViewSettings() {
webView!!.setBackgroundColor(Color.TRANSPARENT)
webView!!.settings.javaScriptEnabled = true
webView!!.settings.javaScriptCanOpenWindowsAutomatically = true
webView!!.settings.domStorageEnabled = true
webView!!.settings.allowFileAccess = true
webView!!.settings.allowContentAccess = true
webView!!.settings.allowUniversalAccessFromFileURLs = true
webView!!.settings.setGeolocationEnabled(true)
setWebViewClient()
setWebViewChromeClient()
webView!!.visibility = View.INVISIBLE
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//ONLY API_LEVEL >= 21 can use WebViewAssetLoader
assetLoader = WebViewAssetLoader.Builder()
.addPathHandler("/assets/", AssetsPathHandler(this))
.addPathHandler("/res/", ResourcesPathHandler(this))
.build()
webView!!.loadUrl(Constants.WEB_URL_SERVED)
}
else{
webView!!.loadUrl(Constants.WEB_URL_LOCAL)
}
}
我进行了研究,结果发现这是一个与此问题相关的已知错误,但它已针对较新版本的 Chrome 解决,我正在使用 Android 在 Galaxy Note10 上进行测试] API 28(最新)
有没有人遇到过类似的问题?任何线索将不胜感激。
我的回答并不能直接解决您的问题,因为它需要更多上下文(更多日志以及您使用的 webview 包和版本),但希望这可能有所帮助。
2019-11-18 16:58:40.439 21492-21492/? E/Zygote: isWhitelistProcess - Process is Whitelisted 2019-11-18 16:58:40.439 21492-21492/? E/Zygote: accessInfo : 1
2019-11-18 16:58:40.628 21492-21544/com.my.app.dev.debug E/GraphicsEnv: Failed to get gpu service
2019-11-18 16:58:40.805 21492-21492/com.my.app.dev.debug E/chromium: [ERROR:filesystem_posix.cc(89)] stat /data/user/0/com.my.app.dev.debug/cache/WebView/Crashpad: No such file or directory (2)
2019-11-18 16:58:40.805 21492-21492/com.my.app.dev.debug E/chromium: [ERROR:filesystem_posix.cc(62)] mkdir /data/user/0/com.my.app.dev.debug/cache/WebView/Crashpad: No such file or directory (2)
这些日志不是崩溃发生的原因,这是 WebView 本身的问题,与 WebViewAssetLoader
没有任何关系。因此,请确保在您的设备上更新到最新的 WebView 和 Chrome 版本(与 android 框架不同,WebView 通过应用商店定期更新)。为确保这不是 WebViewAssetLoader
问题,请尝试在没有所有 WebViewAssetLoader
代码的情况下构建相同的应用程序,看看是否仍然发生相同的崩溃。
2019-11-18 16:58:45.237 21492-21658/com.my.app.dev.debug E/AssetHelper: Unable to open asset path: dist/
这是唯一与 androidx.webkit.WebViewAssetLoader
相关的行。我假设您正在加载的内容试图打开一个不存在的文件夹 /assets/dist/
。但是,这不应导致任何崩溃。
除此之外,您的代码还有几点注意事项:
- API等级>=21就不用守
WebViewAssetLoader
了,API >= 14. 应该可以用
对于 WebViewClient#shouldInterceptRequest
,如果您覆盖该方法的两个版本而不是完全放弃使用 WebViewAssetLoader
对于旧的 API 会更好:
@RequiresApi(21)
override fun shouldInterceptRequest(
view: WebView?,
request: WebResourceRequest?
): WebResourceResponse? {
return assetLoader.shouldInterceptRequest(request.url)
}
@SuppressWarnings("deprecation") // suppress the warning if your target build API is lower than 21
override fun shouldInterceptRequest(
view: WebView?,
request: String?
): WebResourceResponse? {
return assetLoader.shouldInterceptRequest(Uri.parse(request))
}
- 不要将此设置设为真:
webView!!.settings.allowUniversalAccessFromFileURLs = true
我假设您在未使用 WebViewAssetLoader
的情况下启用此设置。对于 javascript,此设置是高度 discouraged because it allows CORS。如果您曾经在 WebView 中加载第三方内容,这将是一个安全风险,因为它使任何 javascript 代码都能够访问任何私人应用程序文件。这实际上是 WebViewAssetLoader
试图解决的主要问题,因此您不需要 - 实际上不应该 - 在使用 WebViewAssetLoader
时设置 allowUniversalAccessFromFileURLs = true
。
此外,为了让事情更安全,如果您使用 WebViewAssetLoader
访问所有本地应用程序资产文件,您还应该将其设置为 false:
webView!!.settings.allowFileAccess = false
我有一个显示本地资产网站的 Android 应用程序,它只有 1 个 activity 具有常见的 webview:
我正在使用 WebViewAssetLoader 作为提供文件的本地方式,我面临的问题是当它第一次安装时无法加载内容WebView,如果我终止该应用程序并再次 运行 它可以完美运行(但我不能要求用户这样做),而且如果该应用程序是由 Android studio 第二次安装,它可以运行,但是如果该应用程序从未安装过,它总是失败。
这是logcat
的结果2019-11-18 16:58:40.439 21492-21492/? E/Zygote: isWhitelistProcess - Process is Whitelisted 2019-11-18 16:58:40.439 21492-21492/? E/Zygote: accessInfo : 1 2019-11-18 16:58:40.628 21492-21544/com.my.app.dev.debug E/GraphicsEnv: Failed to get gpu service 2019-11-18 16:58:40.805 21492-21492/com.my.app.dev.debug E/chromium: [ERROR:filesystem_posix.cc(89)] stat /data/user/0/com.my.app.dev.debug/cache/WebView/Crashpad: No such file or directory (2) 2019-11-18 16:58:40.805 21492-21492/com.my.app.dev.debug E/chromium: [ERROR:filesystem_posix.cc(62)] mkdir /data/user/0/com.my.app.dev.debug/cache/WebView/Crashpad: No such file or directory (2) 2019-11-18 16:58:45.237 21492-21658/com.my.app.dev.debug E/AssetHelper: Unable to open asset path: dist/
这是加载 WebView 的代码
private fun initializeWebViewSettings() {
webView!!.setBackgroundColor(Color.TRANSPARENT)
webView!!.settings.javaScriptEnabled = true
webView!!.settings.javaScriptCanOpenWindowsAutomatically = true
webView!!.settings.domStorageEnabled = true
webView!!.settings.allowFileAccess = true
webView!!.settings.allowContentAccess = true
webView!!.settings.allowUniversalAccessFromFileURLs = true
webView!!.settings.setGeolocationEnabled(true)
setWebViewClient()
setWebViewChromeClient()
webView!!.visibility = View.INVISIBLE
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//ONLY API_LEVEL >= 21 can use WebViewAssetLoader
assetLoader = WebViewAssetLoader.Builder()
.addPathHandler("/assets/", AssetsPathHandler(this))
.addPathHandler("/res/", ResourcesPathHandler(this))
.build()
webView!!.loadUrl(Constants.WEB_URL_SERVED)
}
else{
webView!!.loadUrl(Constants.WEB_URL_LOCAL)
}
}
我进行了研究,结果发现这是一个与此问题相关的已知错误,但它已针对较新版本的 Chrome 解决,我正在使用 Android 在 Galaxy Note10 上进行测试] API 28(最新)
有没有人遇到过类似的问题?任何线索将不胜感激。
我的回答并不能直接解决您的问题,因为它需要更多上下文(更多日志以及您使用的 webview 包和版本),但希望这可能有所帮助。
2019-11-18 16:58:40.439 21492-21492/? E/Zygote: isWhitelistProcess - Process is Whitelisted 2019-11-18 16:58:40.439 21492-21492/? E/Zygote: accessInfo : 1
2019-11-18 16:58:40.628 21492-21544/com.my.app.dev.debug E/GraphicsEnv: Failed to get gpu service
2019-11-18 16:58:40.805 21492-21492/com.my.app.dev.debug E/chromium: [ERROR:filesystem_posix.cc(89)] stat /data/user/0/com.my.app.dev.debug/cache/WebView/Crashpad: No such file or directory (2)
2019-11-18 16:58:40.805 21492-21492/com.my.app.dev.debug E/chromium: [ERROR:filesystem_posix.cc(62)] mkdir /data/user/0/com.my.app.dev.debug/cache/WebView/Crashpad: No such file or directory (2)
这些日志不是崩溃发生的原因,这是 WebView 本身的问题,与 WebViewAssetLoader
没有任何关系。因此,请确保在您的设备上更新到最新的 WebView 和 Chrome 版本(与 android 框架不同,WebView 通过应用商店定期更新)。为确保这不是 WebViewAssetLoader
问题,请尝试在没有所有 WebViewAssetLoader
代码的情况下构建相同的应用程序,看看是否仍然发生相同的崩溃。
2019-11-18 16:58:45.237 21492-21658/com.my.app.dev.debug E/AssetHelper: Unable to open asset path: dist/
这是唯一与 androidx.webkit.WebViewAssetLoader
相关的行。我假设您正在加载的内容试图打开一个不存在的文件夹 /assets/dist/
。但是,这不应导致任何崩溃。
除此之外,您的代码还有几点注意事项:
- API等级>=21就不用守
WebViewAssetLoader
了,API >= 14. 应该可以用
对于 WebViewClient#shouldInterceptRequest
,如果您覆盖该方法的两个版本而不是完全放弃使用 WebViewAssetLoader
对于旧的 API 会更好:
@RequiresApi(21)
override fun shouldInterceptRequest(
view: WebView?,
request: WebResourceRequest?
): WebResourceResponse? {
return assetLoader.shouldInterceptRequest(request.url)
}
@SuppressWarnings("deprecation") // suppress the warning if your target build API is lower than 21
override fun shouldInterceptRequest(
view: WebView?,
request: String?
): WebResourceResponse? {
return assetLoader.shouldInterceptRequest(Uri.parse(request))
}
- 不要将此设置设为真:
webView!!.settings.allowUniversalAccessFromFileURLs = true
我假设您在未使用 WebViewAssetLoader
的情况下启用此设置。对于 javascript,此设置是高度 discouraged because it allows CORS。如果您曾经在 WebView 中加载第三方内容,这将是一个安全风险,因为它使任何 javascript 代码都能够访问任何私人应用程序文件。这实际上是 WebViewAssetLoader
试图解决的主要问题,因此您不需要 - 实际上不应该 - 在使用 WebViewAssetLoader
时设置 allowUniversalAccessFromFileURLs = true
。
此外,为了让事情更安全,如果您使用 WebViewAssetLoader
访问所有本地应用程序资产文件,您还应该将其设置为 false:
webView!!.settings.allowFileAccess = false