You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中如何实现每日不同时间的定时重复通知?

实现Flutter每日动态时间推送通知方案

核心思路

periodicallyShow仅支持固定间隔重复推送,无法满足每日不同时间的需求,因此采用单次预约+触发后自动预约下一次的模式:

  • 每次仅预约当日未到时间或次日的单次通知
  • 通知触发时,立即生成下一日的推送时间并完成预约
  • APP启动时自动检查并补预约当日通知

代码修改与实现

1. 新增动态时间生成方法

根据需求生成下一次推送时间,示例为随机生成6-22点的任意时间,可替换为自定义规则(如从预设时间列表选取):

// 生成下一个推送时间:若当前时间已过当日目标时间,则顺延至次日
tz.TZDateTime _getNextNotificationTime() {
  final now = tz.TZDateTime.now(tz.local);
  // 随机生成6-22点之间的小时和分钟
  final randomHour = Random().nextInt(17) + 6;
  final randomMinute = Random().nextInt(60);
  var scheduledDate = tz.TZDateTime(
    tz.local,
    now.year,
    now.month,
    now.day,
    randomHour,
    randomMinute,
  );
  // 若当前时间已过当日预约时间,自动推至次日
  if (scheduledDate.isBefore(now)) {
    scheduledDate = scheduledDate.add(const Duration(days: 1));
  }
  return scheduledDate;
}

2. 重构单次通知调度方法

封装单次预约逻辑,确保通知配置统一:

static Future _scheduleSingleNotification({
  required int id,
  required String title,
  required String body,
  required String payload,
  required tz.TZDateTime scheduledTime,
}) async {
  const AndroidNotificationDetails androidDetails = AndroidNotificationDetails(
    'daily_dynamic_channel',
    '每日动态通知',
    channelDescription: '每天不同时间推送的通知频道',
    importance: Importance.max,
    priority: Priority.high,
  );
  const NotificationDetails notificationDetails =
      NotificationDetails(android: androidDetails);

  await _flutterLocalNotificationsPlugin.zonedSchedule(
    id,
    title,
    body,
    scheduledTime,
    notificationDetails,
    androidScheduleMode: AndroidScheduleMode.exactAllowWhileIdle,
    uiLocalNotificationDateInterpretation:
        UILocalNotificationDateInterpretation.absoluteTime,
    payload: payload,
  );
}

3. 完善通知触发回调

在通知触发后自动预约下一次推送:

static void onNotificationTap(NotificationResponse notificationResponse) {
  onClickNotification.add(notificationResponse.payload!);
  // 通知触发后立即预约下一日的通知
  scheduleNextDailyNotification(
    title: "每日提醒",
    body: "今日提醒已送达",
    payload: "daily_notification_payload",
  );
}

4. 新增首次预约入口方法

用于APP启动时初始化首次通知预约:

static Future scheduleNextDailyNotification({
  required String title,
  required String body,
  required String payload,
}) async {
  tz.initializeTimeZones();
  final nextTime = _getNextNotificationTime();
  // 用日期拼接成唯一ID,避免重复预约
  final notificationId = int.parse("${nextTime.year}${nextTime.month}${nextTime.day}");
  await _scheduleSingleNotification(
    id: notificationId,
    title: title,
    body: body,
    payload: payload,
    scheduledTime: nextTime,
  );
}

5. 启动时自动初始化预约

在原有init方法末尾添加首次预约逻辑:

static Future init() async {
  // 保留原有的初始化代码...
  
  await _flutterLocalNotificationsPlugin.initialize(initializationSettings,
      onDidReceiveNotificationResponse: onNotificationTap,
      onDidReceiveBackgroundNotificationResponse: onNotificationTap);
  
  // APP启动时自动预约下一次通知
  await scheduleNextDailyNotification(
    title: "每日提醒",
    body: "新的一天提醒已安排",
    payload: "initial_daily_payload",
  );
}

关键注意事项

  • 时区处理:必须使用tz包的TZDateTime,避免时区偏差导致通知时间错误
  • 通知ID唯一性:每日使用不同ID(如日期拼接),防止覆盖未触发的预约
  • 安卓权限配置:在AndroidManifest.xml中添加精确闹钟权限:
    <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
    <uses-permission android:name="android.permission.USE_EXACT_ALARM" />
    
  • 后台回调配置:确保onDidReceiveBackgroundNotificationResponse正常工作,保证APP后台时也能自动预约下一次通知

内容的提问来源于stack exchange,提问作者Auvee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 23:04:56