FCMDebug logoFCMDebug

FCM with Flutter

Complete guide to sending and receiving FCM push notifications in Flutter apps.

Setup

1. Install the Plugin

From the root of your Flutter project, run:

bash
flutter pub add firebase_messaging

If you haven't already, also add firebase_core and run flutterfire configure to generate your Firebase config:

bash
flutter pub add firebase_core
dart pub global activate flutterfire_cli
flutterfire configure

This generates a firebase_options.dart file with your project config. On Android it also adds google-services.json, and on iOS it adds GoogleService-Info.plist.

2. Initialize Firebase

dart
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'firebase_options.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );
  runApp(MyApp());
}

3. Get the Device Token

dart
final messaging = FirebaseMessaging.instance;

// Request permission (required on iOS, Android 13+)
final settings = await messaging.requestPermission(
  provisional: true, // lets user choose notification type on first receive
);

// On iOS, ensure APNs token is available before getting FCM token
final apnsToken = await messaging.getAPNSToken();
if (apnsToken != null || !Platform.isIOS) {
  final token = await messaging.getToken();
  print('FCM Token: $token');
}

iOS note: In iOS SDK 10.4.0+, the APNs token must be available before making FCM API requests. Always check getAPNSToken() before calling getToken() on iOS.

4. Handle Foreground Messages

dart
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
  print('Got a message in foreground!');
  print('Title: ${message.notification?.title}');
  print('Body: ${message.notification?.body}');
  print('Data: ${message.data}');
});

5. Handle Background Messages

dart
// This must be a top-level function
@pragma('vm:entry-point')
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  await Firebase.initializeApp();
  print('Background message: ${message.messageId}');
}

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

Listen for Token Refresh

FCM tokens can change. Subscribe to the refresh stream to keep your server in sync:

dart
FirebaseMessaging.instance.onTokenRefresh.listen((newToken) {
  // Send the new token to your server
  print('Token refreshed: $newToken');
});

Topic Subscription

dart
// Subscribe
await FirebaseMessaging.instance.subscribeToTopic('news');

// Unsubscribe
await FirebaseMessaging.instance.unsubscribeFromTopic('news');

Testing Your Setup

  1. Copy your device token from the debug console
  2. Go to the FCM Tester
  3. Paste your service account JSON
  4. Select "Device Token" and paste the token
  5. Send a test notification

Common Issues

IssueFix
Token is nullEnsure Firebase is initialized and permissions are granted. On iOS, check that the APNs token is available first
No notification in foregroundForeground messages don't show automatically — use a local notification plugin
Background handler not firingMake sure the handler is a top-level function with @pragma('vm:entry-point')
iOS not receivingCheck APNs key is uploaded in Firebase Console, and that flutterfire configure was run
Android 13+ not receivingRequest POST_NOTIFICATIONS permission — on Android 13+ it's required at runtime
Hot reload doesn't apply plugin changesNative plugin changes require a full rebuild (flutter run)

Related

Was this page helpful?