如何用flutter_local_notification实现每日20:00本地通知(支持后台/被杀状态)
实现每日定时本地通知(后台/终止状态仍生效)
针对你的需求,以下是两种可行的实现方案,覆盖本地通知和Firebase推送两种场景,确保APP在后台甚至被终止时仍能触发通知:
方案一:使用flutter_local_notifications + android_alarm_manager_plus(本地定时)
该方案适用于无网络依赖的场景,Android端可实现类似闹钟的持久触发,iOS端受系统限制需做适配。
1. 依赖配置
在pubspec.yaml中添加依赖:
dependencies: flutter_local_notifications: ^16.1.0 android_alarm_manager_plus: ^4.0.1
执行flutter pub get安装依赖。
2. 平台配置
Android
在android/app/src/main/AndroidManifest.xml中添加权限和配置:
<!-- 允许接收开机广播,重启后恢复定时任务 --> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/> <!-- 允许唤醒设备触发通知 --> <uses-permission android:name="android.permission.WAKE_LOCK"/> <!-- 允许在设备休眠时触发任务 --> <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/> <application ...> <!-- 注册闹钟广播接收器(用于开机重启任务) --> <receiver android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationBootReceiver"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED"/> <action android:name="android.intent.action.MY_PACKAGE_REPLACED"/> </intent-filter> </receiver> </application>
iOS
在ios/Runner/Info.plist中添加后台权限配置:
<key>UIBackgroundModes</key> <array> <string>fetch</string> <string>remote-notification</string> </array> <key>NSNotificationSettingsUsageDescription</key> <string>需要发送每日定时通知</string>
3. 代码实现
初始化通知插件
import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:android_alarm_manager_plus/android_alarm_manager_plus.dart'; final FlutterLocalNotificationsPlugin _notificationsPlugin = FlutterLocalNotificationsPlugin(); Future<void> initNotifications() async { // Android初始化配置 const AndroidInitializationSettings androidInit = AndroidInitializationSettings('@mipmap/ic_launcher'); // iOS初始化配置 final DarwinInitializationSettings iosInit = DarwinInitializationSettings( requestAlertPermission: true, requestBadgePermission: true, requestSoundPermission: true, ); // 统一初始化 await _notificationsPlugin.initialize( InitializationSettings(android: androidInit, iOS: iosInit), ); }
设置每日8点定时任务
// 计算下一个8点的时间 DateTime _getNextEightPM() { final now = DateTime.now(); var nextTime = DateTime(now.year, now.month, now.day, 20, 0, 0); if (nextTime.isBefore(now)) { nextTime = nextTime.add(const Duration(days: 1)); } return nextTime; } // Android端:用AlarmManager实现后台/终止状态触发 Future<void> setupDailyAlarm() async { await AndroidAlarmManager.initialize(); // 每日重复触发,精确到时间 await AndroidAlarmManager.periodic( const Duration(days: 1), 1001, // 唯一任务ID _triggerNotification, startAt: _getNextEightPM(), exact: true, wakeup: true, allowWhileIdle: true, // 设备休眠时仍触发 ); } // 通知触发逻辑(必须加@pragma注解,确保APP终止时仍能被调用) @pragma('vm:entry-point') static void _triggerNotification() async { const AndroidNotificationDetails androidDetails = AndroidNotificationDetails( 'daily_notification_channel', '每日通知', channelDescription: '每日晚8点推送的定时通知', importance: Importance.max, priority: Priority.high, sound: RawResourceAndroidNotificationSound('notification'), ); await _notificationsPlugin.show( 0, '每日提醒', '现在是晚上8点啦', const NotificationDetails(android: androidDetails), ); } // iOS端:用插件自带的zonedSchedule实现定时 Future<void> setupDailyIOSNotification() async { await _notificationsPlugin.zonedSchedule( 0, '每日提醒', '现在是晚上8点啦', _getNextEightPM(), const NotificationDetails( iOS: DarwinNotificationDetails(sound: 'notification.wav'), ), androidAllowWhileIdle: true, uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime, matchDateTimeComponents: DateTimeComponents.time, // 按时间每日重复 ); }
方案二:使用Firebase Cloud Messaging(FCM)计划推送
该方案依赖网络,无需处理本地定时逻辑,跨平台兼容性更好,APP终止时仍能通过系统推送通道触发通知。
1. 集成FCM
在pubspec.yaml中添加依赖:
dependencies: firebase_core: ^2.15.0 firebase_messaging: ^14.6.5 flutter_local_notifications: ^16.1.0
完成Firebase项目配置(Android和iOS的密钥、证书等)。
2. 后台消息处理
import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; // 后台消息处理回调(APP终止时仍会触发) @pragma('vm:entry-point') Future<void> _firebaseBackgroundHandler(RemoteMessage message) async { await Firebase.initializeApp(); // 显示本地通知 const AndroidNotificationDetails androidDetails = AndroidNotificationDetails( 'fcm_daily_channel', 'FCM每日通知', channelDescription: '通过FCM推送的每日定时通知', importance: Importance.max, priority: Priority.high, ); await _notificationsPlugin.show( message.messageId.hashCode, message.notification?.title ?? '每日提醒', message.notification?.body ?? '现在是晚上8点啦', const NotificationDetails(android: androidDetails), ); } // 初始化FCM Future<void> initFCM() async { await Firebase.initializeApp(); // 请求通知权限 await FirebaseMessaging.instance.requestPermission( alert: true, badge: true, sound: true, ); // 注册后台消息处理器 FirebaseMessaging.onBackgroundMessage(_firebaseBackgroundHandler); }
3. 设置计划推送
在Firebase控制台创建计划消息:
- 进入云消息传递 -> 发送消息
- 填写通知标题、内容,选择计划 -> 定期发送
- 设置触发时间为每日晚8点(注意时区配置)
- 选择目标设备或主题,完成发送
关键注意事项
- Android:必须手动开启应用的「自启动权限」,否则APP被终止后AlarmManager无法触发;需确保
SCHEDULE_EXACT_ALARM权限已获取。 - iOS:本地定时通知在APP被彻底杀死后可能被系统延迟或忽略,这是iOS的系统限制;FCM推送需确保设备联网且APNs配置正确。
- 两种方案都需请求用户的通知权限,否则通知无法显示。
内容的提问来源于stack exchange,提问作者Janki
相关产品推荐
相关产品推荐

