182 lines
6.0 KiB
Dart
182 lines
6.0 KiB
Dart
import 'dart:async';
|
|
import 'dart:developer';
|
|
|
|
import 'package:firebase_core/firebase_core.dart';
|
|
import 'package:firebase_messaging/firebase_messaging.dart';
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
|
import 'package:hub/firebase_options.dart';
|
|
|
|
class NotificationService {
|
|
// Singleton instance
|
|
static final NotificationService _instance = NotificationService._internal();
|
|
|
|
// Factory constructor
|
|
factory NotificationService() => _instance;
|
|
|
|
// Private constructor
|
|
NotificationService._internal();
|
|
|
|
static final FirebaseMessaging _firebaseMessaging =
|
|
FirebaseMessaging.instance;
|
|
static final FlutterLocalNotificationsPlugin
|
|
_flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
|
|
static bool _initialized = false;
|
|
|
|
Future<void> initialize() async {
|
|
if (_initialized) return;
|
|
_initialized = true;
|
|
|
|
try {
|
|
await _requestPermissions();
|
|
await _initializeLocalNotifications();
|
|
|
|
FirebaseMessaging.onBackgroundMessage(
|
|
_firebaseMessagingBackgroundHandler);
|
|
|
|
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
|
|
_printNotification(message, 'onMessage');
|
|
});
|
|
|
|
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
|
|
_printNotification(message, 'onMessageOpenedApp');
|
|
});
|
|
} catch (e) {
|
|
log('Error initializing notification manager: $e');
|
|
}
|
|
}
|
|
|
|
Future<void> _printNotification(RemoteMessage message, String type) async {
|
|
log('Notification $type: ${message.messageId}');
|
|
// Handle the notification display logic here
|
|
}
|
|
|
|
Future<void> _initializeLocalNotifications() async {
|
|
const AndroidInitializationSettings initializationSettingsAndroid =
|
|
AndroidInitializationSettings('@mipmap/ic_launcher');
|
|
final DarwinInitializationSettings initializationSettingsIOS =
|
|
DarwinInitializationSettings(
|
|
onDidReceiveLocalNotification:
|
|
(int id, String? title, String? body, String? payload) async {
|
|
// Handle the notification received in foreground
|
|
},
|
|
);
|
|
final InitializationSettings initializationSettings =
|
|
InitializationSettings(
|
|
android: initializationSettingsAndroid,
|
|
iOS: initializationSettingsIOS,
|
|
);
|
|
|
|
await _flutterLocalNotificationsPlugin.initialize(initializationSettings,
|
|
onDidReceiveNotificationResponse: (payload) async =>
|
|
log('Notification tapped: $payload'),
|
|
onDidReceiveBackgroundNotificationResponse: (payload) async =>
|
|
log('Notification tapped in background: $payload'));
|
|
}
|
|
|
|
Future<void> _requestPermissions() async {
|
|
NotificationSettings settings = await _firebaseMessaging.requestPermission(
|
|
alert: true,
|
|
announcement: false,
|
|
badge: true,
|
|
carPlay: false,
|
|
criticalAlert: false,
|
|
provisional: false,
|
|
sound: true,
|
|
);
|
|
|
|
log('User granted permission: ${settings.authorizationStatus}');
|
|
}
|
|
|
|
Future<void> subscribeToTopic(String topic) async {
|
|
try {
|
|
await _firebaseMessaging.subscribeToTopic(topic);
|
|
log('Subscribed to topic: $topic');
|
|
} catch (e) {
|
|
log('Error subscribing to topic $topic: $e');
|
|
}
|
|
}
|
|
|
|
Future<void> unsubscribeFromTopic(String topic) async {
|
|
try {
|
|
await _firebaseMessaging.unsubscribeFromTopic(topic);
|
|
log('Unsubscribed from topic: $topic');
|
|
} catch (e) {
|
|
log('Error unsubscribing from topic $topic: $e');
|
|
}
|
|
}
|
|
}
|
|
|
|
@pragma('vm:entry-point')
|
|
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
|
|
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
|
|
await setupFlutterNotifications();
|
|
showFlutterNotification(message);
|
|
// If you're going to use other Firebase services in the background, such as Firestore,
|
|
// make sure you call `initializeApp` before using other Firebase services.
|
|
log('Handling a background message ${message.messageId}');
|
|
}
|
|
|
|
/// Create a [AndroidNotificationChannel] for heads up notifications
|
|
late AndroidNotificationChannel channel;
|
|
|
|
bool isFlutterLocalNotificationsInitialized = false;
|
|
|
|
Future<void> setupFlutterNotifications() async {
|
|
if (isFlutterLocalNotificationsInitialized) {
|
|
return;
|
|
}
|
|
channel = const AndroidNotificationChannel(
|
|
'high_importance_channel', // id
|
|
'High Importance Notifications', // title
|
|
description:
|
|
'This channel is used for important notifications.', // description
|
|
importance: Importance.high,
|
|
);
|
|
|
|
flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
|
|
|
|
/// Create an Android Notification Channel.
|
|
///
|
|
/// We use this channel in the `AndroidManifest.xml` file to override the
|
|
/// default FCM channel to enable heads up notifications.
|
|
await flutterLocalNotificationsPlugin
|
|
.resolvePlatformSpecificImplementation<
|
|
AndroidFlutterLocalNotificationsPlugin>()
|
|
?.createNotificationChannel(channel);
|
|
|
|
/// Update the iOS foreground notification presentation options to allow
|
|
/// heads up notifications.
|
|
await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
|
|
alert: true,
|
|
badge: true,
|
|
sound: true,
|
|
);
|
|
isFlutterLocalNotificationsInitialized = true;
|
|
}
|
|
|
|
void showFlutterNotification(RemoteMessage message) {
|
|
RemoteNotification? notification = message.notification;
|
|
AndroidNotification? android = message.notification?.android;
|
|
if (notification != null && android != null && !kIsWeb) {
|
|
flutterLocalNotificationsPlugin.show(
|
|
notification.hashCode,
|
|
notification.title,
|
|
notification.body,
|
|
NotificationDetails(
|
|
android: AndroidNotificationDetails(
|
|
channel.id,
|
|
channel.name,
|
|
channelDescription: channel.description,
|
|
// TODO add a proper drawable resource to android, for now using
|
|
// one that already exists in example app.
|
|
icon: 'launch_background',
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
/// Initialize the [FlutterLocalNotificationsPlugin] package.
|
|
late FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin;
|