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

Flutter实现自定义重复本地通知:按周几、时段、间隔触发

Flutter 本地通知:按指定星期、时段与间隔触发

需求说明

  • 支持选择通知触发的星期(如周日、周一)
  • 可设置通知触发的时间范围(如下午4-5点)
  • 自定义通知触发间隔(如每5分钟)
  • 仅在选定星期的指定时段内,按设置间隔触发通知

实现代码

void generateAndScheduleNotifications() {
    // 从Hive获取用户设置的通知间隔分钟数
    hiveController.retrieveCustomMinute();

    // 将用户设置的开始时间转换为UTC时间
    DateTime start = convertTimeOfDayToDateTime(startTime).toUtc();
    // 结束时间设置为30天后的同一时段(可根据需求调整时长)
    DateTime end = convertTimeOfDayToDateTime(endTime).toUtc().add(const Duration(days: 30));

    print('为以下星期生成通知: $selectedDayNames');

    // 生成符合选定星期的每日起始时间规则
    final rule = RecurrenceRule(
      frequency: Frequency.daily,
      until: end,
      byWeekDays: selectedDayNames,
    );

    // 获取所有符合规则的起始时间点
    final instances = rule
        .getInstances(
            start: DateTime.utc(start.year, start.month, start.day, start.hour,
                start.minute, start.second))
        .toList();

    // 转换为本地时区(这里使用尼泊尔时区,可根据需求修改)
    final dates = instances
        .map((instance) =>
            tz.TZDateTime.from(instance, tz.getLocation('Asia/Kathmandu')))
        .toList();

    print('待调度的每日起始时间: $dates');
    _scheduleDailyAndMinutelyNotifications(dates);
  }

  Future<void> _scheduleDailyAndMinutelyNotifications(
      List<tz.TZDateTime> dailyDates) async {
    // 获取用户设置的结束时间
    DateTime end = convertTimeOfDayToDateTime(endTime);

    for (final dailyDate in dailyDates) {
      // 构造当日的通知结束时间(UTC)
      DateTime endDate = DateTime(dailyDate.year, dailyDate.month,
              dailyDate.day, end.hour, end.minute, end.second)
          .toUtc();

      // 调度当日的起始通知(可选,若不需要可移除)
      await _scheduleDailyNotification(dailyDate);

      // 调度当日时段内的间隔通知
      await generateAndScheduleMinutelyNotifications(dailyDate, endDate);
    }

    print('所有通知调度完成');
  }

  Future<void> _scheduleDailyNotification(tz.TZDateTime dailyDate) async {
    await flutterLocalNotificationsPlugin.zonedSchedule(
      dailyDate.hashCode, // 用时间哈希作为唯一通知ID
      '定时通知',
      '每日通知: ${DateFormat('yyyy-MM-dd EEEE HH:mm').format(dailyDate)}',
      dailyDate,
      const NotificationDetails(
        android:
            AndroidNotificationDetails('daily_channel', '每日通知频道'),
      ),
      androidAllowWhileIdle: true, // 允许在设备休眠时触发
      uiLocalNotificationDateInterpretation:
          UILocalNotificationDateInterpretation.absoluteTime,
      matchDateTimeComponents: DateTimeComponents.dateAndTime,
    );
    print('每日通知已调度: $dailyDate');
  }

  Future<void> generateAndScheduleMinutelyNotifications(
      tz.TZDateTime dailyDate, DateTime endDate) async {
    DateTime start = dailyDate.toUtc();

    print('生成从 $start 到 $endDate 的间隔通知');

    // 生成按用户设置间隔触发的时间规则
    final rule = RecurrenceRule(
      frequency: Frequency.minutely,
      until: DateTime.utc(endDate.year, endDate.month, endDate.day,
          endDate.hour, endDate.minute, endDate.second),
      interval: hiveController.customMinute ?? 5, // 使用用户设置的间隔,默认5分钟
    );

    // 获取所有符合间隔规则的时间点
    final instances = rule
        .getInstances(
            start: DateTime.utc(start.year, start.month, start.day, start.hour,
                start.minute, start.second))
        .toList();

    // 转换为本地时区
    final dates = instances
        .map((instance) =>
            tz.TZDateTime.from(instance, tz.getLocation('Asia/Kathmandu')))
        .toList();

    print('待调度的间隔通知时间点: $dates');

    await _scheduleNotifications(dates);
  }

  Future<void> _scheduleNotifications(List<tz.TZDateTime> dates) async {
    for (final date in dates) {
      await flutterLocalNotificationsPlugin.zonedSchedule(
        date.hashCode, // 唯一ID
        '定时通知',
        '间隔通知: ${DateFormat('yyyy-MM-dd EEEE HH:mm').format(date)}',
        date,
        const NotificationDetails(
            android: AndroidNotificationDetails(
                'interval_channel', '间隔通知频道')),
        androidAllowWhileIdle: true,
        uiLocalNotificationDateInterpretation:
            UILocalNotificationDateInterpretation.absoluteTime,
        matchDateTimeComponents: DateTimeComponents.time,
      );
    }

    print('所有间隔通知调度完成');
  }

关键说明

  1. 依赖库:需在pubspec.yaml中添加以下依赖:
    flutter_local_notifications: ^16.1.0
    timezone: ^0.9.2
    hive: ^2.2.3
    hive_flutter: ^1.1.0
    
  2. 时区配置:代码中使用Asia/Kathmandu时区,可根据用户所在地区修改为对应时区(如Asia/Shanghai)。
  3. 通知ID:使用时间的哈希值作为唯一ID,避免重复调度同一通知。
  4. 用户配置:selectedDayNames(选定星期)、startTime/endTime(时间范围)、customMinute(间隔分钟数)需从用户界面获取并存储到Hive中。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 12:02:18