mymuseum-visitapp/lib/Services/pushNotificationService.dart

94 lines
3.2 KiB
Dart

import 'dart:io';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
/// Handles background FCM messages (must be top-level function)
@pragma('vm:entry-point')
Future<void> firebaseMessagingBackgroundHandler(RemoteMessage message) async {
// Firebase is already initialized in main — nothing to do here,
// the OS will display the notification automatically.
}
class PushNotificationService {
static final FlutterLocalNotificationsPlugin _localNotifications =
FlutterLocalNotificationsPlugin();
/// Notifier set when the user taps a notification (background or terminated).
static final ValueNotifier<RemoteMessage?> tappedMessage = ValueNotifier(null);
/// Call once after Firebase.initializeApp(), passing the instanceId.
static Future<void> initialize(String instanceId) async {
// Register background handler
FirebaseMessaging.onBackgroundMessage(firebaseMessagingBackgroundHandler);
// Request permission (iOS / Android 13+)
await FirebaseMessaging.instance.requestPermission(
alert: true,
badge: true,
sound: true,
);
// Configure local notifications for foreground display
const androidSettings =
AndroidInitializationSettings('@mipmap/ic_launcher');
const iosSettings = DarwinInitializationSettings();
await _localNotifications.initialize(
const InitializationSettings(android: androidSettings, iOS: iosSettings),
);
// Subscribe to the instance topic
await subscribeToInstance(instanceId);
// Show local notification when app is in foreground
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
_showLocalNotification(message);
});
// App opened from background by tapping a notification
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
tappedMessage.value = message;
});
// App launched from terminated state by tapping a notification
final initial = await FirebaseMessaging.instance.getInitialMessage();
if (initial != null) {
Future.delayed(const Duration(milliseconds: 500), () {
tappedMessage.value = initial;
});
}
}
static Future<void> subscribeToInstance(String instanceId) async {
await FirebaseMessaging.instance
.subscribeToTopic('instance_$instanceId');
}
static Future<void> unsubscribeFromInstance(String instanceId) async {
await FirebaseMessaging.instance
.unsubscribeFromTopic('instance_$instanceId');
}
static Future<void> _showLocalNotification(RemoteMessage message) async {
final notification = message.notification;
if (notification == null) return;
const androidDetails = AndroidNotificationDetails(
'push_notifications',
'Push Notifications',
channelDescription: 'Notifications from the museum',
importance: Importance.high,
priority: Priority.high,
);
const iosDetails = DarwinNotificationDetails();
await _localNotifications.show(
notification.hashCode,
notification.title,
notification.body,
const NotificationDetails(android: androidDetails, iOS: iosDetails),
);
}
}