Flutter中如何实现每日自动定时推送礼拜时间通知?
问题:实现每日自动礼拜时间通知
我使用adhan Dart包获取礼拜时间,通过flutter_local_notifications的zonedSchedule()方法设置通知,但目前用户点击设置按钮后仅当天能收到通知。希望实现用户点击设置后,每天自动收到对应礼拜时间的通知。
以下是当前代码:
通知服务类
import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:intl/intl.dart'; import 'package:islamic/getprayertime.dart'; import 'package:timezone/timezone.dart' as tz; class NotificationService { final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); static final NotificationService _notificationService = NotificationService._internal(); factory NotificationService() { return _notificationService; } NotificationService._internal(); Future<void> initializenotification() async { AndroidInitializationSettings androidInitializationSettings = const AndroidInitializationSettings('logo'); InitializationSettings initializationSettings = InitializationSettings(android: androidInitializationSettings); await flutterLocalNotificationsPlugin.initialize(initializationSettings); } backgroundtask() { Prayers.getPrayertimes().then((value) { final currenttime = DateTime.now(); if (value.fajr!.toLocal().isAfter(currenttime)) { schedulePrayerTimeNotification(value.fajr!.toLocal(), 'Fajr'); } if (value.dhuhr!.toLocal().isAfter(currenttime)) { schedulePrayerTimeNotification(value.dhuhr!.toLocal(), 'Dhuhr'); } if (value.asr!.toLocal().isAfter(currenttime)) { schedulePrayerTimeNotification(value.asr!.toLocal(), 'Asr'); } if (value.maghrib!.toLocal().isAfter(currenttime)) { schedulePrayerTimeNotification(value.maghrib!.toLocal(), 'Maghrib'); } if (value.isha!.toLocal().isAfter(currenttime)) { schedulePrayerTimeNotification(value.isha!.toLocal(), 'Isha'); } }); } Future<void> schedulePrayerTimeNotification( DateTime prayerTime, String prayerName) async { const AndroidNotificationDetails androidNotificationDetails = AndroidNotificationDetails( 'main_channel', 'Main Channel', channelDescription: "ashwin", importance: Importance.max, priority: Priority.max, ); const NotificationDetails notificationDetails = NotificationDetails(android: androidNotificationDetails); final formattedTime = DateFormat('h:mm a').format(prayerTime); await flutterLocalNotificationsPlugin.zonedSchedule( prayerName.hashCode, 'Prayer Time', 'It\'s time for $prayerName prayer at $formattedTime.', tz.TZDateTime.from(prayerTime, tz.local), notificationDetails, androidAllowWhileIdle: true, uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime, ); } }
主页类
import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:islamic/background_task.dart'; import 'package:islamic/drawer.dart'; class Homepage extends StatefulWidget { const Homepage({super.key}); @override State<Homepage> createState() => _HomepageState(); } class _HomepageState extends State<Homepage> { @override Widget build(BuildContext context) { return SafeArea( child: Scaffold( appBar: AppBar( backgroundColor: Colors.indigo, ), body: Center( child: SizedBox( height: 60, width: 300, child: ElevatedButton( onPressed: () { Get.snackbar( 'Prayer reminder', 'Your prayer reminder has been created', snackPosition: SnackPosition.TOP, icon: Icon(Icons.mosque), ); NotificationService().backgroundtask(); }, style: ElevatedButton.styleFrom(backgroundColor: Colors.indigo), child: Text( 'Set Prayer reminder', style: TextStyle(color: Colors.white), ), ), ), ), ), ); } }
解决方案
要实现每日重复通知,关键是利用flutter_local_notifications提供的重复规则,并调整时间处理逻辑确保次日及以后的通知能正常触发。
1. 修改通知调度方法,添加每日重复规则
在schedulePrayerTimeNotification方法的zonedSchedule调用中,添加repeatInterval: RepeatInterval.daily参数,让通知每天在指定时间重复触发。
2. 调整时间处理逻辑,覆盖当天已过的礼拜时间
原来的逻辑只设置当天未过的礼拜时间通知,现在需要为已过的时间设置次日的通知,并开启重复,确保每天都能收到。
修改后的通知服务类代码
import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:intl/intl.dart'; import 'package:islamic/getprayertime.dart'; import 'package:timezone/timezone.dart' as tz; class NotificationService { final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); static final NotificationService _notificationService = NotificationService._internal(); factory NotificationService() { return _notificationService; } NotificationService._internal(); Future<void> initializenotification() async { AndroidInitializationSettings androidInitializationSettings = const AndroidInitializationSettings('logo'); InitializationSettings initializationSettings = InitializationSettings(android: androidInitializationSettings); await flutterLocalNotificationsPlugin.initialize(initializationSettings); } backgroundtask() { Prayers.getPrayertimes().then((value) { final currentTime = DateTime.now(); // 统一处理每个礼拜时间的通知调度 _handlePrayerTime(value.fajr!.toLocal(), 'Fajr', currentTime); _handlePrayerTime(value.dhuhr!.toLocal(), 'Dhuhr', currentTime); _handlePrayerTime(value.asr!.toLocal(), 'Asr', currentTime); _handlePrayerTime(value.maghrib!.toLocal(), 'Maghrib', currentTime); _handlePrayerTime(value.isha!.toLocal(), 'Isha', currentTime); }); } // 处理单个礼拜时间的通知调度逻辑 void _handlePrayerTime(DateTime prayerTime, String prayerName, DateTime currentTime) { DateTime scheduledTime = prayerTime; // 如果当前时间已过当天礼拜时间,将调度时间设为次日同一时间 if (scheduledTime.isBefore(currentTime)) { scheduledTime = scheduledTime.add(const Duration(days: 1)); } schedulePrayerTimeNotification(scheduledTime, prayerName); } Future<void> schedulePrayerTimeNotification( DateTime prayerTime, String prayerName) async { const AndroidNotificationDetails androidNotificationDetails = AndroidNotificationDetails( 'main_channel', 'Main Channel', channelDescription: "Prayer Reminders", importance: Importance.max, priority: Priority.max, ); const NotificationDetails notificationDetails = NotificationDetails(android: androidNotificationDetails); final formattedTime = DateFormat('h:mm a').format(prayerTime); await flutterLocalNotificationsPlugin.zonedSchedule( prayerName.hashCode, 'Prayer Time', 'It\'s time for $prayerName prayer at $formattedTime.', tz.TZDateTime.from(prayerTime, tz.local), notificationDetails, androidAllowWhileIdle: true, uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime, // 添加每日重复规则 repeatInterval: RepeatInterval.daily, ); } }
关键改动说明
- 添加重复规则:在
zonedSchedule中加入repeatInterval: RepeatInterval.daily,让通知每天自动重复触发。 - 统一时间处理:新增
_handlePrayerTime方法,判断当前时间是否已过当天礼拜时间,若已过则将调度时间改为次日,确保通知从次日开始每天生效。 - 移除原有条件判断:不再仅设置当天未过的时间,而是为所有礼拜时间设置重复通知,覆盖全天场景。
这样用户点击设置按钮后,所有礼拜时间的通知都会被设置为每日重复,无需再次操作即可每天收到提醒。
内容的提问来源于stack exchange,提问作者Abdullah Shahzad
相关产品推荐
相关产品推荐

