Flutter iOS端前台无法接收OneSignal静默通知问题排查
iOS Flutter应用前台无法接收OneSignal静默通知的解决方案
核心问题排查
- OneSignal SDK未初始化:你的AppDelegate里完全没初始化OneSignal,这直接导致SDK无法接管通知处理逻辑,静默通知自然没法触发原生回调。
- 前台通知回调未配置:没有设置
UNUserNotificationCenter的delegate,前台收到通知时不会走原生方法,全被OneSignal Flutter插件拦截了。 - 静默通知Payload可能不符合要求:APN发送的静默通知必须严格符合格式,否则iOS不会识别为静默通知。
具体修复步骤
1. 补全OneSignal初始化与Delegate配置
修改AppDelegate.swift,添加OneSignal初始化代码,同时设置通知中心delegate,确保前台通知能触发原生回调:
import Flutter import UIKit import OneSignal // 别忘了导入OneSignal @main @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { print("**** didFinishLaunchingWithOptions ****"); // 初始化OneSignal,替换成你的App ID OneSignal.initialize("YOUR_ONESIGNAL_APP_ID", withLaunchOptions: launchOptions) let center = UNUserNotificationCenter.current() center.requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in if granted { DispatchQueue.main.async { UIApplication.shared.registerForRemoteNotifications() } } } // 设置delegate,确保前台通知能触发原生方法 center.delegate = self GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } // 处理前台收到的所有通知(包括非静默和静默) override func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { print("**** 前台收到通知 ****") let userInfo = notification.request.content.userInfo // 检查是否为静默通知 if let aps = userInfo["aps"] as? [String: Any], aps["content-available"] as? Int == 1 { // 传递给Flutter if let flutterVC = window?.rootViewController as? FlutterViewController { let channel = FlutterMethodChannel(name: "com.shachardev.vivencia/notifications", binaryMessenger: flutterVC.binaryMessenger) channel.invokeMethod("notificationReceived", arguments: userInfo) } // 静默通知不需要展示,直接传空选项 completionHandler([]) } else { // 非静默通知交给OneSignal处理,同时展示通知 OneSignal.didReceiveNotificationExtensionRequest(notification.request, with: notification.request.content.mutableCopy() as! UNMutableNotificationContent, withContentHandler: { content in completionHandler([.alert, .sound, .badge]) }) } } override func application( _ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void ) { print("**** didReceiveRemoteNotification ****"); DispatchQueue.main.async { print("收到通知内容: \(userInfo)") } // 处理静默通知 if let aps = userInfo["aps"] as? [String: Any], aps["content-available"] as? Int == 1 { if let flutterVC = window?.rootViewController as? FlutterViewController { let channel = FlutterMethodChannel(name: "com.shachardev.vivencia/notifications", binaryMessenger: flutterVC.binaryMessenger) channel.invokeMethod("notificationReceived", arguments: userInfo) } completionHandler(.newData) return } // 非静默通知交给OneSignal处理 OneSignal.didReceiveRemoteNotification(userInfo, fetchCompletionHandler: completionHandler) } }
2. 确保静默通知Payload格式正确
通过APN控制台发送的静默通知必须满足:
aps字典必须包含"content-available": 1- 不能有
alert、badge、sound这些会触发通知展示的字段 - 示例Payload:
{ "aps": { "content-available": 1 }, "custom_data": "你的自定义数据" }
3. 验证后台权限配置
- 在Xcode的
Signing & Capabilities中,添加Background Modes,勾选Remote notifications - 确认Info.plist中
UIBackgroundModes数组包含remote-notification
4. 关于NotificationServiceExtension
这个扩展只处理带有mutable-content: 1的通知(比如需要修改通知内容、加附件),静默通知不需要这个扩展,所以它不会触发,属于正常情况。如果不需要修改通知内容,可以直接移除这个扩展。
测试注意事项
- 必须用真机测试,模拟器收不到APN通知
- 设备要登录Apple ID,并且开启了应用的通知权限
- 测试前台静默通知时,确保应用处于完全活跃的前台状态(没被挂起)
内容的提问来源于stack exchange,提问作者Shachar
相关产品推荐
相关产品推荐

