How to implement Firebase Cloud Messaging (FCM) in Flutter (Android & iOS)

May 12, 2025

How to implement Firebase Cloud Messaging (FCM) in Flutter (Android & iOS)
Code

Watch here, and make sure to follow our amazing developer Bohdan Samusko on YouTube:

This video is a comprehensive tutorial on how to implement Firebase Cloud Messaging (FCM) in a Flutter application for both Android and iOS, covering foreground and background/terminated states.

‍

‍

Summary of the tutorial

‍

This is a comprehensive tutorial on how to implement Firebase Cloud Messaging (FCM) in a Flutter application for both Android and iOS, covering foreground and background/terminated states.

Here's a breakdown of the key steps (please note that the file names would make more sense when you watch the video, as the code is visible there):

  1. Firebase Project Setup:
    • Create a new Firebase project (e.g., "Push notifications sample").
    • Disable optional features like Gemini and Google Analytics for simplicity.
      ‍
  2. Flutter Project Setup & Dependencies:
    • Add necessary Flutter plugins to pubspec.yaml:
      • firebase_core: For initializing Firebase.
      • firebase_messaging: For handling FCM.
      • flutter_local_notifications: For displaying notifications when the app is in the foreground (as FCM doesn't auto-display them in this state).
        ‍
  3. Firebase CLI & FlutterFire Configuration:
    • Ensure Firebase CLI is installed and logged in (firebase login).
    • Activate FlutterFire CLI (dart pub global activate flutterfire_cli).
    • Run flutterfire configure to link the Flutter app with the Firebase project, selecting Android and iOS platforms. This generates firebase_options.dart and platform-specific configuration files (GoogleService-Info.plist for iOS, google-services.json for Android).
      ‍
  4. iOS APNs (Apple Push Notification service) Configuration:
    • Go to the Apple Developer account.
    • Navigate to "Certificates, Identifiers & Profiles" -> "Keys".
    • Create a new APNs key, enabling "Apple Push Notifications service (APNs)".
    • Name the key (e.g., "Test APNs key") and configure it for "Sandbox & Production".
    • Download the generated .p8 key file.
    • Go back to the Firebase console -> Project Settings -> Cloud Messaging.
    • Under "Apple app configuration", upload the downloaded .p8 key file.
    • Provide the Key ID and Team ID (obtained from the Apple Developer account).
      ‍
  5. iOS Xcode Project Configuration:
    • Open the iOS module of the Flutter project in Xcode (ios/Runner.xcworkspace).
    • Select the "Runner" target, then "Signing & Capabilities".
    • Add the "Push Notifications" capability.
    • Addsthe "Background Modes" capability and enables "Remote notifications" within it.
    • Crucially, for flutter_local_notifications on iOS: Modify AppDelegate.swift to import flutter_local_notifications and add specific code to didFinishLaunchingWithOptions to ensure iOS handles foreground notifications correctly by passing events to the Flutter plugin.
      ‍
  6. Flutter Code Implementation:
    • local_notifications_service.dart:
      • Creates a service class (singleton pattern).
      • Initializes FlutterLocalNotificationsPlugin.
      • Sets up Android (AndroidInitializationSettings with a default icon like @mipmap/ic_launcher) and iOS (DarwinInitializationSettings requesting permissions for alert, badge, sound).
      • Creates an init() method to initialize the plugin with platform settings and set up an onDidReceiveNotificationResponse callback.
      • Creates an Android notification channel (AndroidNotificationChannel).
      • Creates a showNotification() method to display local notifications using the plugin.
        ‍
    • firebase_messaging_service.dart:
      • Creates a service class (singleton pattern).
      • Creates an init() method that:
        • Takes an instance of LocalNotificationsService.
        • Handles retrieving and printing the FCM token (FirebaseMessaging.instance.getToken()).
        • Listens for token refresh events (FirebaseMessaging.instance.onTokenRefresh).
        • Requests notification permissions for iOS (FirebaseMessaging.instance.requestPermission()).
        • Sets up a background message handler (FirebaseMessaging.onBackgroundMessage) which must be a top-level or static function.
        • Listens for foreground messages (FirebaseMessaging.onMessage.listen) and uses the LocalNotificationsService to display them.
        • Listens for messages that opened the app (FirebaseMessaging.onMessageOpenedApp.listen).
        • Checks for an initial message that opened the app from a terminated state (FirebaseMessaging.instance.getInitialMessage()).
          ‍
    • main.dart:
      • Makes main asynchronous.
      • Ensures WidgetsFlutterBinding.ensureInitialized().
      • Initializes Firebase (await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform)).
      • Initializes LocalNotificationsService and FirebaseMessagingService.
        ‍
  7. Testing Notifications:
    • Run the app on an iOS simulator (and implicitly Android would work similarly).
    • Allow notification permissions when prompted.
    • Copy the FCM token printed in the debug console.
    • Go to Firebase Console -> Messaging -> "Create your first campaign" -> "Firebase Notification messages".
    • Compose a notification (e.g., "Firebase Messaging", "Hello from Firebase!").
    • Click "Send test message", paste the FCM token, and send.
    • Foreground Test: The notification appears, handled by flutter_local_notifications.
    • Close the app (send it to background/terminate it).
    • Modify the notification title in Firebase (e.g., "Firebase Messaging Background").
    • Send another test message.
    • Background Test: The notification appears as a system notification. Tapping it opens the app.

‍

Profile photo for Bohdan Samusko
Bohdan Samusko

Let's have a coffee β˜•οΈ

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.