// lib/core/service/fcm_service.dart import 'dart:convert'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:smpn1_lengkong/core/routes/app_routes.dart'; import 'package:smpn1_lengkong/main.dart'; import 'package:smpn1_lengkong/core/service/student_service.dart'; // WAJIB: Fungsi ini mesti di luar class untuk handle notif saat aplikasi mati (Terminated) @pragma('vm:entry-point') Future firebaseMessagingBackgroundHandler(RemoteMessage message) async { debugPrint("Handling a background message: ${message.messageId}"); // Anda boleh tambah logik simpan data ke local storage di sini jika perlu } class FcmService { final _firebaseMessaging = FirebaseMessaging.instance; final _localNotifications = FlutterLocalNotificationsPlugin(); final _androidChannel = const AndroidNotificationChannel( 'high_importance_channel', 'High Importance Notifications', description: 'This channel is used for important notifications.', importance: Importance.max, playSound: true, // Pastikan ini true enableVibration: true, ); Future initNotifications() async { // Minta Izin User NotificationSettings settings = await _firebaseMessaging.requestPermission( alert: true, badge: true, sound: true, ); if (settings.authorizationStatus == AuthorizationStatus.authorized) { // Dapatkan Token untuk keperluan push dari website/backend String? token = await _firebaseMessaging.getToken(); debugPrint("FCM Token: $token"); } // Setup Notifikasi Lokal untuk Foreground const androidSettings = AndroidInitializationSettings('@mipmap/ic_launcher'); const iosSettings = DarwinInitializationSettings(); await _localNotifications.initialize( const InitializationSettings(android: androidSettings, iOS: iosSettings), onDidReceiveNotificationResponse: (NotificationResponse response) { if (response.payload != null) { final message = RemoteMessage.fromMap(jsonDecode(response.payload!)); _handleMessage(message); } }, ); final platform = _localNotifications.resolvePlatformSpecificImplementation< AndroidFlutterLocalNotificationsPlugin>(); await platform?.createNotificationChannel(_androidChannel); // Listen notif saat aplikasi terbuka (Foreground) FirebaseMessaging.onMessage.listen((RemoteMessage message) { final notification = message.notification; if (notification != null) { _localNotifications.show( notification.hashCode, notification.title, notification.body, NotificationDetails( android: AndroidNotificationDetails( _androidChannel.id, _androidChannel.name, channelDescription: _androidChannel.description, icon: 'ic_launcher', importance: Importance.max, priority: Priority.high, ), ), payload: jsonEncode(message.toMap()), ); } }); _setupInteractedMessage(); } // Handle ketika notifikasi diklik (Aplikasi dari mati/background jadi terbuka) Future _setupInteractedMessage() async { // 1. Jika aplikasi dalam keadaan TERMINATED RemoteMessage? initialMessage = await _firebaseMessaging.getInitialMessage(); if (initialMessage != null) { _handleMessage(initialMessage); } // 2. Jika aplikasi dalam keadaan BACKGROUND FirebaseMessaging.onMessageOpenedApp.listen(_handleMessage); } void _handleMessage(RemoteMessage message) async { final data = message.data; final type = data['type']; // Ambil data student (Gunakan StudentService yang sudah ada) final studentData = await StudentService().getCurrentStudentData(); if (navigatorKey.currentState == null) return; // Logik Navigasi berdasarkan 'type' data yang dikirim dari website if (type == 'violation') { navigatorKey.currentState?.pushNamed(AppRoutes.discipline, arguments: studentData); } else if (type == 'academic') { navigatorKey.currentState?.pushNamed(AppRoutes.academic, arguments: studentData); } else if (type == 'attendance') { navigatorKey.currentState?.pushNamed(AppRoutes.attendance, arguments: studentData); } else { navigatorKey.currentState?.pushNamed( AppRoutes.notificationDetail, arguments: { 'title': message.notification?.title ?? 'Pengumuman', 'body': message.notification?.body ?? '', 'date': DateTime.now().toString(), }, ); } } }