【问题标题】:Android WebView failing only the very first timeAndroid WebView 仅在第一次失败
【发布时间】:2019-11-18 23:17:35
【问题描述】:

我有一个显示本地资产网站的 Android 应用程序,它只有 1 个带有通用 web 视图的活动:

我使用WebViewAssetLoader 作为本地方式来提供文件,我面临的问题是它非常令人沮丧的是,当它第一次安装的应用程序无法在 WebView 中加载内容时,如果我杀死该应用程序并再次运行它可以完美运行(但我不能说用户这样做),如果该应用程序由 Android Studio 第二次安装,它可以工作,但如果该应用程序从未安装它总是失败。

这是logcat的结果

2019-11-18 16:58:40.439 21492-21492/? E/Zygote: isWhitelistProcess - 进程被列入白名单 2019-11-18 16:58:40.439 21492-21492/? E/Zygote:访问信息:1 2019-11-18 16:58:40.628 21492-21544/com.my.app.dev.debug E/GraphicsEnv:获取 gpu 服务失败 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:没有这样的文件或目录(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:没有这样的文件或目录(2) 2019-11-18 16:58:45.237 21492-21658/com.my.app.dev.debug E/AssetHelper:无法打开资产路径: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 API 28(最新)在 Galaxy Note10 上执行测试

有人遇到过类似的问题吗?任何线索将不胜感激。

【问题讨论】:

    标签: android kotlin webview android-webview


    【解决方案1】:

    我的回答并不能直接解决您的问题,因为它需要更多上下文(更多日志以及您使用的 webview 包和版本),但希望这可能会有所帮助。

    2019-11-18 16:58:40.439 21492-21492/? E/Zygote: isWhitelistProcess - 进程被列入白名单 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:获取gpu服务失败

    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:没有这样的文件或目录(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:没有这样的文件或目录(2)

    这些日志不是发生崩溃的原因,这是 WebView 本身的问题,与 WebViewAssetLoader 没有任何关系。因此,请确保在您的设备上更新到最新的 WebView 和 Chrome 版本(WebView 是通过应用商店定期更新的,这与 android 框架不同)。为确保这不是 WebViewAssetLoader 问题,请尝试在没有所有 WebViewAssetLoader 代码的情况下构建相同的应用程序,看看是否仍然发生相同的崩溃。

    2019-11-18 16:58:45.237 21492-21658/com.my.app.dev.debug E/AssetHelper:无法打开资产路径:dist/

    这是与androidx.webkit.WebViewAssetLoader 相关的唯一行。我假设您正在加载的内容正在尝试打开一个不存在的文件夹 /assets/dist/。但是,这不会导致任何崩溃。


    除此之外,您的代码还有一些注意事项:

    • 对于 API 级别 >= 21,您不必保护 WebViewAssetLoader,您应该可以将它用于 API >= 14

    对于WebViewClient#shouldInterceptRequest,最好覆盖两个版本的方法,而不是完全放弃对旧API 使用WebViewAssetLoader

    @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))
    }
    
    • 不要将此设置设为 true:
      webView!!.settings.allowUniversalAccessFromFileURLs = true
    

    我假设您在不使用 WebViewAssetLoader 的情况下启用此设置。此设置高度为discouraged,因为它允许CORS 用于javascript。如果您曾经在 WebView 中加载第 3 方内容,这将是一个安全风险,因为它使任何 javascript 代码能够访问任何私有应用程序文件。这实际上是WebViewAssetLoader 试图解决的主要问题,所以当你使用WebViewAssetLoader 时,你不需要——实际上也不应该——设置allowUniversalAccessFromFileURLs = true

    此外,为了更安全,如果您使用 WebViewAssetLoader 访问所有本地应用资产文件,您还应该将其设置为 false:

    webView!!.settings.allowFileAccess = false
    

    【讨论】:

    • 谢谢你的信息,另一方面,这对我来说非常有价值应用程序运行它重定向到 /assets/dist/# 这似乎与 WebViewAssetLoader 拦截器冲突,我过滤了该重定向并且一切运行正常。
    • 关于 WebViewAssetLoader 和 API 级别,感谢您阐明其工作的版本,但我遇到了与 WebViewClient 配置相关的问题,shouldInterceptRequest 在尝试访问 request.url 时向我显示错误询问我至少 API 21
    • 很高兴这有帮助,我更新了我的答案,因为我无法在评论中很好地添加代码块。
    • 另外补充一句,如果您的所有网络应用程序文件都位于资产下,则无需添加.addPathHandler("/res/", ResourcesPathHandler(this)
    • 我也很好奇事情是如何结束的,全新安装的崩溃是否停止了?当您将该重定向请求过滤到dist 时它是否停止了,或者您是否也更新了 WebView?如果它停止是因为在您过滤掉重定向后立即停止,这很糟糕,我认为使用此链接here 向 google 的 androidx.webkit 团队报告它会很棒
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-13
    相关资源
    最近更新 更多