Flutter - Firebase_messaging 从 v7 迁移到 v11 - onMessage 未被调用

Flutter - Firebase_messaging migrating from v7 to v11 - onMessage not being called

我在迁移项目时需要一些帮助。 基本上这个项目现在有点老了,它 运行 差不多 3 年了,直到现在它是用 flutter 1.22.6 构建的。现在我正在尝试将其迁移到 v2.10.3 并且迁移即将完成。最后一个不工作的部分是 iOS 推送通知。

旧版本是 firebase_messaging v.7.0.3 上的 运行,并且工作正常。 升级 flutter 需要 9.0.0 或更高版本。

我已经完成了基本的代码迁移并且 Android 没问题,但是在 iOS 上我的 onMessage 处理程序从未被调用。 当应用程序处于后台时,正在传递推送并正确显示通知。但是当它在前台时,或者我会点击那个通知,应用程序进入前台,但回调没有被触发。

我在日志中看到的唯一错误是: nw_endpoint_handler_set_adaptive_read_handler [C6.1 216.58.212.42:443 ready channel-flow (satisfied (Path is satisfied), viable, interface: en0, ipv4, dns)] unregister notification for read_timeout failed

OFC 我浏览了关于堆栈和其他地方的大部分主题,但是 none 这些解决方案对我有用。 我没有使用任何其他插件,例如 flutter_local_notifications 或类似的,这可能会导致错误。

最重要的代码片段:

扑博士

Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel unknown, 2.10.3, on macOS 11.6 20G165 darwin-x64, locale
    pl-PL)
[✓] Android toolchain - develop for Android devices (Android SDK version
    33.0.0-rc3)
[✓] Xcode - develop for iOS and macOS (Xcode 13.2)
[✓] Chrome - develop for the web
[✓] Android Studio (version 4.2)
[✓] VS Code (version 1.67.1)
[✓] Connected device (1 available)
[✓] HTTP Host Availability

pubspec.yaml

  firebase_core: 1.16.0
  firebase_messaging: 11.3.0
  google_ml_kit: 0.7.3

AppDelegate.swift

override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?
    ) -> Bool {
        disableCache();
        FirebaseConfiguration.shared.setLoggerLevel(.min)
        FirebaseApp.configure()
        self.SetupPushNotification(application: application)
    
    func SetupPushNotification(application: UIApplication) -> () {
        if #available(iOS 10, *){ UNUserNotificationCenter.current().requestAuthorization(options: [.alert,.sound,.badge])
        {(granted,error) in
            if granted{
                DispatchQueue.main.async {
                    application.registerForRemoteNotifications()
                }
            } else {
                print("User Notification permission denied: \(error?.localizedDescription ?? "error")")
            }
        }
        }
    }
    
    override func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        NotificationDeviceToken.sharedInstance.setToken(token: tokenString(deviceToken))
     }

    override func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
        print("Failed to register for remote notifications: \(error.localizedDescription)")
    }
    
    override func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
        print(userInfo)
     }

     func tokenString(_ deviceToken:Data) -> String{
         let bytes = [UInt8](deviceToken)
         var token = ""
         for byte in bytes{
             token += String(format: "%02x",byte)
         }
         return token 
     }

main.dart

void startApp(AppConfig config) async {
  // add this, and it should be the first line in main method
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  ...
}

app.dart

  void init(BuildContext context, AppCubit cubit,
      SubscriptionManager subscriptionManager) {
    await FirebaseMessaging.instance.getToken();
    FirebaseMessaging.onMessage.listen((map) {
      _log.debug('onMessage: ${map.data}');
      final push = Push(map.data, PushType.onMessage);
      _streamController.add(push);
      return Future<bool>.value(true);
    });

    FirebaseMessaging.onMessageOpenedApp.listen((map) {
      _log.debug('onMessageOpenedApp: ${map.data}');
      _startAppFromPush = true;
      final push = Push(map.data, PushType.onLaunch);
      _streamController.add(push);
      return Future<bool>.value(true);
    });
  }

Info.plist

...
<key>FirebaseAppDelegateProxyEnabled<key/>
<false/>
...

如有任何帮助,我们将不胜感激。 提前致谢。

看来我找到了解决方案。

我在 github flutterfire 项目中发现了一个未解决的问题。 其中一个主题与我的麻烦非常相似。 https://github.com/firebase/flutterfire/issues/4300

事实是,从 FCM 发送的每个推送都会在负载中获得名为 gcm.message_id 的附加字段。 来自 APNS 的通知不会获取此字段。

从版本 9 到现在的插件 firebase_messaging 正在验证此字段,如果推送不包含它,则不会触发回调 onMessageonMessageOpenedApp

如果您遇到类似的问题,您有两个选择:

  • 在您的 APNS 消息负载中添加缺失的字段
  • 使用 firebase_messaging 插件创建您自己的分支,并在 2 个位置修改 FLTFirebaseMessagingPlugin,其中包含正确的 if 语句。

我希望这对你们中的一些人有用。我花了很多时间研究这个问题。