本文介绍: Android WebView MultiProcess导致App崩溃

应用场景

应用内有两个位置用到WebView加载页面,具体处理逻辑不能通用。分别扩展了WebView了。应用内独立页面使用Fragment展示(单Activity架构),应用提供切换语言功能

一、WebView内核bug

具体路径
进入app–>设置切换语言应用界面重新加载)-再次进入设置->跳转到WebViewFragment展示H5。随便操作滑动。退出到上一页。重复该操作,会引发应用crash

MI 10 输出error 日志
请添加图片描述

] Failed to create directory: /data/user/0/com.codeview.miniparty/cache/WebView/Default/HTTP Cache/Code Cache/js
D  Compat change id reported: 171228096; UID 10728; state: ENABLED
I  QUALCOMM build                   : db3d445dbc, Ia06b22fa1a
   Build Date                       : 10/04/21
   OpenGL ES Shader Compiler Version: EV031.32.02.16
   Local Branch                     : 
   Remote Branch                    : 
   Remote Branch                    : 
   Reconstruct Branch               : 
I  Build Config                     : S P 10.0.7 AArch64
I  Driver Path                      : /vendor/lib64/egl/libGLESv2_adreno.so
W  Application attempted to call on a destroyed WebView
   java.lang.Throwable
    at org.chromium.android_webview.AwContents.m(chromium-TrichromeWebViewGoogle6432.aab-stable-530410534:10)
    at com.android.webview.chromium.WebViewChromium.addJavascriptInterface(chromium-TrichromeWebViewGoogle6432.aab-stable-530410534:25)
    at android.webkit.WebView.addJavascriptInterface(WebView.java:1928)
    at miui.contentcatcher.sdk.utils.WebViewUtils$NativeWebViewUtils.addJavascriptInterface(WebViewUtils.java:244)
    at miui.contentcatcher.sdk.utils.WebViewUtils.initWebViewJsInterface(WebViewUtils.java:157)
    at miui.contentcatcher.InterceptorProxy$1.run(InterceptorProxy.java:193)
    at android.os.Handler.handleCallback(Handler.java:938)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loopOnce(Looper.java:210)
    at android.os.Looper.loop(Looper.java:299)
    at android.app.ActivityThread.main(ActivityThread.java:8293)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:556)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1045)

网上找到chrome 官方issue问题
https://bugs.chromium.org/p/chromium/issues/detail?id=558377
该问题一直追踪到2021年也并没有给出具体的解决方案

快速操作界面开关,导致WebView异常,引发应用闪退

在红米K40上(Android 12)显示
请添加图片描述

Build fingerprint: 'Verizon/kltevzw/kltevzw:5.0/LRX21T/G900VVRU2BOE1:user/release-keys'
Revision: '14'
ABI: 'arm'
pid: 30968, tid: 30968, name: com.myapp >>> com.myapp <<<
signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
Abort message: '[FATAL:jni_android.cc(295)] Check failed: false. Please include Java exception stack in crash report
'
r0 00000000 r1 000078f8 r2 00000006 r3 00000000
r4 b6f5c114 r5 00000006 r6 0000000b r7 0000010c
r8 b6f3be04 r9 bec21408 sl 00000000 fp bec213cc
ip 000078f8 sp bec20ee0 lr b6ee5fd1 pc b6f09970 cpsr 600f0010

backtrace:
#00 pc 00037970 /system/lib/libc.so (tgkill+12)
#01 pc 00013fcd /system/lib/libc.so (pthread_kill+52)
#02 pc 00014beb /system/lib/libc.so (raise+10)
#03 pc 00011531 /system/lib/libc.so (__libc_android_abort+36)
#04 pc 0000fcbc /system/lib/libc.so (abort+4)
#05 pc 002a7569 /data/app/com.google.android.webview-2/lib/arm/libwebviewchromium.so 

这个问题在stackoverflows上找到另一个解决方案
https://stackoverflow.com/questions/31416568/could-someone-help-me-with-this-crash-report

这个问题更像是应用使用场景webView在Fragment中,快速打开关闭Fragment导致应用Crash

在Application的AccachBaseContextbase:Context)中进行处理multiProcess

    override fun attachBaseContext(base: Context?) {
        super.attachBaseContext(base)
        WebViewMultiProcessPatch.apply {
            setDirectorySuffix(
                isSameProcess(this@SkyCastleApplication),
                getProcessName(this@SkyCastleApplication)
            )
        }
    }

新建一个WebViewMultiProcessPatch单例用来做一些逻辑判断

/**
 * 
 * Date:   2022/11/29 19:00
 * Description:多进程闪退
 */


object WebViewMultiProcessPatch {

    /**
     * fix:Using WebView from more than one process at once with the same data directory is not supported
     * https://www.yisu.com/zixun/445583.html
     */
    fun tryLockOrRecreateFile(context: Context, processName: String) {
        val filePath =
            context.dataDir.absolutePath + "/${processName}/app_webview/webview_data.lock"
        File(filePath).let {
            if (it.exists()) {
                try {
                    val tryLock = RandomAccessFile(it, "rw").channel.tryLock()
                    if (tryLock != null) {
                        tryLock.close()
                    } else {
                        createLockFile(it, it.delete())
                    }
                } catch (e: Exception) {
                    e.printStackTrace()
                    var delete = false
                    if (it.exists()) {
                        delete = it.delete()
                    }
                    createLockFile(it, delete)
                }
            }
        }
    }

    private fun createLockFile(file: File, delete: Boolean) {
        try {
            if (delete &amp;&amp; !file.exists()) {
                file.createNewFile()
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    /**
     * fix:Using WebView from more than one process at once with the same data directory is not supported
     * https://www.jianshu.com/p/f3ccc065f632
     */
    fun setDirectorySuffix(isSameProcess: Boolean, processName: String?) {
        if (!isSameProcess) {
            //see https://developer.android.google.cn/about/versions/pie/android-9.0-changes-28#web-data-dirs
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P &amp;&amp; !processName.isNullOrBlank()) {
                WebView.setDataDirectorySuffix(processName)
            }
        }
    }


    fun isSameProcess(context: Context): Boolean {
        return getProcessName(context) == getPackageName(context)
    }

    fun getProcessName(cxt: Context): String? {
        val pid = Process.myPid()
        val am = cxt.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
        val runningApps = am.runningAppProcesses ?: return null
        for (procInfo in runningApps) {
            if (procInfo.pid == pid) {
                return procInfo.processName
            }
        }
        return null
    }
    private fun getPackageName(context: Context): String? {
        return context.packageName
    }

}

总结

Android 不仅需要对不同品牌设备适配,还需要针对不同的系统版本做适配。会有比较多的问题定位不到具体原因。这种情况不但要平时多多积累,更要掌握解决问题的思路。

引用

  1. Android webView
  2. Android 9.0 行为变更
  3. Android如何解决WebView多进程崩溃的问题

原文地址:https://blog.csdn.net/o279642707/article/details/128105516

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。

如若转载,请注明出处:http://www.7code.cn/show_8167.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注