Firebase Cloud Messaging iOS端通知卡在scheduled状态无法送达问题
Flutter FCM iOS端无法接收通知排查方案
基础配置校验
- 确认Xcode项目的
Bundle ID和Firebase控制台登记的完全一致,注意大小写和后缀不要写错,同时确认GoogleService-Info.plist是从对应Firebase项目下载、正确拖入Xcode,勾选了Copy items if needed和对应target。 - 检查APNs密钥的权限:确认生成APNs密钥时勾选了Apple Push Notifications service (APNs) 权限,且上传到Firebase控制台时填写的Team ID和苹果开发者账号Team ID完全匹配,没有输错。
- 确认测试物理设备没有开启通知屏蔽,去iOS设置-通知里找到对应的应用,确认允许通知的开关是开启状态,对应的横幅、声音等权限和申请的匹配。
- 检查当前的构建模式:如果是debug模式下调试,确认Xcode的Signing & Capabilities里Push Notifications的环境是Development,Firebase控制台发送通知时不要选错APNs环境。
- 确认
ios/Runner/AppDelegate.swift里已经添加了FCM的APNs代理配置,示例代码如下:
import UIKit import Flutter import FirebaseMessaging @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { GeneratedPluginRegistrant.register(with: self) Messaging.messaging().delegate = self return super.application(application, didFinishLaunchingWithOptions: launchOptions) } override func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { Messaging.messaging().apnsToken = deviceToken super.application(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken) } }
代码逻辑问题修复
现有代码缺少前台接收通知的监听逻辑,FCM默认不会在应用前台时弹出通知,需要主动监听FirebaseMessaging.onMessage事件,配合flutter_local_notifications包主动弹出前台通知,补充逻辑参考:
// 先引入flutter_local_notifications包,初始化本地通知 final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); void internNotifications() async { FirebaseMessaging messaging = FirebaseMessaging.instance; // 初始化本地通知 const AndroidInitializationSettings initializationSettingsAndroid = AndroidInitializationSettings('@mipmap/ic_launcher'); final DarwinInitializationSettings initializationSettingsDarwin = DarwinInitializationSettings( requestAlertPermission: true, requestBadgePermission: true, requestSoundPermission: true, ); final InitializationSettings initializationSettings = InitializationSettings( android: initializationSettingsAndroid, iOS: initializationSettingsDarwin, ); await flutterLocalNotificationsPlugin.initialize(initializationSettings); // 监听前台通知事件 FirebaseMessaging.onMessage.listen((RemoteMessage message) { RemoteNotification? notification = message.notification; AppleNotification? apple = message.notification?.apple; if (notification != null && apple != null) { flutterLocalNotificationsPlugin.show( notification.hashCode, notification.title, notification.body, const NotificationDetails( iOS: DarwinNotificationDetails(), ), ); } }); // 原有逻辑保持不变 String token = await messaging.getToken( vapidKey: "BP_yTdkgwyo2GEdNdjn8KIz874lEdaKaDWVz5wHKpb1_48RBU4UKUmPiRhG1DT7ViHvY7cy8goNZOQE3a0X6yiM", ); // 打印token,确认Firebase控制台发送测试通知时填的是这个真实获取到的token print('FCM Token: $token'); RemoteMessage initialMessage = await FirebaseMessaging.instance.getInitialMessage(); if (initialMessage != null) { _handleMessage(initialMessage); } FirebaseMessaging.onMessageOpenedApp.listen(_handleMessage); NotificationSettings settings = await messaging.requestPermission( alert: true, announcement: false, badge: true, carPlay: false, criticalAlert: false, provisional: false, sound: true, ); print('User granted permission: ${settings.authorizationStatus}'); // *确认打印的权限状态是authorized,如果是denied说明用户没给权限,无法接收通知* } void _handleMessage(RemoteMessage message) { if (message.data['type'] == 'chat') { Navigator.pushNamed( context, '/chat', ); } }
调试验证步骤
- 运行应用后先看控制台输出,确认权限状态为
authorized,且成功打印出了FCM Token,复制这个Token到Firebase控制台的发送测试通知界面,选择对应iOS设备发送,不要用全量推送测试。 - 如果还是收不到,直接用苹果的APNs测试工具发送测试通知到设备,确认是APNs链路问题还是FCM的配置问题:如果APNs能收到,就是Firebase和APNs的绑定配置有误,重新检查APNs密钥、Team ID、Bundle ID的匹配性。
内容的提问来源于stack exchange,提问作者MikeBrock03
相关产品推荐
相关产品推荐

