I m 开发一个挥发式镜,用于推动通知和用于当地通知的繁琐通知包。 然而,我碰到了一个问题,即我收到一份单一的刚果解放运动推动通知书后,便显示两份通知而不是一份通知。 不论情况如何(理由、背景或终止)。
这里简要概述我的手头如何处理现金支付通知:
import package:firebase_core/firebase_core.dart ;
import package:firebase_messaging/firebase_messaging.dart ;
import package:logger/logger.dart ;
import ../app/data/local/my_shared_pref.dart ;
import awesome_notifications_helper.dart ;
class FcmHelper {
// prevent making instance
FcmHelper._();
// FCM Messaging
static late FirebaseMessaging messaging;
/// this function will initialize firebase and fcm instance
static Future<void> initFcm() async {
try {
// initialize fcm and firebase core
await Firebase.initializeApp(
// TODO: uncomment this line if you connected to firebase via cli
//options: DefaultFirebaseOptions.currentPlatform,
);
// initialize firebase
messaging = FirebaseMessaging.instance;
// notification settings handler
await _setupFcmNotificationSettings();
// generate token if it not already generated and store it on shared pref
await _generateFcmToken();
// background and foreground handlers
FirebaseMessaging.onMessage.listen(_fcmForegroundHandler);
FirebaseMessaging.onBackgroundMessage(_fcmBackgroundHandler);
} catch (error) {
// if you are connected to firebase and still get error
// check the todo up in the function else ignore the error
// or stop fcm service from main.dart class
Logger().e(error);
}
}
///handle fcm notification settings (sound,badge..etc)
static Future<void> _setupFcmNotificationSettings() async {
//show notification with sound and badge
messaging.setForegroundNotificationPresentationOptions(
alert: true,
sound: true,
badge: true,
);
//NotificationSettings settings
await messaging.requestPermission(
alert: true,
badge: true,
sound: true,
provisional: true,
);
}
/// generate and save fcm token if its not already generated (generate only for 1 time)
static Future<void> _generateFcmToken() async {
try {
var token = await messaging.getToken();
if (token != null) {
MySharedPref.setFcmToken(token);
_sendFcmTokenToServer();
} else {
// retry generating token
await Future.delayed(const Duration(seconds: 5));
_generateFcmToken();
}
} catch (error) {
Logger().e(error);
}
}
/// this method will be triggered when the app generate fcm
/// token successfully
static _sendFcmTokenToServer() {
var token = MySharedPref.getFcmToken();
// TODO SEND FCM TOKEN TO SERVER
}
///handle fcm notification when app is closed/terminated
/// if you are wondering about this annotation read the following
/// https://stackoverflow.com/a/67083337
@pragma( vm:entry-point )
static Future<void> _fcmBackgroundHandler(RemoteMessage message) async {
AwesomeNotificationsHelper.showNotification(
id: 1,
title: message.notification?.title ?? Tittle ,
body: message.notification?.body ?? Body ,
payload: message.data
.cast(), // pass payload to the notification card so you can use it (when user click on notification)
);
}
//handle fcm notification when app is open
static Future<void> _fcmForegroundHandler(RemoteMessage message) async {
AwesomeNotificationsHelper.showNotification(
id: DateTime.now().microsecond,
title: message.notification?.title ?? Tittle ,
body: message.notification?.body ?? Body ,
payload: message.data
.cast(), // pass payload to the notification card so you can use it (when user click on notification)
);
}
}
在这里,我是如何初步确定“敏感通知”的:
import package:awesome_notifications/awesome_notifications.dart ;
import package:flutter/material.dart ;
import package:get/get.dart ;
import ../routes/app_pages.dart ;
class AwesomeNotificationsHelper {
// prevent making instance
AwesomeNotificationsHelper._();
// Notification lib
static AwesomeNotifications awesomeNotifications = AwesomeNotifications();
/// initialize local notifications service, create channels and groups
/// setup notifications button actions handlers
static init() async {
// initialize local notifications
await _initNotification();
// request permission to show notifications
await awesomeNotifications.requestPermissionToSendNotifications();
// list when user click on notifications
listenToActionButtons();
}
/// when user click on notification or click on button on the notification
static listenToActionButtons() {
// Only after at least the action method is set, the notification events are delivered
awesomeNotifications.setListeners(
onActionReceivedMethod: NotificationController.onActionReceivedMethod,
onNotificationCreatedMethod:
NotificationController.onNotificationCreatedMethod,
onNotificationDisplayedMethod:
NotificationController.onNotificationDisplayedMethod,
onDismissActionReceivedMethod:
NotificationController.onDismissActionReceivedMethod);
}
///init notifications channels
static _initNotification() async {
await awesomeNotifications.initialize(
null, // null mean it will show app icon on the notification (status bar)
[
NotificationChannel(
channelGroupKey: NotificationChannels.generalChannelGroupKey,
channelKey: NotificationChannels.generalChannelKey,
channelName: NotificationChannels.generalChannelName,
groupKey: NotificationChannels.generalGroupKey,
channelDescription: NotificationChannels.generalChannelDescription,
defaultColor: Colors.green,
ledColor: Colors.white,
channelShowBadge: true,
playSound: true,
importance: NotificationImportance.Max,
),
// NotificationChannel(
// channelGroupKey: NotificationChannels.chatChannelGroupKey,
// channelKey: NotificationChannels.chatChannelKey,
// channelName: NotificationChannels.chatChannelName,
// groupKey: NotificationChannels.chatGroupKey,
// channelDescription: NotificationChannels.chatChannelDescription,
// defaultColor: Colors.green,
// ledColor: Colors.white,
// channelShowBadge: true,
// playSound: true,
// importance: NotificationImportance.Max)
], channelGroups: [
NotificationChannelGroup(
channelGroupKey: NotificationChannels.generalChannelGroupKey,
channelGroupName: NotificationChannels.generalChannelGroupName,
),
// NotificationChannelGroup(
// channelGroupKey: NotificationChannels.chatChannelGroupKey,
// channelGroupName: NotificationChannels.chatChannelGroupName,
// )
]);
}
//display notification for user with sound
static showNotification(
{required String title,
required String body,
required int id,
String? channelKey,
String? groupKey,
NotificationLayout? notificationLayout,
String? summary,
List<NotificationActionButton>? actionButtons,
Map<String, String>? payload,
String? largeIcon}) async {
awesomeNotifications.isNotificationAllowed().then((isAllowed) {
if (!isAllowed) {
awesomeNotifications.requestPermissionToSendNotifications();
} else {
// u can show notification
awesomeNotifications.createNotification(
content: NotificationContent(
id: id,
title: title,
body: body,
groupKey: groupKey ?? NotificationChannels.generalGroupKey,
channelKey: channelKey ?? NotificationChannels.generalChannelKey,
showWhen:
true, // Hide/show the time elapsed since notification was displayed
payload:
payload, // data of the notification (it will be used when user clicks on notification)
notificationLayout: notificationLayout ??
NotificationLayout
.Default, // notification shape (message,media player..etc) For ex => NotificationLayout.Messaging
autoDismissible:
true, // dismiss notification when user clicks on it
summary:
summary, // for ex: New message (it will be shown on status bar before notificaiton shows up)
largeIcon:
largeIcon, // image of sender for ex (when someone send you message his image will be shown)
),
actionButtons: actionButtons,
);
}
});
}
}
class NotificationController {
/// Use this method to detect when a new notification or a schedule is created
@pragma("vm:entry-point")
static Future<void> onNotificationCreatedMethod(
ReceivedNotification receivedNotification) async {
// Your code goes here
}
/// Use this method to detect every time that a new notification is displayed
@pragma("vm:entry-point")
static Future<void> onNotificationDisplayedMethod(
ReceivedNotification receivedNotification) async {
// Your code goes here
}
/// Use this method to detect if the user dismissed a notification
@pragma("vm:entry-point")
static Future<void> onDismissActionReceivedMethod(
ReceivedAction receivedAction) async {
// Your code goes here
}
/// Use this method to detect when the user taps on a notification or action button
@pragma("vm:entry-point")
static Future<void> onActionReceivedMethod(
ReceivedAction receivedAction) async {
// Map<String, String?>? payload = receivedAction.payload;
// TODO handle clicking on notification
// example
// String routeToGetTo = payload[ route ];
// normal navigation (Get.toNamed) will throw error
Get.key.currentState?.pushNamed(Routes.dashboard);
}
}
class NotificationChannels {
// // chat channel (for messages only)
// static String get chatChannelKey => "chat_channel";
// static String get chatChannelName => "Chat channel";
// static String get chatGroupKey => "chat group key";
// static String get chatChannelGroupKey => "chat_channel_group";
// static String get chatChannelGroupName => "Chat notifications channels";
// static String get chatChannelDescription => "Chat notifications channels";
// general channel (for all other notifications)
static String get generalChannelKey => "jobjourney_channel";
static String get generalGroupKey => "jobjourney group key";
static String get generalChannelGroupKey => "jobjourney_channel_group";
static String get generalChannelGroupName =>
"jobjourney notifications channel";
static String get generalChannelName => "jobjourney notifications channels";
static String get generalChannelDescription =>
"Notification channel for jobjourney notifications";
}
我如何确定和解决在使用FCM时收到重复通知的原因,并在“彩虹”中发出过繁多的通知? 这两项通知处理机制之间是否有已知的问题或冲突,我或许会考虑?