187 lines
5.6 KiB
Dart
187 lines
5.6 KiB
Dart
import 'dart:async';
|
|
import 'dart:convert';
|
|
import 'package:firebase_core/firebase_core.dart';
|
|
import 'package:firebase_messaging/firebase_messaging.dart';
|
|
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
|
import 'auth_service.dart';
|
|
|
|
@pragma('vm:entry-point')
|
|
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
|
|
await Firebase.initializeApp();
|
|
print('Background message: ${message.messageId}');
|
|
}
|
|
|
|
class NotificationService {
|
|
static final NotificationService _instance = NotificationService._internal();
|
|
factory NotificationService() => _instance;
|
|
NotificationService._internal();
|
|
|
|
final FirebaseMessaging _firebaseMessaging = FirebaseMessaging.instance;
|
|
final FlutterLocalNotificationsPlugin _localNotifications =
|
|
FlutterLocalNotificationsPlugin();
|
|
|
|
bool _initialized = false;
|
|
|
|
// Stream per gestire i tap sulle notifiche
|
|
final StreamController<RemoteMessage> _messageStreamController =
|
|
StreamController<RemoteMessage>.broadcast();
|
|
|
|
Stream<RemoteMessage> get onMessageTap => _messageStreamController.stream;
|
|
|
|
Future<void> initialize() async {
|
|
if (_initialized) return;
|
|
|
|
try {
|
|
await _requestPermissions();
|
|
await _initializeLocalNotifications();
|
|
_configureHandlers();
|
|
await _getFcmToken();
|
|
_initialized = true;
|
|
print('NotificationService initialized');
|
|
} catch (e) {
|
|
print('Error initializing notifications: $e');
|
|
}
|
|
}
|
|
|
|
Future<void> _requestPermissions() async {
|
|
final settings = await _firebaseMessaging.requestPermission(
|
|
alert: true,
|
|
badge: true,
|
|
sound: true,
|
|
);
|
|
print('Notification permission: ${settings.authorizationStatus}');
|
|
}
|
|
|
|
Future<void> _initializeLocalNotifications() async {
|
|
const androidSettings = AndroidInitializationSettings('@mipmap/ic_launcher');
|
|
const iosSettings = DarwinInitializationSettings();
|
|
|
|
await _localNotifications.initialize(
|
|
const InitializationSettings(android: androidSettings, iOS: iosSettings),
|
|
onDidReceiveNotificationResponse: _onNotificationTapped,
|
|
);
|
|
|
|
const channel = AndroidNotificationChannel(
|
|
'allarmi_channel',
|
|
'Allarmi',
|
|
description: 'Notifiche per allarmi del sistema di monitoraggio',
|
|
importance: Importance.high,
|
|
playSound: true,
|
|
enableVibration: true,
|
|
);
|
|
|
|
await _localNotifications
|
|
.resolvePlatformSpecificImplementation<
|
|
AndroidFlutterLocalNotificationsPlugin>()
|
|
?.createNotificationChannel(channel);
|
|
}
|
|
|
|
void _onNotificationTapped(NotificationResponse response) {
|
|
print('Notifica tappata: ${response.payload}');
|
|
if (response.payload != null && response.payload!.isNotEmpty) {
|
|
try {
|
|
final data = jsonDecode(response.payload!);
|
|
// Crea un RemoteMessage mock per compatibilità
|
|
final message = RemoteMessage(
|
|
data: data,
|
|
messageId: DateTime.now().toString(),
|
|
);
|
|
_messageStreamController.add(message);
|
|
} catch (e) {
|
|
print('Errore parsing payload: $e');
|
|
}
|
|
}
|
|
}
|
|
|
|
void _configureHandlers() {
|
|
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
|
|
FirebaseMessaging.onMessage.listen(_handleForegroundMessage);
|
|
|
|
// Handler quando app aperta da notifica (background/terminated)
|
|
FirebaseMessaging.onMessageOpenedApp.listen((message) {
|
|
print('Notifica aperta (background): ${message.messageId}');
|
|
_messageStreamController.add(message);
|
|
});
|
|
|
|
// Controlla se app avviata da notifica
|
|
_firebaseMessaging.getInitialMessage().then((message) {
|
|
if (message != null) {
|
|
print('App avviata da notifica: ${message.messageId}');
|
|
_messageStreamController.add(message);
|
|
}
|
|
});
|
|
}
|
|
|
|
Future<void> _getFcmToken() async {
|
|
try {
|
|
final token = await _firebaseMessaging.getToken();
|
|
if (token != null) {
|
|
print('FCM Token: $token');
|
|
await AuthService().saveFcmToken(token);
|
|
}
|
|
|
|
_firebaseMessaging.onTokenRefresh.listen((newToken) {
|
|
AuthService().saveFcmToken(newToken);
|
|
});
|
|
} catch (e) {
|
|
print('Error getting FCM token: $e');
|
|
}
|
|
}
|
|
|
|
Future<void> _handleForegroundMessage(RemoteMessage message) async {
|
|
print('Foreground message: ${message.messageId}');
|
|
final notification = message.notification;
|
|
if (notification != null) {
|
|
await _showLocalNotification(
|
|
title: notification.title ?? 'ASE Monitor',
|
|
body: notification.body ?? 'Nuovo allarme',
|
|
payload: jsonEncode(message.data),
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<void> _showLocalNotification({
|
|
required String title,
|
|
required String body,
|
|
String? payload,
|
|
}) async {
|
|
const androidDetails = AndroidNotificationDetails(
|
|
'allarmi_channel',
|
|
'Allarmi',
|
|
channelDescription: 'Notifiche per allarmi del sistema di monitoraggio',
|
|
importance: Importance.high,
|
|
priority: Priority.high,
|
|
playSound: true,
|
|
enableVibration: true,
|
|
icon: '@mipmap/ic_launcher',
|
|
);
|
|
|
|
const iosDetails = DarwinNotificationDetails(
|
|
presentAlert: true,
|
|
presentBadge: true,
|
|
presentSound: true,
|
|
);
|
|
|
|
await _localNotifications.show(
|
|
DateTime.now().millisecondsSinceEpoch ~/ 1000,
|
|
title,
|
|
body,
|
|
const NotificationDetails(android: androidDetails, iOS: iosDetails),
|
|
payload: payload,
|
|
);
|
|
}
|
|
|
|
Future<String?> getFcmToken() async {
|
|
try {
|
|
return await _firebaseMessaging.getToken();
|
|
} catch (e) {
|
|
print('Errore ottenimento FCM token: $e');
|
|
return null;
|
|
}
|
|
}
|
|
|
|
void dispose() {
|
|
_messageStreamController.close();
|
|
}
|
|
}
|