Flutter每日定时通知:如何实现每日推送不同内容
问题:每日固定时间推送不同内容的通知
当前代码设置的每日重复通知只会发送首次选择的内容,需要修改实现每日内容不同的定时推送。
原代码
import 'dart:math'; import 'package:flutter/material.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:timezone/data/latest.dart' as tz; import 'package:timezone/timezone.dart' as tz; void main() async { WidgetsFlutterBinding.ensureInitialized(); tz.initializeTimeZones(); tz.setLocalLocation(tz.getLocation("Europe/Istanbul")); runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( home: MyHomePage(), ); } } class MyHomePage extends StatelessWidget { final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); MyHomePage({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Bildirim Uygulaması'), ), body: Center( child: Column( children: [ ElevatedButton( onPressed: () async { await _scheduleDailyNotification(); }, child: const Text('Günlük Bildirim Gönder'), ), ElevatedButton( onPressed: () async { await unScheduleAllNotifications(); }, child: const Text('iptal'), ), ], ), ), ); } // Tüm zamanlanmış fonksiyonları iptal etme. Future unScheduleAllNotifications() async => await flutterLocalNotificationsPlugin.cancelAll(); Future<void> _scheduleDailyNotification() async { var androidDetails = const AndroidNotificationDetails( 'channelId', 'channelName', importance: Importance.high, ); var generalNotificationDetails = NotificationDetails(android: androidDetails); // Saat 10:00 için bir DateTime nesnesi oluştur tz.TZDateTime scheduledDate = tz.TZDateTime( tz.local, DateTime.now().year, DateTime.now().month, DateTime.now().day, 20, 38, 1, ); String selectedMessage = "ilk deger"; int id = 1; // Eğer bu saat geçtiyse, bir sonraki gün için planla if (scheduledDate.isBefore(tz.TZDateTime.now(tz.local))) { print("bu kisim bakalim hep calisiyor mu olursa sorun aha burada lutfen ol"); scheduledDate = scheduledDate.add(const Duration(days: 1)); // Günlük bildirim içeriği listesi List<String> dailyMessages = [ 'Bugün harika bir gün!', 'Yeni bir şeyler öğrenmeye hazır mısınız?', 'Hayalinizdeki projeye başlama zamanı!', 'Güzel anları değerlendirin!', 'Bugün bir gülümsemeyle başlayın!', ]; // Rastgele bir mesaj seç Random random = Random(); final a = random.nextInt(dailyMessages.length); selectedMessage = dailyMessages[random.nextInt(dailyMessages.length)]; id = a; } await flutterLocalNotificationsPlugin.zonedSchedule( id, 'Günlük Hatırlatma', selectedMessage, scheduledDate, generalNotificationDetails, androidScheduleMode: AndroidScheduleMode.alarmClock, uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime, matchDateTimeComponents: DateTimeComponents.time, ); } }
问题原因
你使用了matchDateTimeComponents: DateTimeComponents.time来设置每日重复通知,但该参数会让系统以首次调度时的固定内容重复发送,无法动态更新通知内容。
解决方案
改为单次调度次日通知,并在通知触发后、应用启动时重新调度下一次通知,确保每次调度都生成新的随机内容。
修改后的代码
import 'dart:math'; import 'package:flutter/material.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:timezone/data/latest.dart' as tz; import 'package:timezone/timezone.dart' as tz; void main() async { WidgetsFlutterBinding.ensureInitialized(); tz.initializeTimeZones(); tz.setLocalLocation(tz.getLocation("Europe/Istanbul")); runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( home: MyHomePage(), ); } } class MyHomePage extends StatefulWidget { const MyHomePage({super.key}); @override State<MyHomePage> createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { final FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); final List<String> _dailyMessages = [ 'Bugün harika bir gün!', 'Yeni bir şeyler öğrenmeye hazır mısınız?', 'Hayalinizdeki projeye başlama zamanı!', 'Güzel anları değerlendirin!', 'Bugün bir gülümsemeyle başlayın!', ]; @override void initState() { super.initState(); _initializeNotifications(); // 应用启动时检查是否已调度通知,没有则立即调度 _checkAndScheduleNotification(); } // 初始化通知插件并设置回调 Future<void> _initializeNotifications() async { const AndroidInitializationSettings initializationSettingsAndroid = AndroidInitializationSettings('@mipmap/ic_launcher'); const InitializationSettings initializationSettings = InitializationSettings(android: initializationSettingsAndroid); await _flutterLocalNotificationsPlugin.initialize( initializationSettings, onDidReceiveNotificationResponse: (response) { // 用户点击通知后,重新调度次日通知 _scheduleNextDailyNotification(); }, ); // 监听通知触发事件(即使应用在后台) _flutterLocalNotificationsPlugin.getNotificationAppLaunchDetails().then((details) { if (details?.didNotificationLaunchApp ?? false) { _scheduleNextDailyNotification(); } }); } // 检查是否已有待触发的通知,没有则调度 Future<void> _checkAndScheduleNotification() async { List<PendingNotificationRequest> pendingRequests = await _flutterLocalNotificationsPlugin.pendingNotificationRequests(); if (pendingRequests.isEmpty) { await _scheduleNextDailyNotification(); } } // 取消所有已调度的通知 Future<void> _cancelAllNotifications() async => await _flutterLocalNotificationsPlugin.cancelAll(); // 调度下一次的每日通知 Future<void> _scheduleNextDailyNotification() async { const AndroidNotificationDetails androidDetails = AndroidNotificationDetails( 'daily_notification_channel', '每日通知', importance: Importance.high, priority: Priority.high, ); const NotificationDetails notificationDetails = NotificationDetails(android: androidDetails); // 计算目标时间(每天20:38:01) tz.TZDateTime scheduledDate = tz.TZDateTime( tz.local, DateTime.now().year, DateTime.now().month, DateTime.now().day, 20, 38, 1, ); // 如果当前时间已过目标时间,调度到次日 if (scheduledDate.isBefore(tz.TZDateTime.now(tz.local))) { scheduledDate = scheduledDate.add(const Duration(days: 1)); } // 随机选择通知内容 final random = Random(); final selectedMessage = _dailyMessages[random.nextInt(_dailyMessages.length)]; final notificationId = random.nextInt(1000); // 使用随机ID避免冲突 await _flutterLocalNotificationsPlugin.zonedSchedule( notificationId, 'Günlük Hatırlatma', selectedMessage, scheduledDate, notificationDetails, androidScheduleMode: AndroidScheduleMode.alarmClock, uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime, // 移除重复调度参数,只调度单次通知 ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Bildirim Uygulaması'), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ ElevatedButton( onPressed: _scheduleNextDailyNotification, child: const Text('Günlük Bildirim Gönder'), ), const SizedBox(height: 16), ElevatedButton( onPressed: _cancelAllNotifications, child: const Text('İptal'), ), ], ), ), ); } }
关键改动说明
- 改为StatefulWidget:方便在
initState中初始化通知并设置回调,监听通知交互。 - 移除重复调度参数:删除
matchDateTimeComponents: DateTimeComponents.time,只调度单次通知。 - 动态生成内容:每次调度时都随机选择新的通知内容,确保每日内容不同。
- 通知回调处理:在用户点击通知或应用因通知启动时,自动调度次日的通知,形成循环。
- 启动时检查调度状态:应用启动时如果没有待触发的通知,立即调度下一次,避免遗漏。
内容的提问来源于stack exchange,提问作者suleyman gunes
相关产品推荐
相关产品推荐

