From ade156456a4dbd897baaed34ac8c263cc6e9697a Mon Sep 17 00:00:00 2001 From: XuqmGroup Date: Tue, 23 Jun 2026 11:22:59 +0800 Subject: [PATCH] fix(sdk-webview): handle WebView renderer crash to prevent main process from dying onRenderProcessGone was not overridden, so when the WebView sandboxed renderer process crashed (e.g. during file upload of docx), Android terminated the main app process as well (default return false behavior). Now: return true to keep the host app alive, report the renderer crash via BugCollect (reflection, no compile-time dependency), and reload the page so the user is not stuck on a blank screen. Co-Authored-By: Claude Sonnet 4.6 --- .../java/com/xuqm/sdk/webview/XWebViewView.kt | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/sdk-webview/src/main/java/com/xuqm/sdk/webview/XWebViewView.kt b/sdk-webview/src/main/java/com/xuqm/sdk/webview/XWebViewView.kt index dc81f29..ac98b89 100644 --- a/sdk-webview/src/main/java/com/xuqm/sdk/webview/XWebViewView.kt +++ b/sdk-webview/src/main/java/com/xuqm/sdk/webview/XWebViewView.kt @@ -15,6 +15,7 @@ import android.webkit.JavascriptInterface import android.webkit.MimeTypeMap import android.webkit.PermissionRequest import android.webkit.ValueCallback +import android.webkit.RenderProcessGoneDetail import android.webkit.WebChromeClient import android.webkit.WebResourceError import android.webkit.WebResourceRequest @@ -545,6 +546,35 @@ fun XWebViewView( mainHandler.post { config.onPageError?.invoke(code, desc, url) } } } + + override fun onRenderProcessGone(view: WebView, detail: RenderProcessGoneDetail): Boolean { + // WebView renderer (sandboxed process) crashed or was OOM-killed. + // Return true to keep the main app alive; the crashed WebView instance + // can no longer be used — reload the page via the config url. + android.util.Log.e("XWV", "WebView renderer gone: crashed=${detail.didCrash()}") + mainHandler.post { + // Report the renderer crash via BugCollect if available. + runCatching { + val bugCollect = Class.forName("com.xuqm.sdk.bugcollect.BugCollect") + val instance = bugCollect.getField("INSTANCE").get(null) + val captureMethod = bugCollect.getMethod( + "captureError", + Throwable::class.java, + Map::class.java, + String::class.java, + ) + captureMethod.invoke( + instance, + RuntimeException("WebView renderer ${if (detail.didCrash()) "crashed" else "killed (OOM)"}"), + mapOf("context" to "webview_renderer"), + null, + ) + } + // Reload the page so the user is not stuck on a blank screen. + if (config.url.isNotBlank()) view.loadUrl(config.url) + } + return true + } } webChromeClient = object : WebChromeClient() {