'Flutter Firebase foreground push notification not showing but background is working

It's been few days since I've been trying to solve this problem. I have implemented firebase messaging for push notification, as a result, I am able to receive notification when the app is in background, but not able to receive it when the app is in foreground. I tried every solution possible or on stackoverflow/github but nothing worked so far. The following are the sources which I tried:

stackoverflow solution 1

stackoverflow solution 2

Current code =>

NotificationService.dart:

class NotificationService {
  static final FlutterLocalNotificationsPlugin
      _flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();

  static Future initialize() async {
    final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
        FlutterLocalNotificationsPlugin();

    AndroidInitializationSettings androidInitializationSettings =
        AndroidInitializationSettings('@mipmap/ic_launcher');

    InitializationSettings initializationSettings =
        InitializationSettings(android: androidInitializationSettings);

    await flutterLocalNotificationsPlugin.initialize(
      initializationSettings,
      // onSelectNotification: doSomething(),
    );
  }

  static Future showNotification(RemoteMessage message) async {
    AndroidNotificationDetails androidDetails = AndroidNotificationDetails(
      "default_notification_channel_id",
      "channel",
      enableLights: true,
      enableVibration: true,
      priority: Priority.high,
      importance: Importance.max,
      largeIcon: DrawableResourceAndroidBitmap("ic_launcher"),
      styleInformation: MediaStyleInformation(
        htmlFormatContent: true,
        htmlFormatTitle: true,
      ),
      playSound: true,
    );

    await _flutterLocalNotificationsPlugin.show(
        message.data.hashCode,
        message.data['title'],
        message.data['body'],
        NotificationDetails(
          android: androidDetails,
        ));
  }
}

main.dart:

Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  await Firebase.initializeApp();
  print('Handling a background message ${message.messageId}');
  print('Notification Message: ${message.data}');
  NotificationService.showNotification(message);
}

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
  runApp(
    MyApp(),
  );
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {

  @override
  void initState() {
    super.initState();
    NotificationService.initialize();
    FirebaseMessaging.onMessage.listen((RemoteMessage message) {
      NotificationService.showNotification(message);
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(...)

One more point to add, when the app is in background (the case where I can receive notification), I get the output of the first 2 print statements i.e. message.messageId and message.data:

I/flutter ( 3363): Handling a background message 0:1637822186109880%5dd28a92f9fd7ecd
I/flutter ( 3363): Notification Message: {body: Price is at Bull! Buy Now!, title: Hello Traders!}

But when the app is in foreground (the case where I do not receive notification), I get the following output: D/FLTFireMsgReceiver( 3363): broadcast received for message

It would really help if someone could help me out, It's been days debugging, finding solution. Thank you!

AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.trading_app">

  <uses-permission android:name="android.permission.VIBRATE"/>
  <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
  <uses-permission android:name="android.permission.INTERNET"/>

   <application
        android:label="TradingApp"
        android:icon="@mipmap/ic_launcher">

        <meta-data
            android:name="com.google.firebase.messaging.default_notification_icon"
            android:resource="@mipmap/ic_launcher" />

        <meta-data         
            android:name="com.google.firebase.messaging.default_notification_channel_id"                 
            android:value="@string/default_notification_channel_id" />

        <receiver android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationBootReceiver">
        <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED"></action>
        </intent-filter>
        </receiver>
        <receiver android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationReceiver" />

        <activity
            android:name=".MainActivity"
            android:launchMode="singleTop"
            android:theme="@style/LaunchTheme"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize">

            <meta-data
              android:name="io.flutter.embedding.android.NormalTheme"
              android:resource="@style/NormalTheme"
              />

            <meta-data
              android:name="io.flutter.embedding.android.SplashScreenDrawable"
              android:resource="@drawable/launch_background"
              />
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>

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


Solution 1:[1]

I dont know if it will work or not for you, but here is my code to show notification when app on foreground. I put messageHandler on initState(). LocalNotification is a custom class, so you can either create a same class, or just put whatever inside showNotification to onMessage

  Future<void> messageHandler() async {
  await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
    alert: true,
    badge: true,
    sound: true,
  );

  FirebaseMessaging.onMessage.listen((RemoteMessage event) {
    LocalNotification.showNotification(event);
  });

}

  static Future<void> showNotification(RemoteMessage payload) async {

    var android = AndroidInitializationSettings('logo_rs');
    var initiallizationSettingsIOS = IOSInitializationSettings();
    var initialSetting = new InitializationSettings(android: android, iOS: initiallizationSettingsIOS);
    final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
    flutterLocalNotificationsPlugin.initialize(initialSetting);



    const AndroidNotificationDetails androidDetails = AndroidNotificationDetails(
        'default_notification_channel_id',
        'Notification',
        'All Notification is Here',
        importance: Importance.max,
        priority: Priority.high,
        ticker: 'ticker',
        icon: "logo_rs",
        playSound: true,
        sound: RawResourceAndroidNotificationSound("notification")
    );
    const iOSDetails = IOSNotificationDetails();
    const NotificationDetails platformChannelSpecifics = NotificationDetails(android: androidDetails, iOS: iOSDetails);

    await flutterLocalNotificationsPlugin.show(0, payload.notification!.title, payload.notification!.body, platformChannelSpecifics);
  }

Add try to put this on your AndroidManifest

   <meta-data  android:name="com.google.firebase.messaging.default_notification_channel_id"
                android:value="@string/default_notification_channel_id" />

String.xml (new file inside res/values)

<?xml version='1.0' encoding='utf-8'?>
<resources>
    <string name="default_notification_channel_id" translatable="false">fcm_default_channel</string>
</resources>

Solution 2:[2]

According to docs,

To listen to messages whilst your application is in the foreground, listen to the onMessage stream.

So, you should print your message id and data there.

In your MyApp initState,

FirebaseMessaging.onMessage.listen((RemoteMessage message) {
  // print foreground message here.
  print('Handling a foreground message ${message.messageId}');
  print('Notification Message: ${message.data}');

  if (message.notification != null) {
    print('Message also contained a notification: ${message.notification}');
  }

  //.. rest of your code
  NotificationService.showNotification(message);
});

Solution 3:[3]

After struggling a lot with this I found the solution. The problem was that I was sending the message the wrong way inside the firebase console. When u are creating the notification inside the firebase console, locate the "Send test message" button (it should be above the images showing u the notification preview).

enter image description here

To send a test message u have to put a token. This token is obtained by code with:

_getDevToken() async{
String? token = await FirebaseMessaging.instance.getToken();
print("DEV TOKEN FIREBASE CLOUD MESSAGING -> $token");
}

Also, remember to put the android channel id in the last step or your background notification won't find the method to be handled. Happy coding y'all!

Solution 4:[4]

Hi I also faced the same issue, firebase messaging was working fine for me . I was using firebase_messaging: ^11.2.8 flutter_local_notifications: ^9.3.2

When I run "flutter pub get" it changed to latest version of both this packages that made the problem. When we use ^ before version number while we adding packages to pubspec.yaml it will automatically update to latest version when update. My solution is - I cleared the cache folder from flutter/bin directory , and I removed ^ from pubspec.yaml package version name.Then run the project.

Solution 5:[5]

Try invoking the code below inside main() right after initialisation code for FlutterLocalNotification

FirebaseMessaging.onMessage.listen((RemoteMessage message) {
    // handle message here
});

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3 Ramiro G.M.
Solution 4 Graycodder
Solution 5 Ercross