import 'package:flisp_app/models/calendar.dart'; import 'package:flisp_app/models/todo.dart'; import 'package:flisp_app/service/calendar_service.dart'; import 'package:flisp_app/service/todo_service.dart'; import 'package:flutter/material.dart'; import 'package:flutter_common/utils/date_utils.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:timezone/data/latest_all.dart' as tz; import 'package:timezone/timezone.dart' as tz; class NotifyService { static final NotifyService _instance = NotifyService._internal(); factory NotifyService() => _instance; NotifyService._internal(); late FlutterLocalNotificationsPlugin _notifications; // 使用绝对时间(而不是相对时间),避免时区转换问题。 final dateInterpretation = UILocalNotificationDateInterpretation.absoluteTime; // Android特殊模式,即使设备处于省电模式也能准时触发。 final scheduleMode = AndroidScheduleMode.exactAllowWhileIdle; // 初始化通知服务 Future initialize() async { _notifications = FlutterLocalNotificationsPlugin(); // 初始化时区 tz.initializeTimeZones(); // String timeZoneName = await FlutterNativeTimezone.getLocalTimezone(); tz.setLocalLocation(tz.getLocation("Asia/Shanghai")); // 设置Android平台的初始化配置 使用应用图标作为通知图标 const AndroidInitializationSettings androidSettings = AndroidInitializationSettings('@mipmap/ic_launcher'); // 设置iOS平台的初始化配置 const DarwinInitializationSettings iosSettings = DarwinInitializationSettings( requestAlertPermission: true, requestBadgePermission: true, requestSoundPermission: true, ); // 初始化设置 const InitializationSettings settings = InitializationSettings( android: androidSettings, iOS: iosSettings, ); await _notifications.initialize(settings); WidgetsBinding.instance.addPostFrameCallback((_) { _refreshScheduled(); }); } /// 重新刷新提醒 防止每次重启设备后提醒丢失的问题 void _refreshScheduled() async { await cancelAllNotifications(); TodoService todoService = TodoService(); final List todoResult = todoService.getAllTodos( TodoSortMode.priority, ); final List todayTodos = todoResult .where( (todo) => !todo.isCompleted && isAfterToday(todo.scheduledTime), ) .toList(); for (Todo todo in todayTodos) { await scheduleNotification( id: todo.id, title: '待办提醒', body: todo.title, scheduledTime: todo.scheduledTime!, ); } CalendarService calendarService = CalendarService(); final List calendarResult = calendarService.getAllCalendars(); final List todayCalendars = calendarResult .where((item) => isAfterToday(item.scheduledTime)) .toList(); for (Calendar calendar in todayCalendars) { await scheduleNotification( id: calendar.id, title: '日程提醒', body: calendar.title, scheduledTime: calendar.scheduledTime!, ); } } // 创建Android通知详情 AndroidNotificationDetails _androidNotificationDetails() { const channelId = 'com.cxx.flisp_app'; const channelName = '闪灵'; const channelDescription = '闪灵通知'; return const AndroidNotificationDetails( channelId, channelName, channelDescription: channelDescription, importance: Importance.high, priority: Priority.high, playSound: true, enableVibration: true, ); } // 创建iOS通知详情 DarwinNotificationDetails _iosNotificationDetails() { return const DarwinNotificationDetails( presentAlert: true, presentBadge: true, presentSound: true, ); } NotificationDetails get _details { return NotificationDetails( android: _androidNotificationDetails(), iOS: _iosNotificationDetails(), ); } // 立即显示通知 Future showInstantNotification({ required String title, required String body, int id = 0, }) async { await _notifications.show(id, title, body, _details); } // 安排定时通知 Future scheduleNotification({ required int id, required String title, required String body, required DateTime scheduledTime, }) async { await _notifications.zonedSchedule( id, title, body, tz.TZDateTime.from(scheduledTime, tz.local), _details, uiLocalNotificationDateInterpretation: dateInterpretation, androidScheduleMode: scheduleMode, ); } // 取消特定通知 Future cancelNotification(int id) async { try { await _notifications.cancel(id); } catch (e) { print('取消通知失败: $e'); } } // 取消所有通知 Future cancelAllNotifications() async { await _notifications.cancelAll(); } // 检查通知权限 Future checkPermission() async { final bool? result = await _notifications .resolvePlatformSpecificImplementation< AndroidFlutterLocalNotificationsPlugin >() ?.areNotificationsEnabled(); return result ?? false; } // 请求权限 Future requestPermission() async { await _notifications .resolvePlatformSpecificImplementation< IOSFlutterLocalNotificationsPlugin >() ?.requestPermissions(alert: true, badge: true, sound: true); } // 获取所有待处理的通知 Future> getPendingNotifications() async { return await _notifications.pendingNotificationRequests(); } }