Flutter用awesome_notifications实现指定时间暂停恢复定时通知
指定时间段暂停/恢复定时通知的实现方案
你之前通过实时格式化当前时间做字符串匹配、再触发取消通知的逻辑无法生效,核心原因是这段判断代码只有在主动执行时才会运行,App在后台、进程挂起状态下不会持续轮询时间,一旦执行时机跳过15:00的时间点,就完全不会触发取消操作,根本做不到精准时间控制。
具体实现步骤
用awesome_notifications自带的日历调度+通知创建监听实现,不需要App常驻前台,系统级调度可以保证到点精准触发:
- 第一步:固定所有通知的ID,不要用随机ID,避免取消通知时找不到目标、误删其他调度任务
// 固定ID常量 const int waterReminderId = 10001; // 喝水提醒通知ID const int stopScheduleId = 10086; // 15:00停止通知的调度ID const int resumeScheduleId = 10087; // 15:20恢复通知的调度ID
- 第二步:注册两个固定时间点的静默调度任务,专门负责通知的启停
// 注册15:00自动停止提醒的调度 Future<void> registerStopTask() async { String localTimeZone = await AwesomeNotifications().getLocalTimeZoneIdentifier(); await AwesomeNotifications().createNotification( content: NotificationContent( id: stopScheduleId, channelKey: 'scheduled_channel', // 设为静默通知,触发时不弹出提示 silent: true, title: '', body: '', ), // 每天15:00:00精准触发 schedule: NotificationCalendar( hour: 15, minute: 0, second: 0, timeZone: localTimeZone, repeats: true, ), ); } // 注册15:20自动恢复提醒的调度 Future<void> registerResumeTask() async { String localTimeZone = await AwesomeNotifications().getLocalTimeZoneIdentifier(); await AwesomeNotifications().createNotification( content: NotificationContent( id: resumeScheduleId, channelKey: 'scheduled_channel', silent: true, title: '', body: '', ), // 每天15:20:00精准触发 schedule: NotificationCalendar( hour: 15, minute: 20, second: 0, timeZone: localTimeZone, repeats: true, ), ); }
- 第三步:修改原有喝水提醒的创建代码,使用固定ID,修复时区取值bug
Future<void> createWaterReminderNotification() async { String localTimeZone = await AwesomeNotifications().getLocalTimeZoneIdentifier(); // 修复原代码里utc时区取值错误的问题 // String utcTimeZone = await AwesomeNotifications().getUtcTimeZoneIdentifier(); await AwesomeNotifications().createNotification( content: NotificationContent( id: waterReminderId, // 使用固定ID channelKey: 'scheduled_channel', title: 'Notification at every single minute', body: 'This notification was schedule to repeat at every single minute.', notificationLayout: NotificationLayout.BigPicture, bigPicture: 'asset://assets/images/dariSDM-modified.png'), schedule: NotificationInterval( interval: 60, timeZone: localTimeZone, repeats: true)); }
- 第四步:注册通知创建流监听,收到启停任务的调度信号时执行对应操作
在App初始化通知的位置添加监听:
AwesomeNotifications().createdStream.listen((notification) { // 触发15点停止任务:只取消喝水提醒,不要删除两个启停调度 if (notification.id == stopScheduleId) { AwesomeNotifications().cancel(waterReminderId); } // 触发15点20恢复任务:重新创建60秒间隔的提醒 if (notification.id == resumeScheduleId) { createWaterReminderNotification(); } });
- 第五步:初始化时注册所有调度
App首次启动、用户重新开启通知权限时,依次调用registerStopTask()、registerResumeTask()、createWaterReminderNotification()即可,不需要额外做时间判断。
注意:不要调用
cancelScheduledNotifications()或者cancelAll()类的全量取消方法,会把两个启停调度任务一起删掉,导致第二天的启停逻辑失效,所有取消操作都只针对固定ID的喝水提醒。
方案优势
- 所有时间触发逻辑交给系统级通知调度实现,不需要App前台运行、不需要自行轮询时间,时间精度可达秒级
- 不存在原字符串匹配方案的漏触发问题,只要调度注册完成,到点系统会自动唤醒App执行对应逻辑
- 配置一次后长期生效,不需要每日重复注册
内容的提问来源于stack exchange,提问作者wahyu
相关产品推荐
相关产品推荐

