Flutter iOS迁移UIScene后FirebaseMessaging.onMessage无法触发
Flutter iOS迁移UISceneDelegate后FirebaseMessaging.onMessage前台不触发问题
将Flutter iOS应用迁移为使用UISceneDelegation(通过Info.plist中的FlutterSceneDelegate)后,Dart层的FirebaseMessaging.onMessage在应用前台时完全无法触发。通过APNs发送的后台通知横幅显示正常,但Dart层接收不到任何消息——既没有onMessage、onMessageOpenedApp的日志,也没有getInitialMessage返回的数据。
正常工作项
- FCM令牌生成成功且非空
- 应用后台时推送通知横幅正常显示
didRegisterForRemoteNotificationsWithDeviceToken回调正常触发UNUserNotificationCenter的willPresent回调正常触发(已通过Swift打印确认)- 从willPresent中成功调用
Messaging.messaging().appDidReceiveMessage(userInfo)
失效项
- Dart层的
FirebaseMessaging.onMessage始终不触发 - Dart层的
FirebaseMessaging.onMessageOpenedApp始终不触发 - 无任何通知相关的Dart端日志
- 已定位根因:使用
FlutterImplicitEngineDelegate时,插件通过func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) { GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry) }注册。GeneratedPluginRegistrant.register执行后,预期FLTFirebaseMessagingPlugin会将自身设置为Messaging.messaging().delegate,但注册后立即打印该代理显示为nil。
迁移至UIScene之前无此问题,当时在didFinishLaunchingWithOptions中调用GeneratedPluginRegistrant.register(with: self),且FlutterAppDelegate(生命周期与应用一致)会强引用插件。
AppDelegate.swift代码
import Flutter import Firebase import UserNotifications import flutter_local_notifications @main @objc class AppDelegate: FlutterAppDelegate, FlutterImplicitEngineDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { FirebaseApp.configure() UNUserNotificationCenter.current().delegate = self let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound] UNUserNotificationCenter.current().requestAuthorization(options: authOptions) { _, _ in } application.registerForRemoteNotifications() // GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) { // This is required to make any communication available in the action isolate. FlutterLocalNotificationsPlugin.setPluginRegistrantCallback { (registry) in GeneratedPluginRegistrant.register(with: registry) } GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry) } override func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { Messaging.messaging().apnsToken = deviceToken // print("✅ APNs token: \(deviceToken.map { String(format: "%02x", $0) }.joined())") super.application(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken) } // override func application(_ application: UIApplication, // didReceiveRemoteNotification userInfo: [AnyHashable : Any], // fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { // Messaging.messaging().appDidReceiveMessage(userInfo) // completionHandler(.newData) // } }
Info.plist代码
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>UIApplicationSceneManifest</key> <dict> <key>UIApplicationSupportsMultipleScenes</key> <false/> <key>UISceneConfigurations</key> <dict> <key>UIWindowSceneSessionRoleApplication</key> <array> <dict> <key>UISceneClassName</key> <string>UIWindowScene</string> <key>UISceneDelegateClassName</key> <string>FlutterSceneDelegate</string> <key>UISceneConfigurationName</key> <string>flutter</string> <key>UISceneStoryboardFile</key> <string>Main</string> </dict> </array> </dict> </dict> <key>CFBundleDevelopmentRegion</key> <string>$(DEVELOPMENT_LANGUAGE)</string> <key>CFBundleDisplayName</key> <string>Bongo Payments</string> <key>CFBundleExecutable</key> <string>$(EXECUTABLE_NAME)</string> <key>CFBundleIdentifier</key> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> <key>CFBundleName</key> <string>bongo_pay</string> <key>CFBundlePackageType</key> <string>APPL</string> <key>CFBundleShortVersionString</key> <string>$(FLUTTER_BUILD_NAME)</string> <key>CFBundleSignature</key> <string>????</string> <key>UIBackgroundModes</key> <array> <string>remote-notification</string> </array> <key>FirebaseAppDelegateProxyEnabled</key> <false/> <key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key> <true/> </dict> <key>CFBundleVersion</key> <string>$(FLUTTER_BUILD_NUMBER)</string> <key>NSLocationWhenInUseUsageDescription</key> <string>We need your location to provide better service.</string> <key>NSLocationAlwaysAndWhenInUseUsageDescription</key> <string>This app uses notifications</string> <key>NSLocationAlwaysUsageDescription</key> <string>We need your location even when the app is in the background.</string> <key>NSUserTrackingUsageDescription</key> <string>This app uses notifications</string> <key>LSRequiresIPhoneOS</key> <true/> <key>UILaunchStoryboardName</key> <string>LaunchScreen</string> <key>UIMainStoryboardFile</key> <string>Main</string> <key>NSFaceIDUsageDescription</key> <string>This app requires Face ID authentication to secure your personal data and ensure only you can access your account.</string> <key>NSCameraUsageDescription</key> <string>We need access to your camera to take photos.</string> <key>NSPhotoLibraryUsageDescription</key> <string>We need access to your photo library to upload images.</string> <key>NSAppleMusicUsageDescription</key> <string>This app does not use Apple Music but requires limited media library access for system features.</string> <key>UISupportedInterfaceOrientations</key> <array> <string>UIInterfaceOrientationPortrait</string> <string>UIInterfaceOrientationLandscapeLeft</string> <string>UIInterfaceOrientationLandscapeRight</string> </array> <key>UISupportedInterfaceOrientations~ipad</key> <array> <string>UIInterfaceOrientationPortrait</string> <string>UIInterfaceOrientationPortraitUpsideDown</string> <string>UIInterfaceOrientationLandscapeLeft</string> <string>UIInterfaceOrientationLandscapeRight</string> </array> <key>CADisableMinimumFrameDurationOnPhone</key> <true/> <key>UIApplicationSupportsIndirectInputEvents</key> <true/> <key>io.flutter.embedded_views_preview</key> <true/> <key>NSMicrophoneUsageDescription</key> <string>We need access to your microphone for video or audio capture in web pages.</string> <key>NSPhotoLibraryAddUsageDescription</key> <string>We need access to save images to your photo library.</string> <key>UIFileSharingEnabled</key> <true/> <key>LSSupportsOpeningDocumentsInPlace</key> <true/> <key>UIStatusBarHidden</key> <false/> </dict> </plist>
内容的提问来源于stack exchange,提问作者Kelvin Ekene
相关产品推荐
相关产品推荐

