Code
Dependencies
- device_info_plus
- firebase_messaging
- flutter_local_notifications
- http
Code triển khai
fcm_services.dart
import 'dart:io';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'local_notitfication_helper.dart';
import 'package:http/http.dart' as http;
class FCMService {
FCMService._();
static FCMService? _instance;
static FCMService get instance {
return _instance ??= FCMService._();
}
final FirebaseMessaging _messaging = FirebaseMessaging.instance;
/// FCM Token
Future<String> _getFCMToken() async {
return await _messaging.getToken() ?? '';
}
/// APN Token IOS -> dùng khi muốn gửi noti trực tiếp qua APNs mà không dùng FCM
Future<String> _getAPNToken() async {
await FirebaseMessaging.instance.requestPermission();
return await _messaging.getAPNSToken() ?? '';
}
Future<String> getFCMRegistrationToken() async {
final token = await _getFCMToken();
if (kDebugMode) {
print('FCM RegistrationToken: $token');
}
return token;
}
/// Call in main.dart to init FCM
Future<void> init() async {
LocalNotificationHelper.instance.init();
_listenMessageOnForeground();
_listenMessageOnBackground();
}
void _listenMessageOnForeground() {
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
final RemoteNotification? notification = message.notification;
if (notification != null) {
showLocalNotification(notification);
}
});
}
void showLocalNotification(RemoteNotification notification) async {
// Đặt id cho thông báo (nếu có)
final notificationId = LocalNotificationHelper.generalNotificationId;
final notificationTitle = notification.title;
final notificationBody = notification.body;
final notificationImageUrl =
notification.android?.imageUrl ?? notification.apple?.imageUrl;
BigPictureStyleInformation? bigPictureStyleInformation;
if (notificationImageUrl != null) {
final Uint8List? bitmap = await _getBytesFromUrl(notificationImageUrl);
if (bitmap != null) {
final bigPicture = ByteArrayAndroidBitmap(bitmap);
bigPictureStyleInformation = BigPictureStyleInformation(
bigPicture,
);
}
}
final androidNotificationDetails = AndroidNotificationDetails(
LocalNotificationHelper.generalNotificationChannelId,
LocalNotificationHelper.generalNotificationChannelName,
importance: Importance.defaultImportance,
priority: Priority.high,
styleInformation: bigPictureStyleInformation,
);
final generalNotificationDetails = NotificationDetails(
android: androidNotificationDetails,
);
LocalNotificationHelper.instance.showNotification(
notificationId,
notificationTitle,
notificationBody,
notificationDetails: generalNotificationDetails,
);
}
void _listenMessageOnBackground() {
FirebaseMessaging.onBackgroundMessage(onBackgroundMessage);
}
static Future<void> onBackgroundMessage(RemoteMessage message) async {
final notification = message.notification;
if (notification != null) {
// Todo: Tuỳ chỉnh nếu cần
// FCMService.instance.showLocalNotification(notification);
}
}
Future<Uint8List?> _getBytesFromUrl(String url) async {
final uri = Uri.tryParse(url);
if (uri == null) {
return null;
}
final response = await http.get(uri);
return response.bodyBytes;
}
/// Device Id
Future<String?> getDeviceId() async {
final deviceInfoPlugin = DeviceInfoPlugin();
if (Platform.isAndroid) {
final AndroidDeviceInfo androidInfo = await deviceInfoPlugin.androidInfo;
return androidInfo.id;
} else if (Platform.isIOS) {
final IosDeviceInfo iosInfo = await deviceInfoPlugin.iosInfo;
return iosInfo.identifierForVendor;
}
return null;
}
}
local_notification_helper.dart
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
/// [LocalNotificationHelper] handle show local notification
///
class LocalNotificationHelper {
LocalNotificationHelper._();
static LocalNotificationHelper? _instance;
static LocalNotificationHelper get instance {
return _instance ??= LocalNotificationHelper._();
}
static const String generalNotificationChannelId = 'id-general-notifications';
static const String generalNotificationChannelName = 'General notifications';
static const int generalNotificationId = 321;
final FlutterLocalNotificationsPlugin _notificationsPlugin =
FlutterLocalNotificationsPlugin();
('vm:entry-point')
static Function(NotificationResponse notificationResponse)?
onDidReceiveBackgroundNotificationResponse;
void init({
Function(NotificationResponse notificationResponse)?
onDidReceiveNotificationResponse,
}) async {
final AndroidInitializationSettings initializationSettingsAndroid =
AndroidInitializationSettings('@mipmap/ic_launcher');
final DarwinInitializationSettings initializationSettingsDarwin =
DarwinInitializationSettings();
final InitializationSettings initializationSettings =
InitializationSettings(
android: initializationSettingsAndroid,
iOS: initializationSettingsDarwin,
);
await _notificationsPlugin.initialize(
initializationSettings,
onDidReceiveNotificationResponse: onDidReceiveNotificationResponse,
onDidReceiveBackgroundNotificationResponse:
onDidReceiveBackgroundNotificationResponse,
);
}
Future<void> showNotification(int id,
String? title,
String? body, {
NotificationDetails? notificationDetails,
String? payload,
}) async {
final AndroidNotificationDetails androidNotificationDetails =
AndroidNotificationDetails(
generalNotificationChannelId,
generalNotificationChannelName,
importance: Importance.defaultImportance,
priority: Priority.high,
);
final generalNotificationDetails = NotificationDetails(
android: androidNotificationDetails,
);
await _notificationsPlugin.show(
id,
title,
body,
notificationDetails ?? generalNotificationDetails,
);
}
}