Here my issue is "The notification appears in the notification bar, but the notification banner popup does not appear in the background or terminated state. The banner works correctly after receiving a notification in the foreground state. What could be the issue?"

here below pasting the code of main.dart file

Future<void> main() async {
  await runZonedGuarded(
    () async {
      WidgetsFlutterBinding.ensureInitialized();
      Bloc.observer = AppBlocObserver();
      SystemChrome.setPreferredOrientations([
        DeviceOrientation.portraitUp,
        DeviceOrientation.portraitDown,
      ]);
      FlutterError.onError = (details) {
        log(details.exceptionAsString(), stackTrace: details.stack);
      };
      ///firebase initialize
      await Firebase.initializeApp(
        options: DefaultFirebaseOptions.currentPlatform,
      );
      FirebasePerformance performance = FirebasePerformance.instance;
      performance.isPerformanceCollectionEnabled();
      NotificationServices.getFirebaseMessagingToken().then((_) {
        NotificationServices().firebaseInit();
      });
      FlutterError.onError =
          FirebaseCrashlytics.instance.recordFlutterFatalError;
      PlatformDispatcher.instance.onError = (error, stack) {
        FirebaseCrashlytics.instance.recordError(error, stack, fatal: true);
        return true;
      };
      runApp(child: const MyApp())));
    },
    (error, stackTrace) => log(error.toString(), stackTrace: stackTrace),
  );
}

here i am pasting the code of Notification service class

class NotificationServices {
  static String? firebasePushToken;

  static FirebaseMessaging firebaseMessaging = FirebaseMessaging.instance;
  static final FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin =
      FlutterLocalNotificationsPlugin();

  static void initLocalNotifications(RemoteMessage message) async {
    var androidInitializationSettings =
    const AndroidInitializationSettings('@mipmap/launcher_icon');
    var iosInitializationSettings = const DarwinInitializationSettings();
    var initializationSetting = InitializationSettings(
        android: androidInitializationSettings, iOS: iosInitializationSettings);

    await _flutterLocalNotificationsPlugin.initialize(
      initializationSetting,
      onDidReceiveNotificationResponse: (payload) {
        handleMessage(message);
      },
    );
  }

  Future<void> firebaseInit() async {
    FirebaseMessaging.onMessage.listen((message) async {
      String? receiverId = await PrefManager.retrieveValue(
          Constants.id);
      String senderId  = message.data['senderId'];
      if(receiverId != null && senderId != receiverId)
        {
          if (Platform.isIOS) {
            initLocalNotifications(message);
          } else {
            initLocalNotifications(message);
            showNotification(message);
          }
        }else{
        print("receiver id $receiverId senderId ${message.data['senderId']}");
      }
    });

    FirebaseMessaging.onMessageOpenedApp.listen((message) {
      print("on Message Opened");
      handleMessage(message);
      // Use NavigationService.navigateTo or other navigation logic here
    }
    );
  }

  static Future<void> showNotification(RemoteMessage message) async {
      print('inside showNotification');
    const AndroidNotificationChannel androidNotificationChannel =
        AndroidNotificationChannel(
            "high_importance_channel", "High Importance Notifications",
            description: 'This channel is used for important notifications.',
            importance: Importance.max);

    AndroidNotificationDetails androidNotificationDetails =
        AndroidNotificationDetails(
            androidNotificationChannel.id, androidNotificationChannel.name,
            channelDescription:
                'This channel is used for important notifications.',
            importance: Importance.high,
            priority: Priority.high);
    const DarwinNotificationDetails darwinNotificationDetails =
        DarwinNotificationDetails(
            presentAlert: true, presentBadge: true, presentSound: true);

    NotificationDetails notificationDetails = NotificationDetails(
      android: androidNotificationDetails,
      iOS: darwinNotificationDetails,
    );

    Future.delayed(Duration.zero, () {
      _flutterLocalNotificationsPlugin.show(
          0,
          message.notification?.title.toString(),
          message.notification?.body.toString(),
          notificationDetails);
    });
  }

  static Future<String?> getFirebaseMessagingToken() async {
    NotificationSettings settings = await firebaseMessaging.requestPermission(
      alert: true,
      announcement: true,
      badge: true,
      carPlay: true,
      criticalAlert: false,
      provisional: false,
      sound: true,
    );
    log('User granted firebase permission: ${settings.authorizationStatus}');
  
  
    await FirebaseMessaging.instance
        .setForegroundNotificationPresentationOptions(
      alert: true,
      badge: true,
      sound: true,
    );
    await firebaseMessaging.getToken().then((token) {
      if (token != null) {
        firebasePushToken = token;
        log("fcm token : $token");
      }
    });
    await PrefManager.storeValue(
        Constants.firebaseDeviceToken, firebasePushToken);
    return firebasePushToken;
  }

  ///Handling incoming message

  static Future<void> handleMessage(RemoteMessage? message) async {
    if (message == null) {
      return;
    } else {
      String isGroupChat = message.data["isGroupChat"];
      String senderId = message.data["senderId"];
      String? receiverId = await PrefManager.retrieveValue(
          Constants.id);
      if (receiverId != null && message.notification?.title != null) {
        if(isGroupChat == 'true')
          {
            print("inside groupChat ");
            NavigationService.navigateTo(AppRoutes.groupChatScreen,arguments: {
              'currentUserId':receiverId,
              'topicName':message.data["topicName"],
              'groupName':message.notification?.title,
            });
          }else{
          NavigationService.navigateTo(AppRoutes.chatScreen, arguments: {
            'name': senderName,
            'userId': senderId,
            'currentUserId': receiverId,
          });
          }
      } else {
        print(" null");
      }
      print("notification msg");
    }
  }
}

The notification appears in the notification bar, but the notification banner popup does not appear in the background or terminated state. The banner works correctly after receiving a notification in the foreground state. What could be the issue?.

payload Details

final body = {
        "to":groupChat? "/topics/$pushToken": pushToken,
        "notification": {
          "android_channel_id": "high_importance_channel",
          "title":groupChat? groupName:senderName,
          "body":groupChat?'$senderName : $msg':msg,
          "priority": "high",
          "time_to_live": 86400,
          "click_action": "FLUTTER_NOTIFICATION_CLICK",
        },
        "data":{
          "chatId":chatId,
          "senderId":senderId,
          "isGroupChat":groupChat,
          "topicName":pushToken,
          "memberCount":memberCount,
          "groupId":groupId
        },
        "android": {
          "priority": "high"
        },
        "apns": {
          "payload": {
            "aps": {
              "contentAvailable": true
            }
          }
        }
      };

1

There are 1 best solutions below

7
FDuhen On

Is this issue happening with locale notifications or with remote notifications ?
If you're using a server to send the notification, could you share the detail of your payload ?

Things you can update in your mobile app is to add this to your AndroidManifest.xml

...
        <meta-data
            android:name="com.google.firebase.messaging.default_notification_channel_id"
            android:value="high_importance_channel" />
    </application>
</manifest>

And you can also set the importance and the priority to "max"

AndroidNotificationDetails(
  'high_importance_channel',
  'YOUR_CHANNEL_NAME',
  channelDescription: 'YOUR_CHANNEL_DESCRIPTION',
  importance: Importance.max,
  priority: Priority.max,
)

You can also set the importance in the server payload to "max".
And, more importantly, do your tests on a real device and not on an emulator. The behavior on emulated devices is quite buggy with the notifications.