import 'package:flutter/foundation.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:app_badge_plus/app_badge_plus.dart'; import 'package:permission_handler/permission_handler.dart'; /// Central service for all local notification and badge operations. /// Call [initialize] once in main(), then use [showNotification] and [setBadge]. class NotificationService { static final NotificationService _instance = NotificationService._internal(); factory NotificationService() => _instance; NotificationService._internal(); static const String _channelId = 'mapan_loyalty_channel'; static const String _channelName = 'Mie Mapan Promos'; static const String _channelDescription = 'Notifications for new promos and loyalty rewards from Mie Mapan.'; final FlutterLocalNotificationsPlugin _flnp = FlutterLocalNotificationsPlugin(); bool _initialized = false; Future initialize() async { if (_initialized) return; const androidInit = AndroidInitializationSettings('@mipmap/ic_launcher'); const darwinInit = DarwinInitializationSettings( requestAlertPermission: false, requestBadgePermission: false, requestSoundPermission: false, ); const initSettings = InitializationSettings( android: androidInit, iOS: darwinInit, ); await _flnp.initialize( settings: initSettings, ); await _createNotificationChannel(); _initialized = true; } Future _createNotificationChannel() async { const channel = AndroidNotificationChannel( _channelId, _channelName, description: _channelDescription, importance: Importance.max, ); await _flnp .resolvePlatformSpecificImplementation< AndroidFlutterLocalNotificationsPlugin>() ?.createNotificationChannel(channel); } /// Request POST_NOTIFICATIONS permission on Android 13+. Future requestPermission() async { if (await Permission.notification.isDenied) { await Permission.notification.request(); } } /// Show a single notification in the device tray. Future showNotification({ required int id, required String title, required String body, }) async { await initialize(); const androidDetails = AndroidNotificationDetails( _channelId, _channelName, channelDescription: _channelDescription, importance: Importance.max, priority: Priority.high, icon: '@mipmap/ic_launcher', ); const iosDetails = DarwinNotificationDetails( presentAlert: true, presentBadge: true, presentSound: true, ); const details = NotificationDetails( android: androidDetails, iOS: iosDetails, ); await _flnp.show( id: id, title: title, body: body, notificationDetails: details, ); } /// Set the badge count on the app icon. Future setBadge(int count) async { try { final supported = await AppBadgePlus.isSupported(); if (supported) { await AppBadgePlus.updateBadge(count); } } catch (e) { debugPrint('Badge update error: $e'); } } /// Clear the badge count (set to 0). Future clearBadge() => setBadge(0); }