flutterdartpush-notificationnotificationsfirebase-cloud-messaging

FCM & AwesomeNotifications display notification twice


Im using Firebase Cloud Messaging as my push notification service and AwesomeNotifications package for the notification badge service. Everything's working fine but there is only one problem where the notification displayed twice one from the FCM the other is from AwesomeNotifications i have setting up my AwesomeNotifications service logic on user tap so i don't need the notification display from FCM, how do i dasble it?

Here is where all the initiation function called

  static Future<void> initFcm() async {
try {
  fcm = 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) {
  Logger().e(error);
}
}

Here is the fcm request permission

  static Future<void> _setupFcmNotificationSettings() async {
//show notification with sound and badge
fcm.setForegroundNotificationPresentationOptions(
  alert: true,
  sound: true,
  badge: true,
);

//NotificationSettings settings
await fcm.requestPermission(
  alert: true,
  badge: true,
  sound: true,
  provisional: true,
);

}

Here is the foreground & background handler

 @pragma('vm:entry-point')
  static Future<void> _fcmBackgroundHandler(RemoteMessage message) async {
    devLog(text: 'Message: ${message.toMap()}');

    // Notification Component
    AwesomeNotificationsHelper.showNotification(
      id: 1,
      title: message.notification?.title ?? 'Title',
      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 {
    // Notification Component
    AwesomeNotificationsHelper.showNotification(
      id: 1,
      title: message.notification?.title ?? 'Title',
      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)
    );
  }

Here is where the action on user tap with AwesomeNotifications

    @pragma("vm:entry-point")
  static Future<void> onActionReceivedMethod(
      ReceivedAction receivedAction) async {
    Map<String, String?>? payload = receivedAction.payload;
    String? route = payload?['to'];
    if (route != null && route.isNotEmpty) {
      if (!router.canPop()) {
        router.go(HomeScreen.route);
      }
      router.push(route);
    }

    devLog(text: 'payload => $payload');
  }

i've read a similar question from this Notification show twice on flutter but didn't get the answer


Solution

  • When sending a message/notification to your device, make sure it is a notification rather than data. The doc mentions that if you send data it will likely be ignored as a push notification. Only use it to send packets of data to the app instead.

    Also, Suppose your notification is sent while the App is in the background. In that case, Firebase automatically sends a push notification, so you don't need to trigger the show notification manually in the App.

    And for local notification one more suggestion is that , use different Id's for creating the local notification like this:

    static int getUniqueNotificationId() {
    var randomNumber = Random();
    var resultOne = randomNumber.nextInt(2000);
    var resultTwo = randomNumber.nextInt(100);
    if (resultTwo >= resultOne) resultTwo += 1;
    return resultTwo;}
    
    await AwesomeNotifications().createNotification(
        content: NotificationContent(
          id: getUniqueNotificationId(),
          channelKey: 'channel_name',
          title: title,
          body: body,
          notificationLayout: notificationLayout,
          payload: remoteMessage,
          actionType: ActionType.Default,
        ),
      );