flutter-freaccess-hub/lib/backend/push_notification/push_notification.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;