592 lines
20 KiB
Dart
592 lines
20 KiB
Dart
import 'dart:async';
|
|
import 'dart:convert';
|
|
import 'dart:io';
|
|
import 'dart:typed_data';
|
|
|
|
import 'package:sefer_driver/constant/colors.dart';
|
|
import 'package:sefer_driver/views/home/Captin/orderCaptin/order_request_page.dart';
|
|
import 'package:sefer_driver/views/home/Captin/orderCaptin/order_speed_request.dart';
|
|
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:permission_handler/permission_handler.dart';
|
|
|
|
import 'package:timezone/data/latest.dart' as tz;
|
|
import 'package:timezone/timezone.dart' as tz;
|
|
import '../../constant/box_name.dart';
|
|
import '../../main.dart';
|
|
import '../../print.dart';
|
|
import '../../views/notification/notification_captain.dart';
|
|
import '../home/captin/home_captain_controller.dart';
|
|
|
|
class NotificationController extends GetxController {
|
|
final FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin =
|
|
FlutterLocalNotificationsPlugin();
|
|
|
|
Future<void> 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);
|
|
tz.initializeTimeZones();
|
|
print('Notifications initialized');
|
|
await _flutterLocalNotificationsPlugin.initialize(
|
|
initializationSettings,
|
|
onDidReceiveNotificationResponse: onDidReceiveNotificationResponse,
|
|
onDidReceiveBackgroundNotificationResponse: notificationTapBackground,
|
|
);
|
|
|
|
// Create a notification channel
|
|
const AndroidNotificationChannel channel = AndroidNotificationChannel(
|
|
'high_importance_channel', // Use the same ID as in strings.xml
|
|
'High Importance Notifications',
|
|
description: 'This channel is used for important notifications.',
|
|
importance: Importance.high,
|
|
);
|
|
|
|
// Register the channel with the system
|
|
await _flutterLocalNotificationsPlugin
|
|
.resolvePlatformSpecificImplementation<
|
|
AndroidFlutterLocalNotificationsPlugin>()
|
|
?.createNotificationChannel(channel);
|
|
}
|
|
|
|
// Displays a notification with the given title and message
|
|
void showNotification(
|
|
String title, String message, String tone, String payLoad) async {
|
|
BigTextStyleInformation bigTextStyleInformation = BigTextStyleInformation(
|
|
message,
|
|
contentTitle: title.tr,
|
|
htmlFormatContent: true,
|
|
htmlFormatContentTitle: true,
|
|
);
|
|
AndroidNotificationDetails android = AndroidNotificationDetails(
|
|
'high_importance_channel',
|
|
'High Importance Notifications',
|
|
importance: Importance.max,
|
|
priority: Priority.high,
|
|
sound: RawResourceAndroidNotificationSound(tone),
|
|
);
|
|
|
|
// AndroidNotificationDetails android = AndroidNotificationDetails(
|
|
// 'high_importance_channel', // Use the same ID as before
|
|
// 'High Importance Notifications',
|
|
// importance: Importance.high,
|
|
// priority: Priority.high,
|
|
// styleInformation: bigTextStyleInformation,
|
|
// playSound: true,
|
|
// sound: RawResourceAndroidNotificationSound(tone),
|
|
// // audioAttributesUsage: AudioAttributesUsage.alarm,
|
|
// visibility: NotificationVisibility.public,
|
|
// autoCancel: false,
|
|
// color: AppColor.primaryColor,
|
|
// showProgress: true,
|
|
// showWhen: true,
|
|
// ongoing: true,
|
|
// enableVibration: true,
|
|
// vibrationPattern: Int64List.fromList([0, 1000, 500, 1000]),
|
|
// timeoutAfter: 14500,
|
|
// setAsGroupSummary: true,
|
|
// subText: message, fullScreenIntent: true,
|
|
// actions: [
|
|
// AndroidNotificationAction(
|
|
// allowGeneratedReplies: true,
|
|
// 'id',
|
|
// title.tr,
|
|
// titleColor: AppColor.blueColor,
|
|
// showsUserInterface: true,
|
|
// )
|
|
// ],
|
|
// category: AndroidNotificationCategory.message,
|
|
// );
|
|
|
|
DarwinNotificationDetails ios = const DarwinNotificationDetails(
|
|
sound: 'default',
|
|
presentAlert: true,
|
|
presentBadge: true,
|
|
presentSound: true,
|
|
);
|
|
NotificationDetails details =
|
|
NotificationDetails(android: android, iOS: ios);
|
|
|
|
await _flutterLocalNotificationsPlugin.show(0, title, message, details,
|
|
payload: jsonEncode({'title': title, 'data': payLoad}));
|
|
}
|
|
|
|
void scheduleNotificationAtSpecificTime(
|
|
String title, String message, String tone, int hour, int minute) async {
|
|
// Initialize and set Cairo time zone
|
|
tz.initializeTimeZones();
|
|
var cairoLocation;
|
|
if (box.read(BoxName.countryCode).toString() == 'Egypt') {
|
|
cairoLocation = tz.getLocation('Africa/Cairo');
|
|
} else {} // todo get for location country
|
|
|
|
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);
|
|
|
|
final now =
|
|
tz.TZDateTime.now(cairoLocation); // Use Cairo timezone for current time
|
|
tz.TZDateTime scheduledTime = tz.TZDateTime(
|
|
cairoLocation, now.year, now.month, now.day, hour, minute);
|
|
|
|
// If the scheduled time has already passed for today, schedule it for the next day
|
|
if (scheduledTime.isBefore(now)) {
|
|
scheduledTime = scheduledTime.add(const Duration(days: 1));
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
print('Current time: $now');
|
|
print('Scheduling notification for: $scheduledTime');
|
|
await _flutterLocalNotificationsPlugin.zonedSchedule(
|
|
0,
|
|
title,
|
|
message,
|
|
scheduledTime,
|
|
details,
|
|
// androidAllowWhileIdle: true,
|
|
uiLocalNotificationDateInterpretation:
|
|
UILocalNotificationDateInterpretation.absoluteTime,
|
|
matchDateTimeComponents: DateTimeComponents.time,
|
|
androidScheduleMode:
|
|
AndroidScheduleMode.alarmClock, // Triggers daily at the same time
|
|
);
|
|
print('Notification scheduled successfully');
|
|
}
|
|
|
|
void scheduleNotificationAfter1Minute(
|
|
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);
|
|
|
|
// Schedule the notification to be shown after 1 minute
|
|
Timer.periodic(const Duration(seconds: 15), (timer) async {
|
|
final now = tz.TZDateTime.now(tz.local);
|
|
final scheduledTime = now.add(const Duration(seconds: 10));
|
|
Log.print('scheduledTime: ${scheduledTime}');
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
print('Scheduling notification for: $scheduledTime');
|
|
await _flutterLocalNotificationsPlugin.zonedSchedule(
|
|
0,
|
|
title,
|
|
message,
|
|
scheduledTime,
|
|
details,
|
|
uiLocalNotificationDateInterpretation:
|
|
UILocalNotificationDateInterpretation.absoluteTime,
|
|
matchDateTimeComponents: DateTimeComponents.time,
|
|
androidScheduleMode: AndroidScheduleMode.alarmClock,
|
|
);
|
|
print('Notification scheduled successfully');
|
|
});
|
|
}
|
|
|
|
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');
|
|
}
|
|
|
|
Future<void> _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(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');
|
|
}
|
|
|
|
void scheduleNotificationEvery10Hours(
|
|
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);
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
Timer.periodic(const Duration(hours: 10), (timer) async {
|
|
final now = tz.TZDateTime.now(tz.local);
|
|
final scheduledTime = now.add(const Duration(minutes: 10));
|
|
|
|
print('Scheduling notification for: $scheduledTime');
|
|
await _flutterLocalNotificationsPlugin.zonedSchedule(
|
|
0,
|
|
title.tr,
|
|
message.tr,
|
|
scheduledTime,
|
|
details,
|
|
// androidAllowWhileIdle: true,
|
|
uiLocalNotificationDateInterpretation:
|
|
UILocalNotificationDateInterpretation.absoluteTime,
|
|
matchDateTimeComponents: DateTimeComponents.time,
|
|
androidScheduleMode: AndroidScheduleMode.alarmClock,
|
|
);
|
|
});
|
|
|
|
print('Notifications scheduled every 5 seconds');
|
|
}
|
|
|
|
void showTimerNotification(String title, String message, String tone) async {
|
|
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
|
|
FlutterLocalNotificationsPlugin();
|
|
|
|
// Setup Android notification
|
|
final AndroidNotificationDetails android = AndroidNotificationDetails(
|
|
'high_importance_channel',
|
|
'High Importance Notifications',
|
|
importance: Importance.max,
|
|
priority: Priority.high,
|
|
showWhen: false,
|
|
sound: RawResourceAndroidNotificationSound(
|
|
tone), // tone without the file extension
|
|
);
|
|
|
|
// Setup iOS notification
|
|
const DarwinNotificationDetails ios = DarwinNotificationDetails(
|
|
sound: 'default',
|
|
presentAlert: true,
|
|
presentBadge: true,
|
|
presentSound: true,
|
|
);
|
|
|
|
final NotificationDetails details =
|
|
NotificationDetails(android: android, iOS: ios);
|
|
|
|
// Request permission on Android
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Timer duration (e.g., 120 seconds countdown)
|
|
int countdown = 12;
|
|
|
|
// Display the notification initially with the full countdown time
|
|
|
|
// Timer to update the notification every second
|
|
Timer.periodic(const Duration(seconds: 1), (timer) async {
|
|
// if (countdown > 0) {
|
|
// Update the existing notification with the updated countdown
|
|
|
|
// Decrease the countdown by 1
|
|
countdown--;
|
|
// } else {
|
|
// // Cancel the timer when the countdown reaches zero
|
|
// timer.cancel();
|
|
// }
|
|
});
|
|
await flutterLocalNotificationsPlugin.show(
|
|
0,
|
|
title,
|
|
'$message Remaining: $countdown seconds', // Initial message
|
|
details,
|
|
);
|
|
print('Notification will update every second');
|
|
}
|
|
|
|
// Callback when the notification is tapped
|
|
void onDidReceiveNotificationResponse(NotificationResponse response) {
|
|
handleNotificationResponse(response);
|
|
}
|
|
|
|
// Callback when the notification is tapped while the app is in the background
|
|
void onDidReceiveBackgroundNotificationResponse(
|
|
NotificationResponse response) {
|
|
handleNotificationResponse(response);
|
|
}
|
|
|
|
// Handle notification response for both foreground and background
|
|
void handleNotificationResponse(NotificationResponse response) {
|
|
print('Notification tapped!');
|
|
Log.print('response.payload: ${response.payload}');
|
|
if (response.payload != null) {
|
|
print('Notification payload: ${response.payload}');
|
|
var payloadData = jsonDecode(response.payload.toString());
|
|
|
|
if (payloadData is Map<String, dynamic>) {
|
|
String title = payloadData['title'];
|
|
var data = payloadData['data'];
|
|
|
|
switch (title) {
|
|
case 'Order':
|
|
_handleOrderNotification(data);
|
|
break;
|
|
case 'OrderSpeed':
|
|
_handleOrderSpeedNotification(data);
|
|
break;
|
|
case 'ADS':
|
|
_handleADSNotification();
|
|
break;
|
|
default:
|
|
Log.print('Unknown notification type');
|
|
}
|
|
} else {
|
|
Log.print('Invalid payload format');
|
|
}
|
|
} else {
|
|
Log.print('Payload is null');
|
|
}
|
|
}
|
|
|
|
void _handleOrderNotification(dynamic data) {
|
|
if (data is String) {
|
|
var orderData = jsonDecode(data);
|
|
if (orderData is List && orderData.length == 34) {
|
|
closeOverLay();
|
|
Get.put(HomeCaptainController()).changeRideId();
|
|
Get.to(() => OrderRequestPage(), arguments: {'myListString': data});
|
|
} else {
|
|
Log.print('Invalid order data');
|
|
}
|
|
} else {
|
|
Log.print('Invalid order payload');
|
|
}
|
|
}
|
|
|
|
void _handleOrderSpeedNotification(dynamic data) {
|
|
if (data is String) {
|
|
var orderData = jsonDecode(data);
|
|
if (orderData is List && orderData.length == 34) {
|
|
closeOverLay();
|
|
Get.put(HomeCaptainController()).changeRideId();
|
|
Get.to(() => OrderRequestPage(), arguments: {'myListString': data});
|
|
} else {
|
|
Log.print('Invalid order data');
|
|
}
|
|
} else {
|
|
Log.print('Invalid order payload');
|
|
}
|
|
}
|
|
|
|
void _handleADSNotification() {
|
|
// var orderData = jsonDecode(data);
|
|
closeOverLay();
|
|
Get.to(
|
|
() => const NotificationCaptain(),
|
|
);
|
|
}
|
|
|
|
void onDidReceiveLocalNotification(
|
|
int id, String? title, String? body, String? payload) async {
|
|
// display a dialog with the notification details, tap ok to go to another page
|
|
}
|
|
}
|
|
|
|
class NotificationController1 extends GetxController {
|
|
final FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin =
|
|
FlutterLocalNotificationsPlugin();
|
|
|
|
// Initializes the local notifications plugin
|
|
Future<void> initNotifications() async {
|
|
const AndroidInitializationSettings android =
|
|
AndroidInitializationSettings('@mipmap/launcher_icon');
|
|
const InitializationSettings initializationSettings =
|
|
InitializationSettings(android: android);
|
|
await _flutterLocalNotificationsPlugin.initialize(initializationSettings);
|
|
}
|
|
|
|
// Displays a notification with the given title and message
|
|
void showNotification(
|
|
String title, String message, String tone, String payLoad) async {
|
|
AndroidNotificationDetails android = AndroidNotificationDetails(
|
|
'your channel id', 'your channel name',
|
|
importance: Importance.max,
|
|
priority: Priority.high,
|
|
showWhen: false,
|
|
sound: RawResourceAndroidNotificationSound(tone));
|
|
|
|
NotificationDetails details = NotificationDetails(android: android);
|
|
await _flutterLocalNotificationsPlugin.show(0, title, message, details);
|
|
}
|
|
}
|