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

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注册的处理函数有严格的写法要求,你现有代码大概率不符合规范:

  1. 处理函数_firebaseMessagingBackgroundHandler必须是顶级函数,定义在main函数外部,不能放在任何类的内部,否则iOS端的后台isolate无法识别到这个函数。
  2. 后台函数运行在独立的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的推送规则,有几个核心错误:

  1. 缺少APNs必要头字段,后台推送必须设置高优先级与正确的推送类型,否则会被系统节流丢弃。
  2. 注意iOS系统级规则:如果推送Payload包含顶层notification字段,App在后台时系统会直接拦截并展示默认通知,完全不会触发你的后台消息回调。要触发自定义后台逻辑,不要加顶层notification字段,把所有通知内容放在data里,在后台handler中自己调用AwesomeNotifications生成通知。
  3. 你之前在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. 修复环境依赖问题

  1. 你当前CocoaPods版本为1.10.1,存在新版Firebase Messaging的链接bug,会导致后台回调注册失败,先升级CocoaPods到1.11.0以上,升级后重新安装iOS依赖:
sudo gem install cocoapods
cd ios
pod install --repo-update
  1. 不要完全依赖Xcode自动签名,手动去苹果开发者后台确认你的App ID已经勾选Push Notifications、Background Modes -> Remote notifications两个权限,重新生成描述文件安装到本地,避免Xcode自动签名漏开权限。
  • 5. 避开测试误区

很多时候配置没问题,是测试方式错误导致收不到回调:

  1. 不要连着Xcode调试测试后台消息,Xcode会接管应用进程,导致系统静默推送回调无法正常触发。正确测试流程:运行App一次,授予通知权限,将App退到后台(不要手动上滑杀掉App),断开Xcode连接后再发推送。
  2. iOS对静默推送有严格节流,每小时最多给App投递2-3条静默推送,短时间频繁发测试推送会被系统直接丢弃。
  3. 如果用户手动上滑杀掉App,iOS不会投递静默推送,也不会触发后台回调,这是系统级限制,无法绕过。

内容的提问来源于stack exchange,提问作者PeakGen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 04:03:24