iOS11.4.1下Firebase Messaging无法触发onBackgroundMessage回调
Flutter Firebase Messaging iOS端
onBackgroundMessage回调不触发排查方案 问题表现
- 应用正常接入Firebase后,前台状态
onMessage回调可正常接收推送,后台(未终止)状态下onBackgroundMessage绑定的处理函数始终无响应,debug、release构建环境测试结果一致 - 系统层面已成功接收到APNs推送,可通过Mac端Console日志确认消息投递,但Flutter层回调未触发
- 排除
flutter_local_notifications通知展示环节的干扰,问题出在消息回调注册/投递链路本身
已完成的前置配置校验
- 已通过Firebase控制台关联应用,
GoogleService-Info.plist已正确添加至iOS项目目录 - 已在Firebase控制台上传有效的APNs认证密钥
- 已定义顶层函数作为后台消息处理回调,且在
main()中执行了注册:
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async { // 后台/终止状态下始终未被调用 print("Handling a background message: ${message.messageId}"); // 自定义业务处理逻辑 } // main函数中注册回调 FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
AppDelegate.swift已添加基础推送配置:
import UIKit import Flutter import Firebase import FirebaseMessaging @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { if #available(iOS 10.0, *) { UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate } GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } }
- 已开启Xcode项目的推送通知、后台模式(Remote notifications)能力
- 应用已获取用户的通知权限授权
- 通过Node.js Admin SDK发送仅含data字段、不含notification字段的静默推送,配置如下:
let message = { apns: { headers: { 'apns-priority': '5', }, payload: { aps: { contentAvailable: true }, }, }, android: { priority: 'normal', }, data: { title: "Test", message: "Test", url: "https://www.google.com/" }, topic: topic };
- Console日志确认系统已收到推送:
default 20:48:06.069282+0300 SpringBoard Received incoming message on topic com.matkonit at priority 5 default 20:48:06.082948+0300 SpringBoard [com.matkonit] Received remote notification request 3823-43DB [ waking: 0, hasAlertContent: 0, hasSound: 0 hasBadge: 0 hasContentAvailable: 1 hasMutableContent: 0 pushType: Background] default 20:48:06.083005+0300 SpringBoard [com.matkonit] Process delivery of push notification 3823-43DB
核心修复步骤
1. 补全AppDelegate缺失的关键配置
现有AppDelegate代码缺少Firebase初始化调用、Messaging代理设置、远程通知注册逻辑,且类声明未遵守MessagingDelegate协议,是导致回调链路断裂的最常见原因,修复后完整代码如下:
import UIKit import Flutter import Firebase import FirebaseMessaging // 添加MessagingDelegate协议遵守 @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate, MessagingDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { // 必须在注册Flutter插件前初始化Firebase FirebaseApp.configure() // 设置Firebase Messaging代理 Messaging.messaging().delegate = self 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) } }
注意:FirebaseApp.configure()必须在GeneratedPluginRegistrant.register调用前执行,否则Flutter插件无法正确获取Firebase实例,后台回调注册会静默失效。
2. 修正Flutter侧初始化顺序
确认main()函数中初始化逻辑顺序正确,错误的顺序会导致回调注册失败:
void main() async { // 必须第一行保证Flutter插件绑定初始化 WidgetsFlutterBinding.ensureInitialized(); // 必须先初始化Firebase App await Firebase.initializeApp(); // 最后注册后台消息回调 FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler); runApp(const MyApp()); }
3. 修正静默推送的发送配置
现有推送配置存在多个不符合iOS APNs规则的问题,会导致系统不唤醒应用执行后台逻辑,修复后配置如下:
let message = { apns: { headers: { 'apns-priority': '10', // 设为5会被系统节流延迟投递,静默推送需要立即唤醒应用必须设为10 'apns-push-type': 'background', // iOS13+必填字段,明确指定为后台推送类型 }, payload: { aps: { contentAvailable: true // 静默推送的aps中不能包含alert/sound/badge字段,否则会被系统当作普通前台通知处理 }, }, }, android: { priority: 'high', }, // data字段所有值必须为字符串类型,禁止传入数字、对象等非字符串值 data: { title: "Test", message: "Test", url: "https://www.google.com/" }, topic: topic };
4. 排查系统级拦截问题
- 测试时不要手动上滑杀死应用:iOS系统会默认拦截所有发给用户手动终止应用的静默推送,直到用户下次手动点开应用才会恢复投递
- 确认应用的「后台App刷新」权限处于开启状态,路径:系统设置->对应应用->后台App刷新,开关关闭时系统不会唤醒应用执行后台回调
- 测试时关闭低电量模式,低电量模式下系统会节流所有后台推送活动
- 不要在Xcode附加调试器状态下测试后台回调:Xcode调试会干扰应用后台生命周期,正确测试方式为:Xcode运行安装应用后点击停止,手动从桌面打开应用,切到后台再发送推送
- 首次安装应用后必须至少手动打开一次,系统才会为应用开通推送投递通道,未打开过的新装应用无法接收后台推送
5. 清理编译缓存
执行以下命令清理缓存,避免旧编译产物导致插件注册失效:
- 执行
flutter clean清理Flutter构建缓存 - 删除iOS目录下的
Pods文件夹、Podfile.lock文件 - 进入iOS目录执行
pod install重新安装依赖 - 重新编译运行项目
注意:尽量使用14.0.0以上稳定版firebase_messaging插件,避免beta/dev版本的已知兼容问题。
内容的提问来源于stack exchange,提问作者Tal Barda
相关产品推荐
相关产品推荐

