Flutter中如何用flutter_local_notifications实现隔N天定时推送本地通知
实现每隔N天固定时间推送本地通知(基于flutter_local_notifications)
flutter_local_notifications插件本身没有提供直接的「每隔N天固定时间」重复通知选项,但可以通过两种方式实现需求:
方法一:手动计算下一次通知时间,触发后重新调度
这种方式跨平台兼容,且能严格保证固定时间推送,是更可靠的方案。
实现步骤
初始化插件及时区支持
先完成插件初始化并引入时区依赖,确保跨时区时间计算准确:import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:timezone/timezone.dart' as tz; import 'package:timezone/data/latest.dart' as tz; final FlutterLocalNotificationsPlugin _notificationsPlugin = FlutterLocalNotificationsPlugin(); void initNotifications() async { // 初始化时区数据 tz.initializeTimeZones(); // 平台初始化配置(根据项目需求补充Android/iOS图标、权限等设置) const initSettings = InitializationSettings( android: AndroidInitializationSettings('@mipmap/ic_launcher'), iOS: IOSInitializationSettings(), ); await _notificationsPlugin.initialize(initSettings, onSelectNotification: (payload) async { // 用户点击通知后,重新调度下一次通知 _scheduleNextNotification(2, const TimeOfDay(hour: 20, minute: 0)); }, ); }编写时间计算逻辑
精准计算下一次通知的触发时间:如果当前时间已过当日目标时间,则推至次日目标时间;否则直接使用当日目标时间,确保首次推送不延迟:tz.TZDateTime _calculateNextTriggerTime(int daysInterval, TimeOfDay targetTime) { final now = tz.TZDateTime.now(tz.local); var nextTrigger = tz.TZDateTime( tz.local, now.year, now.month, now.day, targetTime.hour, targetTime.minute, ); // 当前时间已过当日目标时间,自动顺延至次日 if (nextTrigger.isBefore(now)) { nextTrigger = nextTrigger.add(const Duration(days: 1)); } return nextTrigger; }调度通知及重复逻辑
每次调度时计算好下一次的触发时间,覆盖之前的同ID通知,确保重复逻辑连贯。Android平台可额外通过广播监听通知触发事件,避免应用后台时无法自动重新调度:void _scheduleNextNotification(int daysInterval, TimeOfDay targetTime) async { final baseTime = _calculateNextTriggerTime(daysInterval, targetTime); // 叠加间隔天数,得到下一次的准确触发时间 final nextScheduledTime = baseTime.add(Duration(days: daysInterval - 1)); await _notificationsPlugin.zonedSchedule( 0, // 固定通知ID,后续调度会覆盖之前的设置 '定时提醒', '这是每隔${daysInterval}天的固定时间通知', nextScheduledTime, const NotificationDetails( android: AndroidNotificationDetails( 'fixed_interval_channel', '固定间隔通知', channelDescription: '用于发送每隔N天的固定时间通知', importance: Importance.max, priority: Priority.high, ), ), androidAllowWhileIdle: true, uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime, payload: 'repeat_notification', ); } // 调用示例:开启每隔2天、20:00的推送 void start2DayRepeatNotification() { _scheduleNextNotification(2, const TimeOfDay(hour: 20, minute: 0)); }
方法二:Android平台自定义重复间隔(仅适合非严格固定时间场景)
Android平台支持直接设置自定义时间间隔的重复通知,但iOS不支持该方式(会导致时间偏移),且无法保证严格的固定时间(若通知延迟触发,后续时间会同步偏移)。
实现代码
void scheduleAndroidCustomIntervalNotification() async { final now = DateTime.now(); var scheduledDate = DateTime(now.year, now.month, now.day, 20, 0); // 当前时间已过当日目标时间,顺延至次日 if (scheduledDate.isBefore(now)) { scheduledDate = scheduledDate.add(const Duration(days: 1)); } await _notificationsPlugin.schedule( 0, '定时提醒', '每隔2天的通知', scheduledDate, const NotificationDetails( android: AndroidNotificationDetails( 'custom_interval_channel', '自定义间隔通知', channelDescription: '用于发送自定义间隔的通知', ), ), repeatInterval: const Duration(days: 2), // 自定义2天间隔 androidAllowWhileIdle: true, ); }
关键注意事项
- 后台存活问题:如果应用被完全杀死,手动调度逻辑会失效。Android可结合
WorkManager定期检查并重新调度;iOS需开启「Background App Refresh」权限,在后台唤醒时恢复调度。 - 持久化设置:建议用
shared_preferences保存用户的通知配置(间隔天数、目标时间),应用启动时自动恢复调度。 - iOS限制:iOS对后台任务有严格管控,长期后台可能无法保证通知准时触发,方法一是iOS唯一可靠的实现方式。
内容的提问来源于stack exchange,提问作者truong luu
相关产品推荐
相关产品推荐

