Flutter iOS端Firebase onMessage在APNS推送时未触发问题
问题解答
firebase_messaging的onMessage回调仅针对通过Firebase Cloud Messaging(FCM)发送的消息生效,直接通过APNS推送的消息不会触发该回调。但你可以通过「原生iOS代码+Flutter MethodChannel通信」的方式,实现iOS端APNS推送的监听和自定义控制,达到和Android端一致的逻辑效果。
具体实现步骤:
1. 调整APNS推送Payload格式
根据你的需求(先接收数据再决定是否展示),推送Payload需要满足:
- 若要在App前台捕获消息:
- 带UI的通知:保留
aps.alert等字段,但需通过原生回调拦截处理; - 静默通知:必须包含
content-available: 1,且不能包含alert、sound等UI相关字段,App会在后台/前台唤醒处理。
- 带UI的通知:保留
- 自定义数据可放在
aps字段外,或aps内的custom字段中,确保能被原生代码读取。
2. iOS原生代码添加通知监听
在AppDelegate.swift中实现UNUserNotificationCenterDelegate的回调,将APNS消息传递给Flutter:
import UIKit import Flutter import FirebaseMessaging @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { FirebaseApp.configure() GeneratedPluginRegistrant.register(with: self) // 配置通知权限与代理 UNUserNotificationCenter.current().delegate = self let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound] UNUserNotificationCenter.current().requestAuthorization(options: authOptions) { _, _ in } application.registerForRemoteNotifications() return super.application(application, didFinishLaunchingWithOptions: launchOptions) } // App前台收到通知时触发,拦截并传递消息给Flutter override func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { let userInfo = notification.request.content.userInfo let channel = FlutterMethodChannel(name: "com.your.app/notification", binaryMessenger: window?.rootViewController as! FlutterBinaryMessenger) channel.invokeMethod("onAPNSForegroundMessage", arguments: userInfo) // 自定义控制是否展示通知:比如根据userInfo判断后调用completionHandler // 不展示:completionHandler([]) // 展示默认样式:completionHandler([.alert, .sound, .badge]) } // 用户点击通知时触发 override func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { let userInfo = response.notification.request.content.userInfo let channel = FlutterMethodChannel(name: "com.your.app/notification", binaryMessenger: window?.rootViewController as! FlutterBinaryMessenger) channel.invokeMethod("onAPNSNotificationTap", arguments: userInfo) completionHandler() } }
3. Flutter侧接收原生传递的消息
创建MethodChannel监听原生发来的APNS消息,实现自定义逻辑:
import 'package:flutter/services.dart'; class APNSNotificationHandler { static const _notificationChannel = MethodChannel('com.your.app/notification'); static void init() { _notificationChannel.setMethodCallHandler((call) async { switch (call.method) { case 'onAPNSForegroundMessage': final Map<String, dynamic> message = Map<String, dynamic>.from(call.arguments); // 这里实现你的自定义逻辑:判断是否展示通知、保存数据等 print('Received APNS foreground message: $message'); break; case 'onAPNSNotificationTap': final Map<String, dynamic> message = Map<String, dynamic>.from(call.arguments); // 处理用户点击通知的逻辑 print('APNS notification tapped: $message'); break; } }); } }
在main.dart的initState中初始化监听:
@override void initState() { super.initState(); APNSNotificationHandler.init(); // 保留原有的FCM监听 FirebaseMessaging.onMessage.listen((RemoteMessage message) { // FCM消息处理逻辑 }); }
4. 关键注意事项
- 确保iOS App开启了「后台刷新」权限(在Xcode的Signing & Capabilities中添加Background Modes,勾选Remote notifications);
- 静默通知的Payload必须严格符合Apple要求:
content-available: 1,无UI字段,且推送时需开启“优先级高”; - 若需要修改通知内容,Payload需添加
mutable-content: 1,并在原生代码中处理通知扩展。
内容的提问来源于stack exchange,提问作者Lea González Cuello
相关产品推荐
相关产品推荐

