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 <noreply@anthropic.com>
这个提交包含在:
XuqmGroup 2026-06-23 11:22:59 +08:00
父节点 daaa40147d
当前提交 ade156456a

查看文件

@ -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() {