Flutter中Awesome Notification iOS问题:前台重复通知,后台仅显示一次
解决iOS后台重复通知问题的方案
问题根源
- iOS后台对Timer有严格限制,App进入后台后Timer会被系统暂停,无法按周期触发。
- 每次创建通知都使用同一个
id,iOS会直接覆盖已有通知,不会重复弹出提醒。 - 未申请对应后台权限,无法维持后台定时能力。
具体修复步骤
1. 配置iOS后台权限
在项目的Info.plist中添加后台模式权限,闹钟类App建议同时开启音频和后台处理权限:
<key>UIBackgroundModes</key> <array> <string>audio</string> <string>processing</string> </array>
2. 确保通知ID唯一
每次创建通知时生成唯一ID,避免被系统覆盖,可在原subId基础上拼接时间戳:
int uniqueId = subId! + DateTime.now().millisecondsSinceEpoch ~/ 1000;
3. 用系统级调度替代Timer
不要依赖后台Timer,改用AwesomeNotifications自带的调度功能,直接创建重复通知:
await AwesomeNotifications().createNotification( content: NotificationContent( criticalAlert: true, displayOnBackground: true, displayOnForeground: true, fullScreenIntent: true, id: uniqueId, // 使用生成的唯一ID channelKey: "alarm_Category", title: 'Alarm Reminder', body: 'Your alarm is still active!', autoDismissible: false, payload: receivedNotification.payload, ), schedule: NotificationInterval( interval: 7, // 重复间隔7秒 timeZone: await AwesomeNotifications().getLocalTimeZoneIdentifier(), repeats: true, // 开启重复 ), );
4. 用户点击后终止重复
在onActionReceivedMethod中取消对应闹钟的重复调度,避免用户处理后仍继续发送通知:
static Future<void> onActionReceivedMethod(ReceivedAction receivedAction) async { String? subIdStr = receivedAction.payload?['subId']; if (subIdStr != null) { // 取消该闹钟的所有重复调度 await AwesomeNotifications().cancelSchedulesByKey(subIdStr); // 同时清除已显示的通知 await AwesomeNotifications().cancel(int.parse(subIdStr)); } }
关键注意事项
- iOS后台资源限制严格,即使配置权限,系统也可能在资源紧张时终止App,建议保留
criticalAlert和fullScreenIntent提升通知优先级。 - 务必使用唯一通知ID,否则后台通知会被直接覆盖,无法重复弹出。
- 优先使用系统级调度功能,而非手动维护Timer,更适配iOS后台运行规则。
内容的提问来源于stack exchange,提问作者Thomas lee
相关产品推荐
相关产品推荐

