Schedule Notification

Actions & Logic

Hello Everyone!

Im currently working on our capstone project and I'm having a hard time creating scheduled notification using flutter_local_notification. Do anyone suggest any other package I can use for the scheduled notification on our capstone project?

What have you tried so far?

I've tried flutter_local_notifications but it isn't working

btw, this is my code

import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:flutter/material.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:intl/intl.dart'; import 'package:mechanicwho/methods/capitalize_first_letters/capitalize_first_letters.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:rxdart/rxdart.dart'; import 'package:timezone/timezone.dart' as tz; import 'package:timezone/data/latest.dart' as tz; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:mechanicwho/class/app_notification.dart'; final notificationsProvider = StateNotifierProvider.family< AppNotificationsNotifier, List<AppNotification>, String>( (ref, username) => AppNotificationsNotifier(username), ); class AppNotificationsNotifier extends StateNotifier<List<AppNotification>> { final String username; AppNotificationsNotifier(this.username) : super([]) { fetchNotifications(); } Future<void> fetchNotifications() async { try { FirebaseFirestore.instance .collection('notifications') .where('username', isEqualTo: username) .snapshots() .listen((snapshot) { final notifications = snapshot.docs.map((doc) { return AppNotification( id: doc['id'], username: doc['username'], type: doc['type'], notificationTime: (doc['notificationTime'] as Timestamp).toDate(), scheduledTime: (doc['scheduledTime'] as Timestamp).toDate(), status: doc['status'], location: doc['location'], isRead: doc['isRead'], onPressed: (context) { _getOnPressed(doc['type'])(context); }, ); }).toList(); // Sort notifications by time notifications .sort((a, b) => b.notificationTime.compareTo(a.notificationTime)); state = notifications; // Schedule reminders for today's notifications for (var notif in notifications) { if (notif.type == 'schedule' && _isToday(notif.scheduledTime!)) { _scheduleDailyReminder(notif); } } }); } catch (e) { throw Exception('Failed to fetch notifications: $e'); } } bool _isToday(DateTime date) { final now = DateTime.now(); return now.year == date.year && now.month == date.month && now.day == date.day; } void _scheduleDailyReminder(AppNotification notif) async { try { final now = tz.TZDateTime.now(tz.local); final scheduledTime = tz.TZDateTime.from(notif.scheduledTime!, tz.local); // format the appointment time String formattedTime = DateFormat('hh:mm a').format(notif.scheduledTime!); print('Now: $now'); print('Scheduled Time: $scheduledTime'); // schedule notification at 7 AM on the day of the appointment final tz.TZDateTime sevenAm = tz.TZDateTime(tz.local, scheduledTime.year, scheduledTime.month, scheduledTime.day, 7, 0); print('7 AM Time: $sevenAm'); // Convert tz.TZDateTime to DateTime for scheduling if (sevenAm.isAfter(now)) { await LocalNotifications.showScheduleNotification( id: int.tryParse('${notif.id}07') ?? 0, // Unique ID for 7 AM notification title: 'Reminder: Today\'s Appointment', body: 'You have an appointment today at ${capitalizeFirstLetter(notif.location ?? "")} at $formattedTime.', scheduledDate: sevenAm.toLocal(), // Convert to DateTime if necessary ); print('Notification scheduled for 7 AM at: $sevenAm'); } else { print('7 AM notification is in the past.'); } // Schedule notification 1 hour before the appointment final tz.TZDateTime oneHourBefore = scheduledTime.subtract(Duration(hours: 1)); print('1 Hour Before Time: $oneHourBefore'); // Convert tz.TZDateTime to DateTime for scheduling if (oneHourBefore.isAfter(now)) { await LocalNotifications.showScheduleNotification( id: int.tryParse('${notif.id}01') ?? 0, // Unique ID for 1 hour before notification title: 'Reminder: Appointment in 1 Hour', body: 'You have an appointment at ${capitalizeFirstLetter(notif.location ?? "")} at $formattedTime.', scheduledDate: oneHourBefore.toLocal(), // Convert to DateTime if necessary ); print('Notification scheduled 1 hour before at: $oneHourBefore'); } else { print('1 hour before notification is in the past.'); } } catch (e) { print('Error scheduling reminder: $e'); } } void Function(BuildContext) _getOnPressed(String type) { switch (type) { case 'complaint': return _complaintOnPressed; default: return _scheduleOnPressed; } } static void _complaintOnPressed(BuildContext context) { Navigator.pushNamed(context, '/notification_complaint_report'); } static void _scheduleOnPressed(BuildContext context) { Navigator.pushNamed(context, '/driver_appointment_details'); } Future<void> markAsRead(AppNotification notification) async { try { final getNotif = await FirebaseFirestore.instance .collection('notifications') .where('username', isEqualTo: notification.username) .where('notificationTime', isEqualTo: notification.notificationTime) .get(); for (var doc in getNotif.docs) { await doc.reference.update({'isRead': true}); } // Update the state to reflect the change state = state.map((notif) { if (notif.notificationTime == notification.notificationTime) { return notification.copyWith(isRead: true); } return notif; }).toList(); } catch (e) { throw Exception('Failed to mark notification as read: $e'); } } } class LocalNotifications { static final FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); // Initialize the local notification static Future<void> init() async { tz.initializeTimeZones(); tz.setLocalLocation(tz.getLocation('Asia/Manila')); const AndroidInitializationSettings initializationSettingsAndroid = AndroidInitializationSettings('@mipmap/ic_launcher'); final InitializationSettings initializationSettings = InitializationSettings(android: initializationSettingsAndroid); await _flutterLocalNotificationsPlugin.initialize( initializationSettings, onDidReceiveNotificationResponse: onNotificationTap, onDidReceiveBackgroundNotificationResponse: onNotificationTap, ); } // Request notification permission static Future<void> requestNotificationPermission() async { print("requestNotificationPermission method called"); bool isGranted = await Permission.notification.isGranted; print("Permission status before request: $isGranted"); if (isGranted) { print("Notification permission already granted."); } else { PermissionStatus status = await Permission.notification.request(); print("Permission status after request: ${status.isGranted}"); if (status.isGranted) { print("Notification permission granted."); } else { print("Notification permission denied."); } } } // Schedule the notification static Future<void> showScheduleNotification({ required int id, required String title, required String body, required DateTime scheduledDate, String? payload, }) async { const NotificationDetails notificationDetails = NotificationDetails( android: AndroidNotificationDetails( 'appointment_reminder', 'Reminders', importance: Importance.high, priority: Priority.high, ), ); await _flutterLocalNotificationsPlugin.zonedSchedule( id, title, body, tz.TZDateTime.from(scheduledDate, tz.local), notificationDetails, androidAllowWhileIdle: true, uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime, matchDateTimeComponents: DateTimeComponents.time, payload: payload, ); } static void onNotificationTap(NotificationResponse notificationResponse) { onClickNotification.add(notificationResponse.payload!); } static final onClickNotification = BehaviorSubject<String>(); static Future<void> showImmediateNotification({ required int id, required String title, required String body, String? payload, }) async { const NotificationDetails notificationDetails = NotificationDetails( android: AndroidNotificationDetails( 'appointment_reminder', 'Reminders', importance: Importance.high, priority: Priority.high, ), ); await _flutterLocalNotificationsPlugin.show( id, title, body, notificationDetails, payload: payload, ); } }

Did you check FlutterFlow's Documentation for this topic?
No
1