Firebase Cloud Messaging Setup
Firebase Cloud Messaging Setup
Firebase Cloud Messaging (FCM) is Google's free, cross-platform messaging solution that lets you reliably send notifications and data messages to Android, iOS, and web applications. In Flutter, the firebase_messaging package wraps the native FCM SDKs and exposes a unified Dart API. Before your app can receive a single push notification, you must complete three prerequisites: register the app in the Firebase Console, download the platform-specific configuration file, and add the correct Dart and native dependencies.
Step 1 — Create a Firebase Project
Navigate to console.firebase.google.com and sign in with a Google account. Click Add project, give it a meaningful name (e.g. my-flutter-app), optionally enable Google Analytics, and click Create project. Once provisioned, you land on the project dashboard where you can register individual platform apps.
Step 2 — Register Your Android App
On the project dashboard click the Android icon. You will be asked for the Android package name — this must match the applicationId inside android/app/build.gradle exactly (e.g. com.example.myflutterapp). After submitting, Firebase generates a google-services.json file. Download it and place it inside your Flutter project at:
android/app/google-services.json
Next, apply the Google Services Gradle plugin. Open android/build.gradle (project-level) and add the classpath dependency, then open android/app/build.gradle (app-level) and apply the plugin:
android/build.gradle (project-level)
buildscript {
dependencies {
// Add this line
classpath 'com.google.gms:google-services:4.4.1'
}
}
android/app/build.gradle (app-level) — bottom of file
// Apply the Google Services plugin LAST
apply plugin: 'com.google.gms.google-services'
google-services.json file must sit inside android/app/, not the project root or any other folder. Placing it in the wrong directory causes a Gradle build error that can be confusing to diagnose.Step 3 — Register Your iOS App
Back on the Firebase dashboard click the iOS icon. Enter the iOS bundle ID — this must match the value in ios/Runner.xcodeproj/project.pbxproj (e.g. com.example.myFlutterApp). Firebase generates a GoogleService-Info.plist file. Download it and add it to the project using Xcode (not just the Finder) to ensure it is included in the build target:
- Open
ios/Runner.xcworkspacein Xcode. - Right-click the Runner folder in the project navigator.
- Select Add Files to "Runner" and choose
GoogleService-Info.plist. - Ensure Copy items if needed is checked and the Runner target is selected.
Step 4 — Add the firebase_messaging Package
With the native config files in place, install the Dart packages. Run the following commands from your Flutter project root:
# Add the FlutterFire core plugin and the messaging plugin
flutter pub add firebase_core
flutter pub add firebase_messaging
This updates pubspec.yaml and fetches the packages. Alternatively, you can add them manually to pubspec.yaml:
pubspec.yaml
dependencies:
flutter:
sdk: flutter
firebase_core: ^3.6.0
firebase_messaging: ^15.1.3
firebase_core package is mandatory — it initialises the Firebase App singleton that all other FlutterFire plugins depend on.Step 5 — Initialise Firebase in main.dart
Firebase must be initialised before any other Firebase service is used. The entry point is main(). Because initialisation is asynchronous you must make main() an async function and await the result before calling runApp():
lib/main.dart
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
// Top-level background message handler (must be top-level, not a method)
@pragma('vm:entry-point')
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
// Firebase must be re-initialised in the background isolate
await Firebase.initializeApp();
print('Background message received: ${message.messageId}');
}
Future<void> main() async {
// Ensure Flutter binding is ready before calling native code
WidgetsFlutterBinding.ensureInitialized();
// Initialise Firebase
await Firebase.initializeApp();
// Register the background message handler
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
runApp(const MyApp());
}
@pragma('vm:entry-point'). Flutter runs background messages in a separate Dart isolate; instance methods and closures from the main isolate are not accessible there.Step 6 — Request Notification Permissions (iOS & Web)
On Android 13+ and all iOS versions, you must explicitly request permission before displaying notifications. The FirebaseMessaging instance exposes a requestPermission() method:
Requesting Permission
Future<void> requestNotificationPermissions() async {
final messaging = FirebaseMessaging.instance;
final 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 notification permission');
} else if (settings.authorizationStatus == AuthorizationStatus.provisional) {
print('User granted provisional permission');
} else {
print('User declined or has not accepted permission');
}
}
Summary
To set up FCM in a Flutter project you must: (1) create a Firebase project in the console, (2) register each platform app and download the config file (google-services.json for Android, GoogleService-Info.plist for iOS), (3) apply the Google Services Gradle plugin for Android and add the plist via Xcode for iOS, (4) add firebase_core and firebase_messaging to pubspec.yaml, (5) initialise Firebase before runApp(), and (6) register a top-level background message handler. Once this scaffold is in place, your app is ready to receive and respond to push notifications.
dart pub global activate flutterfire_cli then flutterfire configure) to automate steps 1–3. It registers the app in Firebase and writes a firebase_options.dart file containing all platform credentials — eliminating manual copy-paste errors.