You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在webview_flutter中捕获Android端WebView的进程终止事件?(NavigationDelegate.onWebResourceError未触发)

如何在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
                }
            }
        }
    }
}

关键说明

  1. 为什么这个方案有效?
    直接对接Android原生的onRenderProcessGone API,这个回调是Android系统专门用来监听WebView渲染进程崩溃的,只要渲染进程终止就会触发;返回true可以阻止系统因渲染进程崩溃而杀死整个App进程。
  2. 注意事项
    • 确保你的Android项目依赖的webview_flutter是最新稳定版,旧版本可能没有webViewCreator接口;
    • 如果使用的是拆分后的webview_flutter_android插件,需要调整获取WebView实例的逻辑;
  3. 后续优化
    这个问题是webview_flutter的已知bug,等官方修复映射逻辑后,你可以换回Flutter层的回调,现在先用这个原生扩展方案临时解决。

测试时,加载chrome://crash后,你会看到Flutter控制台打印出捕获到崩溃的日志,并且App不会崩溃,而是执行你定义的恢复逻辑。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.07 07:19:29