Flutter集成OneSignal:后台/关闭时addForegroundWillDisplayListener不触发
你的问题核心是addForegroundWillDisplayListener仅在APP前台时触发,后台或关闭状态下不会执行,因此无法保存通知。以下是针对OneSignal 5.2.2版本的完整解决方案:
1. 重构代码:抽离保存逻辑并补充监听回调
首先将通知保存逻辑抽为独立函数,然后添加全局通知接收监听和启动通知获取,覆盖前台、后台、APP关闭后启动三种场景:
抽离保存逻辑
// 独立的通知保存函数,复用所有场景 Future<void> saveNotificationToSharedPreferences(OSNotification notification) async { // 跳过缺少必要字段的通知 if (notification.additionalData?['myappurl'] == null || notification.title == null || notification.body == null) { return; } String title = notification.title!; String url = notification.additionalData!['myappurl']; String someBody = notification.body!.length > 10 ? notification.body!.substring(0, 10) : notification.body!; SharedPreferences sp = await SharedPreferences.getInstance(); List<OldNotification> oldDatas = readNotificationsFromSharedp(sp, 'SavedNotifications'); OldNotification newSingleData = OldNotification( title: title, url: url, body: someBody, isOpened: false); if (isElementNotExistByURL(oldDatas, newSingleData)) { oldDatas.add(newSingleData); var correctedOrder = oldDatas.reversed.toList(); List<String> favListing = correctedOrder.map((fav) => jsonEncode(fav.toJson())).toList(); await sp.setStringList('SavedNotifications', favListing); } else { print('通知已存在,无需重复保存'); } }
修改初始化逻辑
Future<void> initPlatformState() async { AppConstants constants = AppConstants(); OneSignal.Debug.setLogLevel(OSLogLevel.verbose); OneSignal.Debug.setAlertLevel(OSLogLevel.none); // 确保OneSignal初始化完成 await OneSignal.initialize(constants.OneSignalKey); await OneSignal.Notifications.requestPermission(true); // 通知点击事件处理(保留原有逻辑) OneSignal.Notifications.addClickListener((event) { print('NOTIFICATION CLICK LISTENER CALLED WITH EVENT: $event'); String url = event.notification.additionalData!['myappurl']; webController?.loadUrl(urlRequest: URLRequest(url: WebUri(url))); }); // 前台通知展示前处理(保留原有逻辑) OneSignal.Notifications.addForegroundWillDisplayListener((event) async { print('NOTIFICATION WILL DISPLAY LISTENER CALLED WITH: ${event.notification.jsonRepresentation()}'); event.preventDefault(); event.notification.display(); await saveNotificationToSharedPreferences(event.notification); }); // 全局通知接收监听(前台/后台均触发,iOS需额外配置) OneSignal.Notifications.addNotificationReceivedListener((notification) async { print('NOTIFICATION RECEIVED: ${notification.jsonRepresentation()}'); await saveNotificationToSharedPreferences(notification); }); // 处理APP关闭后点击通知启动的场景 final launchNotification = await OneSignal.Notifications.getLaunchNotification(); if (launchNotification != null) { print('LAUNCH NOTIFICATION: ${launchNotification.jsonRepresentation()}'); await saveNotificationToSharedPreferences(launchNotification); } }
2. iOS端配置:启用Notification Service Extension
iOS默认在后台不会执行Flutter代码,必须通过Service Extension让OneSignal在后台触发通知接收逻辑:
- 打开Xcode中的iOS项目(
ios/Runner.xcworkspace),右键点击Runner文件夹 →New Target。 - 选择
Application Extension分类下的Notification Service Extension,命名为OneSignalNotificationServiceExtension,语言选Swift,点击Finish并激活方案。 - 替换
NotificationService.swift内容:
import UserNotifications import OneSignalFramework class NotificationService: UNNotificationServiceExtension { var contentHandler: ((UNNotificationContent) -> Void)? var bestAttemptContent: UNMutableNotificationContent? override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { self.contentHandler = contentHandler bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent) if let bestAttemptContent = bestAttemptContent { // 委托OneSignal处理通知,触发Flutter端的监听回调 OneSignal.didReceiveNotificationExtensionRequest(request, with: bestAttemptContent) contentHandler(bestAttemptContent) } } override func serviceExtensionTimeWillExpire() { if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent { OneSignal.serviceExtensionTimeWillExpireRequest(bestAttemptContent) contentHandler(bestAttemptContent) } } }
- 在
ios/Podfile中添加Extension的依赖:
target 'OneSignalNotificationServiceExtension' do use_frameworks! use_modular_headers! pod 'OneSignalFramework', '>= 5.0.0' end
然后执行pod install更新依赖。
3. Android端配置(无需额外操作)
OneSignal 5.x版本在Android后台默认会触发addNotificationReceivedListener,只需确保AndroidManifest.xml中已包含OneSignal的默认配置(Flutter插件会自动添加):
<meta-data android:name="com.onesignal.NotificationOpened.DEFAULT" android:value="DISABLE" /> <service android:name="com.onesignal.notifications.services.OSNotificationReceiveService" android:permission="android.permission.BIND_JOB_SERVICE" android:exported="false" />
测试验证
- 前台场景:通知到达,两个监听回调触发,通过去重逻辑避免重复保存。
- 后台场景:通知到达后,
addNotificationReceivedListener触发,自动保存通知,系统正常展示通知。 - APP关闭场景:通知到达后系统展示,用户点击通知启动APP时,
getLaunchNotification获取启动通知并保存。
内容的提问来源于stack exchange,提问作者Biruk Damte
相关产品推荐
相关产品推荐

