如何在webview_flutter中捕获Android端WebView的进程终止事件?(NavigationDelegate.onWebResourceError未触发)
这个问题我之前也踩过坑——确实是当前webview_flutter在Android端处理渲染进程崩溃时的一个痛点。官方文档提到Android的WebViewClient.onRenderProcessGone会映射到Flutter层的NavigationDelegate.onWebResourceError,但实际上像加载chrome://crash这种直接触发渲染进程硬终止的场景,属于原生WebView的进程级事件,并不在常规的Web资源错误范畴里,所以Flutter层的这个回调根本不会被触发,最终导致App直接崩溃。
目前的临时解决方案是通过Flutter的平台通道(Platform Channel)直接对接Android原生的WebView API,手动监听onRenderProcessGone事件,绕过Flutter插件的当前限制。下面是具体的实现步骤和代码示例:
步骤1:Flutter端修改(整合平台通道)
修改你原来的最小项目代码,添加平台通道监听,并且在捕获到崩溃事件时处理(比如重启WebView、显示错误页面):
import 'dart:developer'; import 'package:flutter/material.dart'; import 'package:webview_flutter/webview_flutter.dart'; import 'package:flutter/services.dart'; void main() { runApp( MaterialApp( theme: ThemeData(useMaterial3: true), home: const WebViewApp(), ), ); } class WebViewApp extends StatefulWidget { const WebViewApp({super.key}); @override State<WebViewApp> createState() => _WebViewAppState(); } class _WebViewAppState extends State<WebViewApp> { late final WebViewController controller; static const platform = MethodChannel('com.example.webview_crash_handler/render_process'); @override void initState() { super.initState(); controller = WebViewController(); // 监听原生传来的渲染进程崩溃事件 platform.setMethodCallHandler((call) async { if (call.method == 'onRenderProcessGone') { log('#test# 捕获到渲染进程崩溃!开始处理...'); // 这里可以做崩溃后的处理:比如重新加载WebView,或者显示错误页面 setState(() { // 重置WebViewController并重新加载(示例) controller = WebViewController() ..loadRequest(Uri.parse('https://www.google.com')); }); } }); } @override Widget build(BuildContext context) { return Scaffold( body: WebViewStack(controller: controller), ); } } class WebViewStack extends StatefulWidget { const WebViewStack({required this.controller, super.key}); final WebViewController controller; @override State<WebViewStack> createState() => _WebViewStackState(); } class _WebViewStackState extends State<WebViewStack> { @override void initState() { super.initState(); widget.controller.setNavigationDelegate( NavigationDelegate( onWebResourceError: (WebResourceError error) { log('#test# 常规Web资源错误: ${error.errorCode} ${error.description}'); }, ), ); widget.controller.loadRequest(Uri.parse('chrome://crash')); } @override Widget build(BuildContext context) { return Stack( children: [ WebViewWidget(controller: widget.controller), ], ); } }
步骤2:Android原生端修改(对接onRenderProcessGone)
打开Android项目的app/src/main/kotlin/[你的包名]/MainActivity.kt,修改代码,通过WebViewFlutterPlugin获取WebView实例,设置自定义的WebViewClient并监听onRenderProcessGone:
package com.example.your_package_name // 替换成你的实际包名 import android.webkit.WebView import android.webkit.WebViewClient import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine import io.flutter.plugin.common.MethodChannel import io.flutter.plugins.webviewflutter.WebViewFlutterPlugin class MainActivity : FlutterActivity() { private val CHANNEL = "com.example.webview_crash_handler/render_process" override fun configureFlutterEngine(flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) val channel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL) // 获取WebViewFlutterPlugin实例,监听WebView创建事件 val webViewPlugin = flutterEngine.plugins.get(WebViewFlutterPlugin::class.java) webViewPlugin?.webViewCreator?.setWebViewClientProvider { webView -> object : WebViewClient() { override fun onRenderProcessGone( view: WebView?, detail: android.webkit.RenderProcessGoneDetail? ): Boolean { // 通知Flutter端渲染进程崩溃 channel.invokeMethod("onRenderProcessGone", null) // 返回true表示我们已经处理了崩溃,避免系统杀死整个App进程 return true } } } } }
关键说明
- 为什么这个方案有效?
直接对接Android原生的onRenderProcessGoneAPI,这个回调是Android系统专门用来监听WebView渲染进程崩溃的,只要渲染进程终止就会触发;返回true可以阻止系统因渲染进程崩溃而杀死整个App进程。 - 注意事项
- 确保你的Android项目依赖的
webview_flutter是最新稳定版,旧版本可能没有webViewCreator接口; - 如果使用的是拆分后的
webview_flutter_android插件,需要调整获取WebView实例的逻辑;
- 确保你的Android项目依赖的
- 后续优化
这个问题是webview_flutter的已知bug,等官方修复映射逻辑后,你可以换回Flutter层的回调,现在先用这个原生扩展方案临时解决。
测试时,加载chrome://crash后,你会看到Flutter控制台打印出捕获到崩溃的日志,并且App不会崩溃,而是执行你定义的恢复逻辑。
内容来源于stack exchange
相关产品推荐
相关产品推荐

