You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 17:25:00