Flutter Local Schedule Notification 实现:按用户选定时间每日推送通知
Flutter 实现类闹钟本地通知方案
1. 依赖与基础配置
使用官方维护的 flutter_local_notifications 包处理通知逻辑,搭配 timezone 包处理时区偏差,你需要先在 pubspec.yaml 中引入依赖:
dependencies: flutter: sdk: flutter flutter_local_notifications: ^16.1.0 timezone: ^0.9.2
完成依赖安装后分别做两端基础配置:
- Android 配置:在
android/app/src/main/AndroidManifest.xml中添加通知权限,高版本Android需要额外配置通知渠道权限 - iOS 配置:在
ios/Runner/Info.plist中添加通知权限声明:
<key>NSUserNotificationUsageDescription</key> <string>需要通知权限用于推送定时提醒</string> <key>UIBackgroundModes</key> <array> <string>fetch</string> <string>remote-notification</string> </array>
2. 日期时间选择器实现
可直接使用Flutter自带的 showDatePicker 和 showTimePicker 组合获取用户选定的时间点:
// 先选择日期 DateTime? pickedDate = await showDatePicker( context: context, initialDate: DateTime.now(), firstDate: DateTime.now(), lastDate: DateTime(2100), ); if (pickedDate == null) return; // 再选择时间 TimeOfDay? pickedTime = await showTimePicker( context: context, initialTime: TimeOfDay.now(), ); if (pickedTime == null) return; // 拼接为完整的时间对象 final scheduledTime = DateTime( pickedDate.year, pickedDate.month, pickedDate.day, pickedTime.hour, pickedTime.minute, );
如果需要自定义选择器样式,可按需替换为第三方日期选择组件。
3. 每日重复定时通知逻辑
初始化通知实例
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(); // 初始化逻辑建议放在应用启动页的initState中执行 Future<void> initNotification() async { tz.initializeTimeZones(); const AndroidInitializationSettings androidInit = AndroidInitializationSettings('@mipmap/ic_launcher'); const DarwinInitializationSettings iosInit = DarwinInitializationSettings(); const InitializationSettings initSettings = InitializationSettings(android: androidInit, iOS: iosInit); await notificationsPlugin.initialize(initSettings); // 申请通知权限 await notificationsPlugin .resolvePlatformSpecificImplementation< AndroidFlutterLocalNotificationsPlugin>() ?.requestNotificationsPermission(); await notificationsPlugin .resolvePlatformSpecificImplementation< IOSFlutterLocalNotificationsPlugin>() ?.requestPermissions(); }
配置每日重复通知
// 设置每日重复通知 Future<void> scheduleDailyAlarm(DateTime scheduledTime) async { await notificationsPlugin.zonedSchedule( 0, // 通知唯一ID,不同通知需要使用不同ID '闹钟提醒', // 通知标题 '你设置的定时提醒已触发', // 通知内容 _calcNextTriggerTime(scheduledTime), const NotificationDetails( android: AndroidNotificationDetails( 'daily_alarm_channel', // 通知通道ID '每日闹钟', // 通知通道名称 channelDescription: '每日定时闹钟的通知通道', importance: Importance.max, priority: Priority.high, playSound: true, // 如需自定义闹钟音效可添加sound参数配置 ), iOS: DarwinNotificationDetails(sound: 'alarm_sound.aiff'), ), androidScheduleMode: AndroidScheduleMode.exactAllowWhileIdle, // 低电模式也可触发,保证精准度 uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime, matchDateTimeComponents: DateTimeComponents.time, // 核心配置:按每日固定时分重复触发 ); } // 计算下一次触发时间,避免设置时间已过导致当日立即触发 tz.TZDateTime _calcNextTriggerTime(DateTime scheduledTime) { final tz.TZDateTime now = tz.TZDateTime.now(tz.local); tz.TZDateTime triggerTime = tz.TZDateTime( tz.local, now.year, now.month, now.day, scheduledTime.hour, scheduledTime.minute, ); if (triggerTime.isBefore(now)) { triggerTime = triggerTime.add(const Duration(days: 1)); } return triggerTime; }
4. 注意事项
- 取消指定ID对应的通知调用
notificationsPlugin.cancel(通知ID)即可,取消所有通知使用cancelAll()方法。 - Android 14及以上版本需要额外申请
SCHEDULE_EXACT_ALARM权限才能使用精准闹钟,需在AndroidManifest中添加<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />。 - 部分国产定制系统会限制后台应用通知弹出,需要引导用户将应用加入自启动白名单、后台运行白名单才能保证通知正常触发。
内容的提问来源于stack exchange,提问作者Hadi Khan
相关产品推荐
相关产品推荐

