import 'dart:async'; import 'dart:io'; import 'package:get/get.dart'; import 'package:permission_handler/permission_handler.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; import '../../main.dart'; class NotificationController extends GetxController { final FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); @override void onInit() { super.onInit(); initNotifications(); } // Initializes the local notifications plugin Future initNotifications() async { const AndroidInitializationSettings android = AndroidInitializationSettings('@mipmap/launcher_icon'); DarwinInitializationSettings ios = DarwinInitializationSettings( requestAlertPermission: true, requestBadgePermission: true, requestSoundPermission: true, // onDidReceiveLocalNotification: // (int id, String? title, String? body, String? payload) async {}, ); InitializationSettings initializationSettings = InitializationSettings(android: android, iOS: ios); await _flutterLocalNotificationsPlugin.initialize(initializationSettings); tz.initializeTimeZones(); print('Notifications initialized'); } // Displays a notification with the given title and message void showNotification(String title, String message, String tone) async { final AndroidNotificationDetails android = AndroidNotificationDetails( 'high_importance_channel', 'High Importance Notifications', importance: Importance.max, priority: Priority.high, showWhen: false, sound: RawResourceAndroidNotificationSound(tone), ); const DarwinNotificationDetails ios = DarwinNotificationDetails( sound: 'default', presentAlert: true, presentBadge: true, presentSound: true, ); final NotificationDetails details = NotificationDetails(android: android, iOS: ios); await _flutterLocalNotificationsPlugin.show(0, title, message, details); print('Notification shown: $title - $message'); } // /Users/hamzaaleghwairyeen/development/App/ride 2/lib/controller/firebase/local_notification.dart // Assume _flutterLocalNotificationsPlugin is initialized somewhere in your code // void scheduleNotificationsForSevenDays( // String title, String message, String tone) async { // final AndroidNotificationDetails android = AndroidNotificationDetails( // 'high_importance_channel', // 'High Importance Notifications', // importance: Importance.max, // priority: Priority.high, // sound: RawResourceAndroidNotificationSound(tone), // ); // const DarwinNotificationDetails ios = DarwinNotificationDetails( // sound: 'default', // presentAlert: true, // presentBadge: true, // presentSound: true, // ); // final NotificationDetails details = // NotificationDetails(android: android, iOS: ios); // // Check for the exact alarm permission on Android 12 and above // if (Platform.isAndroid) { // if (await Permission.scheduleExactAlarm.isDenied) { // if (await Permission.scheduleExactAlarm.request().isGranted) { // print('SCHEDULE_EXACT_ALARM permission granted'); // } else { // print('SCHEDULE_EXACT_ALARM permission denied'); // return; // } // } // } // // Schedule notifications for the next 7 days // for (int day = 0; day < 7; day++) { // // Schedule for 8:00 AM // await _scheduleNotificationForTime( // day, 8, 0, title, message, details, day * 1000 + 1); // // Schedule for 3:00 PM // await _scheduleNotificationForTime( // day, 15, 0, title, message, details, day * 1000 + 2); // Unique ID // // Schedule for 8:00 PM // await _scheduleNotificationForTime( // day, 20, 0, title, message, details, day * 1000 + 3); // Unique ID // } // print('Notifications scheduled successfully for the next 7 days'); // } void scheduleNotificationsForSevenDays( String title, String message, String tone) async { final AndroidNotificationDetails android = AndroidNotificationDetails( 'high_importance_channel', 'High Importance Notifications', importance: Importance.max, priority: Priority.high, sound: RawResourceAndroidNotificationSound(tone), ); const DarwinNotificationDetails ios = DarwinNotificationDetails( sound: 'default', presentAlert: true, presentBadge: true, presentSound: true, ); final NotificationDetails details = NotificationDetails(android: android, iOS: ios); // Check for the exact alarm permission on Android 12 and above if (Platform.isAndroid) { if (await Permission.scheduleExactAlarm.isDenied) { if (await Permission.scheduleExactAlarm.request().isGranted) { print('SCHEDULE_EXACT_ALARM permission granted'); } else { print('SCHEDULE_EXACT_ALARM permission denied'); return; } } } // Schedule notifications for the next 7 days for (int day = 0; day < 7; day++) { // List of notification times final notificationTimes = [ {'hour': 8, 'minute': 0, 'id': day * 1000 + 1}, // 8:00 AM {'hour': 15, 'minute': 0, 'id': day * 1000 + 2}, // 3:00 PM {'hour': 20, 'minute': 0, 'id': day * 1000 + 3}, // 8:00 PM ]; for (var time in notificationTimes) { final notificationId = time['id'] as int; // Check if this notification ID is already stored bool isScheduled = box.read('notification_$notificationId') ?? false; if (!isScheduled) { // Schedule the notification if not already scheduled await _scheduleNotificationForTime( day, time['hour'] as int, time['minute'] as int, title, message, details, notificationId, ); // Mark this notification ID as scheduled in GetStorage box.write('notification_$notificationId', true); } else { print('Notification with ID $notificationId is already scheduled.'); } } } print('Notifications scheduled successfully for the next 7 days'); } void scheduleNotificationsForTimeSelected( String title, String message, String tone, DateTime timeSelected) async { final AndroidNotificationDetails android = AndroidNotificationDetails( 'high_importance_channel', 'High Importance Notifications', importance: Importance.max, priority: Priority.high, sound: RawResourceAndroidNotificationSound(tone), ); const DarwinNotificationDetails ios = DarwinNotificationDetails( sound: 'default', presentAlert: true, presentBadge: true, presentSound: true, ); final NotificationDetails details = NotificationDetails(android: android, iOS: ios); // Check for the exact alarm permission on Android 12 and above if (Platform.isAndroid) { if (await Permission.scheduleExactAlarm.isDenied) { if (await Permission.scheduleExactAlarm.request().isGranted) { print('SCHEDULE_EXACT_ALARM permission granted'); } else { print('SCHEDULE_EXACT_ALARM permission denied'); return; } } } // Schedule notifications for 10 and 30 minutes before the timeSelected await _scheduleNotificationForTimeVIP( timeSelected.subtract(const Duration(minutes: 10)), // 10 minutes before title, message, details, 1, // Unique ID for 10-minute before notification ); await _scheduleNotificationForTimeVIP( timeSelected.subtract(const Duration(minutes: 30)), // 30 minutes before title, message, details, 2, // Unique ID for 30-minute before notification ); print('Notifications scheduled successfully for the time selected'); } Future _scheduleNotificationForTimeVIP( DateTime scheduledDate, String title, String message, NotificationDetails details, int notificationId, ) async { // Initialize and set Cairo timezone tz.initializeTimeZones(); var cairoLocation = tz.getLocation('Africa/Cairo'); final now = tz.TZDateTime.now(cairoLocation); // Convert to Cairo time tz.TZDateTime scheduledTZDateTime = tz.TZDateTime.from(scheduledDate, cairoLocation); // Check if 10 minutes before the scheduled time is in the past if (scheduledTZDateTime .subtract(const Duration(minutes: 10)) .isBefore(now)) { // If the 10 minutes before the scheduled time is in the past, don't schedule print( 'Scheduled time minus 10 minutes is in the past. Skipping notification.'); return; // Skip this notification } print('Current time (Cairo): $now'); print('Scheduling notification for: $scheduledTZDateTime'); await _flutterLocalNotificationsPlugin.zonedSchedule( notificationId, // Unique ID for each notification title, message, scheduledTZDateTime, details, androidScheduleMode: AndroidScheduleMode.exact, // uiLocalNotificationDateInterpretation: // UILocalNotificationDateInterpretation.absoluteTime, matchDateTimeComponents: null, // Don't repeat automatically; we handle manually ); print('Notification scheduled successfully for: $scheduledTZDateTime'); } Future _scheduleNotificationForTime( int dayOffset, int hour, int minute, String title, String message, NotificationDetails details, int notificationId, ) async { // Initialize and set Cairo timezone tz.initializeTimeZones(); var cairoLocation = tz.getLocation('Africa/Cairo'); final now = tz.TZDateTime.now(cairoLocation); tz.TZDateTime scheduledDate = tz.TZDateTime( cairoLocation, now.year, now.month, now.day + dayOffset, // Add offset to schedule for the next days hour, minute, ); // If the scheduled time is in the past, move it to the next day if (scheduledDate.isBefore(now)) { scheduledDate = scheduledDate.add(const Duration(days: 1)); } print('Current time (Cairo): $now'); print('Scheduling notification for: $scheduledDate'); await _flutterLocalNotificationsPlugin.zonedSchedule( notificationId, // Unique ID for each notification title, message, scheduledDate, details, androidScheduleMode: AndroidScheduleMode.exact, // uiLocalNotificationDateInterpretation: // UILocalNotificationDateInterpretation.absoluteTime, matchDateTimeComponents: null, // Don't repeat automatically; we handle 7 days manually ); print('Notification scheduled successfully for: $scheduledDate'); } }