Flutter集成FCM后台通知Android正常iOS监听器不触发问题
Flutter Firebase Messaging iOS 端后台回调不触发修复方案
按以下步骤逐一修复配置问题即可解决:
1. 补全AppDelegate缺失的系统回调
你在Info.plist里关闭了Firebase的App Delegate自动代理(FirebaseAppDelegateProxyEnabled = false),这种情况下Firebase不会自动接管系统推送回调,必须手动实现静默推送接收方法,否则系统收到的后台消息根本无法透传给Flutter层的SDK。
直接替换现有AppDelegate.swift代码:
import UIKit import Flutter import GoogleMaps import Firebase import FirebaseMessaging @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { GMSServices.provideAPIKey("xxxxxxx-xxxx") // 注册通知权限与远程通知 if #available(iOS 10.0, *) { UNUserNotificationCenter.current().delegate = self let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound] UNUserNotificationCenter.current().requestAuthorization( options: authOptions, completionHandler: { _, _ in } ) } else { let settings: UIUserNotificationSettings = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil) application.registerUserNotificationSettings(settings) } application.registerForRemoteNotifications() GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } override func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { Messaging.messaging().apnsToken = deviceToken super.application(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken) } // 核心:补全后台静默推送接收入口 override func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { Messaging.messaging().appDidReceiveMessage(userInfo) super.application(application, didReceiveRemoteNotification: userInfo, fetchCompletionHandler: completionHandler) } }
2. 修正Dart层后台消息处理逻辑
onBackgroundMessage注册的处理函数有严格的写法要求,你现有代码大概率不符合规范:
- 处理函数
_firebaseMessagingBackgroundHandler必须是顶级函数,定义在main函数外部,不能放在任何类的内部,否则iOS端的后台isolate无法识别到这个函数。 - 后台函数运行在独立的isolate中,没有主进程的初始化上下文,函数内部必须先重新初始化Firebase,再执行业务逻辑,参考写法:
// 写在main函数外面,顶级作用域 Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async { // 必须先初始化Firebase await Firebase.initializeApp(); // 如果要在后台发通知,也要重新初始化AwesomeNotifications AwesomeNotifications().initialize('resource://drawable/logo', [ NotificationChannel( channelGroupKey: 'basic_tests', channelKey: 'basic_channel', channelName: 'Basic notifications', channelDescription: 'Notification channel for basic tests', defaultColor: Color(0xFF9D50DD), ledColor: Colors.white, importance: NotificationImportance.High), ]); developer.log("后台收到消息: ${message.data}"); // 原有消息分类、发通知的逻辑放这里 if (message.data["data_type"] == "TEXT") { await AwesomeNotifications().createNotification( content: NotificationContent( id: UniqueKey().hashCode, groupKey: message.data["senderUid"], channelKey: 'basic_channel', title: message.data["title"], body: message.data["body"], summary: message.data["body"], notificationLayout: NotificationLayout.Messaging, displayOnBackground: true, displayOnForeground: true), ); } // 图片类型通知逻辑自行补全 } void main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(); // 注册顺序没问题,确保handler是上面的顶级函数即可 FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler); // 剩下的main函数原有逻辑不变 // ... }
3. 修正推送Payload配置
你现有Payload不符合iOS的推送规则,有几个核心错误:
- 缺少APNs必要头字段,后台推送必须设置高优先级与正确的推送类型,否则会被系统节流丢弃。
- 注意iOS系统级规则:如果推送Payload包含顶层
notification字段,App在后台时系统会直接拦截并展示默认通知,完全不会触发你的后台消息回调。要触发自定义后台逻辑,不要加顶层notification字段,把所有通知内容放在data里,在后台handler中自己调用AwesomeNotifications生成通知。 - 你之前在apns.payload里重复写data字段是多余的,Firebase会自动把顶层data透传到APNs负载中,不需要重复定义。
正确的Payload参考:
"message": { "token": "接收方FCM令牌", "data": { "title": "发送方昵称", "body": "消息内容", "chatRoomId": "聊天室ID", "sender_profile_pic": "发送方头像地址", "senderUid": "发送方UID", "data_type": "TEXT/IMAGE", "click_action": "OPEN_CHAT_ROOM" }, "android": { "priority": "high" }, "apns": { "headers": { "apns-priority": "10", "apns-push-type": "background" }, "payload": { "aps": { "category": "OPEN_CHAT_ROOM", "sound": "default", "content-available": 1, "thread-id": "OPEN_CHAT_ROOM" } } } }
4. 修复环境依赖问题
- 你当前CocoaPods版本为1.10.1,存在新版Firebase Messaging的链接bug,会导致后台回调注册失败,先升级CocoaPods到1.11.0以上,升级后重新安装iOS依赖:
sudo gem install cocoapods cd ios pod install --repo-update
- 不要完全依赖Xcode自动签名,手动去苹果开发者后台确认你的App ID已经勾选
Push Notifications、Background Modes -> Remote notifications两个权限,重新生成描述文件安装到本地,避免Xcode自动签名漏开权限。
5. 避开测试误区
很多时候配置没问题,是测试方式错误导致收不到回调:
- 不要连着Xcode调试测试后台消息,Xcode会接管应用进程,导致系统静默推送回调无法正常触发。正确测试流程:运行App一次,授予通知权限,将App退到后台(不要手动上滑杀掉App),断开Xcode连接后再发推送。
- iOS对静默推送有严格节流,每小时最多给App投递2-3条静默推送,短时间频繁发测试推送会被系统直接丢弃。
- 如果用户手动上滑杀掉App,iOS不会投递静默推送,也不会触发后台回调,这是系统级限制,无法绕过。
内容的提问来源于stack exchange,提问作者PeakGen
相关产品推荐
相关产品推荐

