Flutter iOS端如何将FCM后台通知数据存储到Hive?
iOS FCM后台通知处理问题解决方案
问题梳理
- iOS与Android均能正常接收后台通知
- Android端可通过
BackgroundHandler将后台通知数据存入Hive - iOS端
BackgroundHandler无法生效 - 疑问:iOS是否支持
BackgroundHandler?若无支持,有何替代方案?iOS能否将后台通知数据保存到Hive?
一、iOS BackgroundHandler不生效的原因及修复
1. 原生AppDelegate配置缺失
你的AppDelegate未正确实现UNUserNotificationCenterDelegate协议,导致通知回调无法触发Flutter的后台Handler。修改如下:
@UIApplicationMain @objc class AppDelegate: FlutterAppDelegate, UNUserNotificationCenterDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { if #available(iOS 10.0, *) { UNUserNotificationCenter.current().delegate = self } GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } // 处理后台通知回调,必须调用completionHandler @available(iOS 10.0, *) func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { completionHandler() } // 处理前台通知显示(可选) @available(iOS 10.0, *) func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { completionHandler([.badge, .sound, .alert]) } }
2. BackgroundHandler优化(减少后台耗时操作)
iOS后台任务执行时间有限,需简化Hive操作,避免不必要的盒子关闭/打开动作:
@pragma('vm:entry-point') Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async { await Firebase.initializeApp( options: DefaultFirebaseOptions.currentPlatform, ); if (!Hive.isAdapterRegistered(1)) { Hive.registerAdapter<PushNotificationModel>(PushNotificationModelAdapter()); } // 仅在盒子未打开时执行打开操作 if (!Hive.isBoxOpen(HiveBoxConstant.BACKGROUND_NOTIFICATION_LIST)) { await Hive.openBox<PushNotificationModel>(HiveBoxConstant.BACKGROUND_NOTIFICATION_LIST); } if (!Hive.isBoxOpen(HiveBoxConstant.NOTIFICATION_LIST)) { await Hive.openBox<PushNotificationModel>(HiveBoxConstant.NOTIFICATION_LIST); } await FCMManager.saveNotificationList(message, true); // 无需强制关闭盒子,后台任务结束后系统会自动清理资源 }
3. APNs Payload优化
确保payload配置符合iOS后台通知要求,补充apns-topic字段(值为你的App Bundle ID):
payload: { 'aps': { 'badge': 1, 'sound': 'default', 'content_available': true, 'alert': { 'title': '通知标题', 'body': '通知内容' } } }, headers: { "apns-priority": "10", "apns-topic": "com.your.app.bundle.id" }
二、BackgroundHandler失效的替代方案
1. 原生回调+MethodChannel传递数据
在iOS原生层拦截通知,通过MethodChannel将数据传递给Flutter处理:
Flutter端:
const MethodChannel _notificationChannel = MethodChannel('com.your.app/notification_handler'); void main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform); // 监听原生传递的通知数据 _notificationChannel.setMethodCallHandler((call) async { if (call.method == 'handleBackgroundNotification') { Map<String, dynamic> messageData = call.arguments; RemoteMessage message = RemoteMessage.fromMap(messageData); await FCMManager.saveNotificationList(message, true); } }); runApp(...); }
iOS原生端:
override func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { let channel = FlutterMethodChannel(name: "com.your.app/notification_handler", binaryMessenger: window?.rootViewController as! FlutterBinaryMessenger) channel.invokeMethod("handleBackgroundNotification", arguments: userInfo) completionHandler(.newData) }
2. 启动时补全未处理通知
在App启动时拉取初始通知,同时监听通知点击事件,补充保存数据:
void main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform); // 处理启动App的通知 RemoteMessage? initialMessage = await FirebaseMessaging.instance.getInitialMessage(); if (initialMessage != null) { await FCMManager.saveNotificationList(initialMessage, true); } // 处理用户点击通知启动App的情况 FirebaseMessaging.onMessageOpenedApp.listen((message) { FCMManager.saveNotificationList(message, true); }); runApp(...); }
三、iOS端能否将后台通知数据保存到Hive?
可以保存,但需注意:
- 控制操作耗时:iOS后台任务仅提供约30秒执行时间,需简化Hive操作,避免复杂IO
- 线程安全:确保后台与前台操作Hive盒子时无冲突,尽量避免同时读写同一盒子
- 权限:默认App已拥有文档目录读写权限,无需额外配置
内容的提问来源于stack exchange,提问作者LeeDongHee
相关产品推荐
相关产品推荐

