Debug School

rakesh kumar
rakesh kumar

Posted on

How to Show Foreground & Background Notifications in Flutter (Using FlutterLocalNotificationsPlugin + FCM)

Flutter apps do NOT show system notifications by default when using Firebase Messaging.
To display notifications both in foreground and background, you must combine:

✔ FirebaseMessaging
✔ FlutterLocalNotificationsPlugin
✔ Background message handler

Here is the full flow of how your code works.

main() — Initialize Firebase and Register Background Handler
R:\firebase\firebase\lib\main.dart

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await Firebase.initializeApp();

  FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);

  runApp(const MyApp());
}
Enter fullscreen mode Exit fullscreen mode

👉 Simple Explanation

Prepares Flutter for async operations.

Initializes Firebase services.

Registers a background message handler for notifications received when app is killed or minimized.

Launches the Flutter app.

2️⃣ Background Handler — Runs When App Is Closed/Terminated
R:\firebase\firebase\lib\main.dart

@pragma('vm:entry-point')
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  await Firebase.initializeApp();
  print(message.notification!.title.toString());
}
Enter fullscreen mode Exit fullscreen mode

👉 Simple Explanation

Called when notification arrives while app is closed/background.

Must be a top-level function.

Initializes Firebase inside the background isolate.

You can trigger local notification from here too (if needed).

3️⃣ initState() — Setup Permission, Token, Listeners, and Local Notification System
R:\firebase\firebase\lib\home_screen.dart

@override
void initState() {
  super.initState();

  _notificationServices.requestNotificationPermission();
  _notificationServices.listenToTokenRefresh();

  _notificationServices.getDeviceToken().then((value) { print(value); });

  _notificationServices.initLocalNotifications();   // VERY IMPORTANT
  _notificationServices.firebaseInit();
  _notificationServices.handleNotificationClick(context);
}
Enter fullscreen mode Exit fullscreen mode

👉 Simple Explanation
R:\firebase\firebase\lib\notification_services.dart


initLocalNotifications() — Setup Plugin + Notification Channel
void initLocalNotifications() async {
  const AndroidInitializationSettings androidInitializationSettings =
      AndroidInitializationSettings('@mipmap/ic_launcher');

  const DarwinInitializationSettings iosInitializationSettings =
      DarwinInitializationSettings();

  const InitializationSettings initializationSettings = InitializationSettings(
    android: androidInitializationSettings,
    iOS: iosInitializationSettings,
  );

  await _flutterLocalNotificationsPlugin.initialize(
    initializationSettings,
    onDidReceiveNotificationResponse: (response) {},
  );

  const AndroidNotificationChannel channel = AndroidNotificationChannel(
    'high_importance_channel_v2',
    'High Importance Notifications',
    description: 'Channel for important notifications',
    importance: Importance.max,
  );

  await _flutterLocalNotificationsPlugin
      .resolvePlatformSpecificImplementation<
          AndroidFlutterLocalNotificationsPlugin>()
      ?.createNotificationChannel(channel);
}
Enter fullscreen mode Exit fullscreen mode

👉 Simple Explanation


R:\firebase\firebase\lib\notification_services.dart

firebaseInit() — Listen for Foreground Notifications
void firebaseInit() {
  FirebaseMessaging.onMessage.listen((message) {
    print(message.notification!.title.toString());
    print(message.notification!.body.toString());

    showNotification(message);
  });
}
Enter fullscreen mode Exit fullscreen mode

👉 Simple Explanation

Runs when the app is open

Firebase receives notification

Immediately calls showNotification() to show system-level notification

Because FCM does NOT show foreground notifications automatically

6️⃣ showNotification() — Show System Notification
R:\firebase\firebase\lib\notification_services.dart

Future<void> showNotification(RemoteMessage message) async {
  const AndroidNotificationDetails androidNotificationDetails =
      AndroidNotificationDetails(
    'high_importance_channel',
    'High Importance Notifications',
    channelDescription: 'Channel for important notifications',
    importance: Importance.high,
    priority: Priority.high,
    icon: '@mipmap/ic_launcher',
  );

  const DarwinNotificationDetails darwinNotificationDetails =
      DarwinNotificationDetails(
    presentAlert: true,
    presentBadge: true,
    presentSound: true,
  );

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

  await _flutterLocalNotificationsPlugin.show(
    0,
    message.notification?.title ?? 'Notification',
    message.notification?.body ?? '',
    notificationDetails,
  );
}
Enter fullscreen mode Exit fullscreen mode

👉 Simple Explanation

Top comments (0)