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

Flutter已杀死状态下Method Channel无法调用的问题排查求助

问题原因及排查方向

当APP处于已杀死(killed)状态时,点击通知启动APP的流程是:iOS系统先拉起APP的原生进程,再初始化Flutter引擎。而你当前的代码中,userNotificationCenter:didReceiveResponse:方法会在Flutter引擎完全初始化、Dart侧完成Method Channel注册之前就执行调用,此时Dart侧还没准备好接收消息,自然无响应。

核心排查点及解决方案

  1. 检查iOS端调用Method Channel的时机与Flutter引擎状态

    • 杀死状态下,flutterViewController.binaryMessenger对应的Flutter引擎可能还未完成初始化,直接调用invokeMethod会因为通道未建立而失效。
    • 解决:通过UIApplication.shared.applicationState判断APP状态,针对杀死状态单独处理:
      override func userNotificationCenter(_ center: UNUserNotificationCenter,
      didReceive response: UNNotificationResponse,
      withCompletionHandler completionHandler: @escaping () -> Void) {
              let userInfo = response.notification.request.content.userInfo
              let appState = UIApplication.shared.applicationState
              
              if appState == .notRunning {
                  // 杀死状态:暂存通知信息到本地
                  UserDefaults.standard.set(userInfo, forKey: "PendingNotificationTap")
                  UserDefaults.standard.synchronize()
              } else {
                  // 前台/后台:直接调用Method Channel
                  let channel = FlutterMethodChannel(name: "userTapChannel", binaryMessenger:flutterViewController.binaryMessenger)
                  channel.invokeMethod("pushNotificationClicked", arguments: userInfo)
              }
      
              completionHandler()
          }
      
  2. 调整Dart侧Method Channel的注册时机

    • 当前在页面的initState中注册回调,而杀死状态下APP启动时,页面初始化会晚于iOS端的通知响应逻辑,导致回调未注册就收到调用。
    • 解决:将注册逻辑提前到main函数中,确保Flutter启动后立即监听通道:
      void main() {
        WidgetsFlutterBinding.ensureInitialized();
        const userTapChannel = MethodChannel('userTapChannel');
        
        // 提前注册回调
        userTapChannel.setMethodCallHandler(pnTapCallback);
        
        // 启动时主动检查是否有暂存的通知点击信息
        userTapChannel.invokeMethod('getPendingNotification').then((data) {
          if (data != null) {
            pnTapCallback(MethodCall('pushNotificationClicked', data));
            // 处理完清除暂存
            userTapChannel.invokeMethod('clearPendingNotification');
          }
        });
        
        runApp(MyApp());
      }
      
      Future<void> pnTapCallback(MethodCall call) async {
        if (call.method == 'pushNotificationClicked') {
          // 执行跳转到游戏界面的逻辑
        }
      }
      
  3. 补充iOS端的本地缓存读写方法

    • 需要在原生侧新增Method Channel方法,让Dart侧可以获取和清除暂存的通知信息:
      override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
          // ... 原有初始化代码
          
          let channel = FlutterMethodChannel(name: "userTapChannel", binaryMessenger:flutterViewController.binaryMessenger)
          channel.setMethodCallHandler { [weak self] call, result in
              switch call.method {
              case "getPendingNotification":
                  let pending = UserDefaults.standard.dictionary(forKey: "PendingNotificationTap")
                  result(pending)
              case "clearPendingNotification":
                  UserDefaults.standard.removeObject(forKey: "PendingNotificationTap")
                  UserDefaults.standard.synchronize()
                  result(nil)
              default:
                  result(FlutterMethodNotImplemented)
              }
          }
          
          return true
      }
      
  4. 验证状态判断逻辑的准确性

    • 确认appState == .notRunning确实能命中APP杀死的场景,避免因状态判断错误导致逻辑分支未执行。

内容的提问来源于stack exchange,提问作者Temp

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 05:53:25