odoo_loyalty_app/lib/services/notification_service.dart

110 lines
3.2 KiB
Dart

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<void> 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<void> _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<void> requestPermission() async {
if (await Permission.notification.isDenied) {
await Permission.notification.request();
}
}
/// Show a single notification in the device tray.
Future<void> 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<void> 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<void> clearBadge() => setBadge(0);
}