Instruction file imported from NarekManukyan/flutter_boilerplate (
.cursor/rules/firebase/firebase_messaging.mdc). Copyright stays with the author.
Firebase Cloud Messaging Rules
Setup and Configuration
- Enable push notifications and background modes in your Xcode project for iOS targets.
- Upload your APNs authentication key to Firebase before using FCM on iOS.
- Do not disable method swizzling on Apple devices, as it's required for FCM token handling.
- Request user permission before FCM payloads can be received on iOS, macOS, web, and Android 13 or newer.
- For iOS, ensure the bundle ID for your APNs certificate matches the bundle ID of your app.
- Install the FCM plugin using
flutter pub add firebase_messaging. - Ensure your Android devices are running Android 4.4 or higher with Google Play services installed.
- Check for Google Play services compatibility in both
onCreate()andonResume()methods for Android.
Message Handling
-
Use
FirebaseMessaging.onMessage.listento handle messages while your application is in the foreground.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}'); } }); -
Use
FirebaseMessaging.onBackgroundMessageto register a handler for background messages.@pragma('vm:entry-point') Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async { // If you're going to use other Firebase services in the background, such as Firestore, // make sure you call `initializeApp` before using other Firebase services. await Firebase.initializeApp(); print("Handling a background message: ${message.messageId}"); } void main() { FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler); runApp(MyApp()); } -
Background message handlers must not be anonymous functions.
-
Background message handlers must be top-level functions, not class methods which require initialization.
-
When using Flutter version 3.3.0 or higher, annotate background message handlers with
@pragma('vm:entry-point')right above the function declaration to prevent removal during tree shaking for release mode. -
Initialize Firebase before using other Firebase services in background message handlers.
-
Background message handlers cannot update application state or execute UI-impacting logic as they run in a separate isolate.
Permissions
-
Use
requestPermission()method to request user permission for receiving notifications.FirebaseMessaging messaging = FirebaseMessaging.instance; NotificationSettings settings = await messaging.requestPermission( alert: true, announcement: false, badge: true, carPlay: false, criticalAlert: false, provisional: false, sound: true, ); print('User granted permission: ${settings.authorizationStatus}'); -
Check the
authorizationStatusproperty of the returnedNotificationSettingsto determine the user's decision. -
For Android versions prior to 13, be aware that
authorizationStatusreturnsauthorizedif the user has not disabled notifications in the OS settings. -
For Android 13 and above, track permission requests in your app as there's no way to determine if the user has chosen to grant/deny permission.
-
Consider using provisional permissions on iOS by setting
provisional: trueto allow users to choose notification types after receiving their first notification.final notificationSettings = await FirebaseMessaging.instance.requestPermission(provisional: true);
Platform-Specific Considerations
- On iOS, if the user swipes away the application from the app switcher, it must be manually reopened for background messages to work again.
- On Android, if the user force-quits the app from device settings, it must be manually reopened for messages to work.
- On web, you must have requested a token using
getToken()with your web push certificate. - For notification messages to display while the app is in the foreground on Android, create a "High Priority" notification channel.
- For notification messages to display while the app is in the foreground on iOS, update the presentation options for the application.
- For web platforms, create and register a service worker file named
firebase-messaging-sw.jsin your web directory:// Please see this file for the latest firebase-js-sdk version: // https://github.com/firebase/flutterfire/blob/main/packages/firebase_core/firebase_core_web/lib/src/firebase_sdk_version.dart importScripts("https://www.gstatic.com/firebasejs/10.7.0/firebase-app-compat.js"); importScripts("https://www.gstatic.com/firebasejs/10.7.0/firebase-messaging-compat.js"); firebase.initializeApp({ apiKey: "...", authDomain: "...", databaseURL: "...", projectId: "...", storageBucket: "...", messagingSenderId: "...", appId: "...", }); const messaging = firebase.messaging(); // Optional: messaging.onBackgroundMessage((message) => { console.log("onBackgroundMessage", message); });
Token Management
- Retrieve the FCM registration token using
getToken()to send messages to specific devices.final fcmToken = await FirebaseMessaging.instance.getToken(); print("FCM Token: $fcmToken"); - For web platforms, provide your VAPID public key when requesting a token.
final fcmToken = await FirebaseMessaging.instance.getToken( vapidKey: "BKagOny0KF_2pCJQ3m....moL0ewzQ8rZu" ); - Subscribe to the
onTokenRefreshstream to be notified when the token is updated.FirebaseMessaging.instance.onTokenRefresh.listen((fcmToken) { // Send token to your application server }).onError((err) { // Handle error }); - For Apple platforms, ensure the APNS token is available before making FCM plugin API calls.
final apnsToken = await FirebaseMessaging.instance.getAPNSToken(); if (apnsToken != null) { // APNS token is available, make FCM plugin API requests }
Auto-Initialization Control
- Disable FCM auto-initialization on iOS by adding metadata to Info.plist.
FirebaseMessagingAutoInitEnabled = NO - Disable FCM auto-initialization on Android by adding metadata to AndroidManifest.xml.
<meta-data android:name="firebase_messaging_auto_init_enabled" android:value="false" /> <meta-data android:name="firebase_analytics_collection_enabled" android:value="false" /> - Re-enable auto-initialization at runtime if needed.
await FirebaseMessaging.instance.setAutoInitEnabled(true); - Be aware that the auto-initialization setting persists across app restarts once set.
iOS Image Notifications
Important: The iOS simulator does not display images in push notifications. You must test on a physical device.
- Add a notification service extension in Xcode for iOS image support.
- Select either Swift or Objective-C when creating the notification service extension.
- For Swift implementations, use the
FirebaseMessagingSwift package by adding it to your target. - For Objective-C implementations, add the Firebase/Messaging pod to your Podfile.
- Configure the notification service extension to use
Messaging.serviceExtension().populateNotificationContent()for image handling.