image

07 Dec 2025

9K

35K

Integrating Firebase Cloud Messaging in Flutter

Firebase Cloud Messaging (FCM) is a cross-platform messaging solution that lets you reliably send messages at no cost. Using FCM, you can notify a client app that new data is available to sync, send instant messages, or deliver promotional offers. Integrating FCM into a Flutter application allows developers to send push notifications to users across Android and iOS platforms seamlessly. This article will guide you through the process of integrating FCM into your Flutter project.

Prerequisites

  • A Flutter project set up and ready.
  • A Firebase project created in the Firebase Console.
  • Basic understanding of Flutter and Dart.

Firebase Project Setup

1. Create a Firebase Project

If you don't already have one, go to the Firebase Console and create a new project. Follow the on-screen instructions.

2. Register Your Android App

  • In your Firebase project, click on the Android icon to add an Android app.
  • Enter your Android package name (found in `android/app/build.gradle` under `applicationId`).
  • Provide an App nickname (optional).
  • (Optional) Provide a SHA-1 signing certificate. This is required for Google Sign-In and Dynamic Links but not strictly for FCM.
  • Download the `google-services.json` file. Place this file into your Flutter project's `android/app` directory.
  • Follow the console instructions to add the Firebase SDK.

Update your `android/build.gradle` (project level) with:


buildscript {
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:7.3.0' // Use your current Android Gradle Plugin version
        classpath 'com.google.gms:google-services:4.3.15' // Use the latest google-services plugin version
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.10" // Use your current Kotlin version
    }
}

allprojects {
    repositories {
        google()
        mavenCentral()
    }
}

Update your `android/app/build.gradle` (app level) by adding these lines:


apply plugin: 'com.android.application'
apply plugin: 'com.google.gms.google-services' // Add this line
apply plugin: 'kotlin-android'

android {
    // ...
}

dependencies {
    // ...
}

3. Register Your iOS App

  • In your Firebase project, click on the iOS icon to add an iOS app.
  • Enter your iOS bundle ID (found in Xcode under General > Identity > Bundle Identifier).
  • Provide an App nickname (optional).
  • Download the `GoogleService-Info.plist` file.
  • Open your Flutter project in Xcode (Runner.xcworkspace). Drag and drop the `GoogleService-Info.plist` file into the `Runner` folder in Xcode. Ensure "Copy items if needed" is checked.
  • Enable Push Notifications and Background Modes (Remote notifications) in Xcode under your target's "Signing & Capabilities" tab.

Flutter Project Setup

1. Add Dependencies

Open your `pubspec.yaml` file and add the `firebase_core` and `firebase_messaging` packages:


dependencies:
  flutter:
    sdk: flutter
  firebase_core: ^2.24.2 # Use the latest version
  firebase_messaging: ^14.7.10 # Use the latest version

Run `flutter pub get` to fetch the packages.

2. Initialize Firebase

Before using any Firebase services, you need to initialize Firebase in your `main()` function. It's recommended to do this asynchronously and ensure widgets are initialized.


import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'FCM Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

  @override
  State createState() => _MyHomePageState();
}

class _MyHomePageState extends State {
  String _message = 'Waiting for messages...';

  @override
  void initState() {
    super.initState();
    // Initialize FCM listeners here
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Firebase Cloud Messaging'),
      ),
      body: Center(
        child: Text(_message),
      ),
    );
  }
}

Implementing FCM in Flutter

1. Requesting Permissions (iOS & Web)

For iOS and Web platforms, you need to explicitly request user permission to display notifications. Android handles this automatically.


final messaging = FirebaseMessaging.instance;

NotificationSettings settings = await messaging.requestPermission(
  alert: true,
  announcement: false,
  badge: true,
  carPlay: false,
  criticalAlert: false,
  provisional: false,
  sound: true,
);

if (settings.authorizationStatus == AuthorizationStatus.authorized) {
  print('User granted permission');
} else if (settings.authorizationStatus == AuthorizationStatus.provisional) {
  print('User granted provisional permission');
} else {
  print('User declined or has not accepted permission');
}

2. Getting the Device Token

The FCM device token is a unique identifier for each device that your app runs on. You'll need this token to send targeted messages.


String? token = await messaging.getToken();
print("FCM Token: $token");

// Listen for token refresh events
messaging.onTokenRefresh.listen((newToken) {
  print("FCM Token refreshed: $newToken");
  // If you save tokens to a backend, update it here.
});

3. Handling Foreground Messages

Messages received when the app is in the foreground (open and in use) are handled by `onMessage.listen()`. These messages won't typically show a notification automatically unless explicitly built by your app.


FirebaseMessaging.onMessage.listen((RemoteMessage message) {
  print('Got a message whilst in the foreground!');
  print('Message data: ${message.data}');

  if (message.notification != null) {
    print('Message also contained a notification: ${message.notification!.title} / ${message.notification!.body}');
    setState(() {
      _message = 'Foreground message: ${message.notification!.body}';
    });
  }
});

4. Handling Background and Terminated Messages

Messages received when the app is in the background or terminated require a top-level `_firebaseMessagingBackgroundHandler` function. This function runs in an isolated scope and must be registered once.


import 'package:firebase_messaging/firebase_messaging.dart';

// Must be a top-level function
@pragma('vm:entry-point')
Future _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  await Firebase.initializeApp(); // Initialize Firebase again for background isolate
  print("Handling a background message: ${message.messageId}");
  // You can process the message data here
  // For example, update local storage or show a local notification
}

class _MyHomePageState extends State {
  // ...
  @override
  void initState() {
    super.initState();
    FirebaseMessaging.instance.getInitialMessage().then((RemoteMessage? message) {
      if (message != null) {
        print('App launched from terminated state by a message: ${message.notification?.body}');
        setState(() {
          _message = 'Terminated message: ${message.notification?.body}';
        });
      }
    });

    FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
      print('App opened from background by a message: ${message.notification?.body}');
      setState(() {
        _message = 'Background message: ${message.notification?.body}';
      });
      // Navigate to a specific screen based on message.data if needed
    });

    // Register the background message handler
    FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);

    // Call permission request and token retrieval logic here
    _initializeFCM();
  }

  Future _initializeFCM() async {
    // Request permissions
    // Get token
    // Listen for foreground messages
    // (Existing code for these)
  }
  // ...
}

Note: For iOS, to enable background message handling, ensure the 'Background processing' capability is enabled in Xcode and add the `FirebaseAppDelegateProxyEnabled` flag to your `Info.plist` and set it to `NO` if you're not using method swizzling.

5. Subscribing to Topics

FCM allows you to send messages to devices that have subscribed to a particular topic. This is useful for sending broadcast messages to user segments.


await FirebaseMessaging.instance.subscribeToTopic('weather');
print('Subscribed to weather topic');

// To unsubscribe:
// await FirebaseMessaging.instance.unsubscribeFromTopic('weather');

Sending Test Messages

1. Using the Firebase Console

Go to your Firebase project, navigate to "Cloud Messaging" from the left menu. Click "Send your first message". You can compose a notification message and send it to specific tokens or topics.

2. Using a REST API

You can also send messages programmatically using the FCM HTTP v1 API. You'll need your server key (from Project settings > Cloud Messaging) or an access token for service account authentication.


// Example payload for sending a message to a topic via HTTP POST to
// https://fcm.googleapis.com/v1/projects//messages:send
// with Authorization: Bearer 
{
  "message": {
    "topic": "weather",
    "notification": {
      "title": "Weather Update!",
      "body": "There's a storm coming to your area. Stay safe!"
    },
    "data": {
      "route": "/weather-alerts",
      "alert_type": "severe"
    }
  }
}

Conclusion

Integrating Firebase Cloud Messaging into your Flutter application provides a robust and scalable solution for sending push notifications across Android and iOS. By following these steps, you can set up Firebase, handle various message states (foreground, background, terminated), and leverage features like topic-based messaging. This enables powerful user engagement strategies, from critical alerts to promotional content, directly within your mobile app.

Related Articles

Dec 19, 2025

Flutter & Firebase Auth: Seamless Social Media Login

Flutter & Firebase Auth: Seamless Social Media Login In today's digital landscape, user authentication is a critical component of almost every application. Pro

Dec 19, 2025

Building a Widget List with Sticky

Building a Widget List with Sticky Header in Flutter Creating dynamic and engaging user interfaces is crucial for modern applications. One common UI pattern th

Dec 19, 2025

Mastering Transform Scale & Rotate Animations in Flutter

Mastering Transform Scale & Rotate Animations in Flutter Flutter's powerful animation framework allows developers to create visually stunning and highly intera