This guide describes how to get started withFirebase Cloud Messagingin your
Android client apps so that you can reliably send messages.
FCMclients require devices running Android 6.0 or
higher that also have the Google Play Store app installed, or an emulator
running Android 6.0 with Google APIs. Note that you are not
limited to deploying your Android apps through Google Play Store.
A service that extendsFirebaseMessagingService. This is required if you
want to do any message handling beyond receiving notifications on apps in
the background. To receive notifications in foreground apps, to receive
data payload, and more, you must extend this
service.
(Optional) Within the application component, metadata elements to set a default notification
icon and color. Android uses these values whenever incoming
messages don't explicitly set icon or color.
<!-- Set custom default icon. This is used when no icon is set for incoming notification messages.SeeREADME(https://goo.gl/l4GJaQ)formore.-->
<meta-dataandroid:name="com.google.firebase.messaging.default_notification_icon"android:resource="@drawable/ic_stat_ic_notification"/>
<!-- Set color used with incoming notification messages. This is used when no color is set for the incomingnotificationmessage.SeeREADME(https://goo.gl/6BKBk7)formore.-->
<meta-dataandroid:name="com.google.firebase.messaging.default_notification_color"android:resource="@color/colorAccent"/>
(Optional) From Android 8.0 (API level 26) and higher,notification channelsare supported and recommended.FCMprovides a default
notification channel with basic settings. If you prefer tocreateand use your own default channel,
setdefault_notification_channel_idto the ID of your notification channel object
as shown;FCMwill use this
value whenever incoming messages don't explicitly set a notification
channel. To learn more, seeManage notification channels.
Request runtime notification permission on Android 13+
Android 13 introduces a new runtime permission for showing notifications. This
affects all apps running on Android 13 or higher that useFCMnotifications.
By default, theFCMSDK (version 23.0.6 or higher) includes thePOST_NOTIFICATIONSpermission defined in the manifest. However, your app will also need to request
the runtime version of this permission using the constant,android.permission.POST_NOTIFICATIONS. Your app won't be allowed to show
notifications until the user has granted this permission.
To request the new runtime permission:
Kotlin
// Declare the launcher at the top of your Activity/Fragment:privatevalrequestPermissionLauncher=registerForActivityResult(ActivityResultContracts.RequestPermission(),){isGranted:Boolean->if(isGranted){// FCM SDK (and your app) can post notifications.}else{// TODO: Inform user that that your app will not show notifications.}}privatefunaskNotificationPermission(){// This is only necessary for API level >= 33 (TIRAMISU)if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.TIRAMISU){if(ContextCompat.checkSelfPermission(this,Manifest.permission.POST_NOTIFICATIONS)==PackageManager.PERMISSION_GRANTED){// FCM SDK (and your app) can post notifications.}elseif(shouldShowRequestPermissionRationale(Manifest.permission.POST_NOTIFICATIONS)){// TODO: display an educational UI explaining to the user the features that will be enabled// by them granting the POST_NOTIFICATION permission. This UI should provide the user// "OK" and "No thanks" buttons. If the user selects "OK," directly request the permission.// If the user selects "No thanks," allow the user to continue without notifications.}else{// Directly ask for the permissionrequestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)}}}
// Declare the launcher at the top of your Activity/Fragment:privatefinalActivityResultLauncher<String>requestPermissionLauncher=registerForActivityResult(newActivityResultContracts.RequestPermission(),isGranted->{if(isGranted){// FCM SDK (and your app) can post notifications.}else{// TODO: Inform user that that your app will not show notifications.}});privatevoidaskNotificationPermission(){// This is only necessary for API level >= 33 (TIRAMISU)if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.TIRAMISU){if(ContextCompat.checkSelfPermission(this,Manifest.permission.POST_NOTIFICATIONS)==PackageManager.PERMISSION_GRANTED){// FCM SDK (and your app) can post notifications.}elseif(shouldShowRequestPermissionRationale(Manifest.permission.POST_NOTIFICATIONS)){// TODO: display an educational UI explaining to the user the features that will be enabled// by them granting the POST_NOTIFICATION permission. This UI should provide the user// "OK" and "No thanks" buttons. If the user selects "OK," directly request the permission.// If the user selects "No thanks," allow the user to continue without notifications.}else{// Directly ask for the permissionrequestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS);}}}
Generally, you should display a UI explaining to the user the features that will
be enabled if they grant permissions for the app to post notifications. This UI
should provide the user options to agree or deny, such asOKandNo
thanksbuttons. If the user selectsOK, directly request the permission.
If the user selectsNo thanks, allow the user to continue without
notifications.
SeeNotification runtime
permissionfor more best practices on when your app should request thePOST_NOTIFICATIONSpermission from the user.
Notification permissions for apps targeting Android 12L (API level 32) or lower
Android automatically asks the user for permission the first time your app
creates a notification channel, as long as the app is in the foreground.
However, there are important caveats regarding the timing of channel creation
and permission requests:
If your app creates its first notification channel when it is running in the
background, which theFCMSDK does when receiving anFCMnotification, Android won't allow the notification to be displayed and won't
prompt the user for the notification permission until the next time your app
is opened. This means that any notifications received before your app is
opened and the user accepts the permission will be lost.
We strongly recommend that you update your app to target Android 13+ to take
advantage of the platform's APIs to request permission. If that isn't
possible, your app should create notification channels before you send any
notifications to the app in order to trigger the notification permission
dialog and make sure no notifications are lost. Seenotification permission
best
practicesfor more information.
Optional: removePOST_NOTIFICATIONSpermission
By default, theFCMSDK includes thePOST_NOTIFICATIONSpermission.
If your app does not use notification messages (whether throughFCMnotifications, through another SDK, or directly posted by your app) and you
don't want your app to include the permission, you can remove it using themanifest merger'sremovemarker. Keep in mind that removing this permission prevents the display
of all notifications, not justFCMnotifications. Add the following to
your app's manifest file:
On initial startup of your app, theFCMSDK registers the app instance withFCMand returns an identifier for the app instance. If you want to target individual
app instances, you'll need to access this identifier by
extendingFirebaseMessagingServiceand overridingonRegistered().
As a best practice, retrieve the latest updated identifier since the identifier can rotate after the initial startup.
Enable registration via Firebase Installation ID
To enable registering your app instance withFCMusingthe Firebase Installation ID (FID),
add the following metadata flag to yourAndroidManifest.xmlfile:
App instances are targeted using the Firebase Installation ID (FID) once they are registered
withFCM. To retrieve the FID upon registration, implement theonRegistered()callback.
Once an app instance is registered, theFCMSDK
automatically monitors FID changes and invokes the callback when a change is detected.
When auto-initialization is enabled, theFCMSDK
automatically syncs with theFCMbackend to keep the registration fresh and invokes the callback
to ensure your app server has the current identifier. To protect against FID loss or
outdated FIDs, you should send the FID to your app server whenever this callback triggers.
Kotlin
/*** There are three scenarios when `onRegistered` is called:* 1) Every time a manual `register()` call finishes successfully* 2) Whenever the FID is changed and the app is re-registered with FCM via the new FID.* 3) Automatically on app startup or routine sync when auto-initialization is enabled.* Under #2, there are three scenarios when the existing FID is changed:* A) App is restored to a new device* B) User uninstalls/reinstalls the app* C) User clears app data*/overridefunonRegistered(installationId:String){Log.d(TAG,"Registered installation ID:$installationId")// Send the Firebase Installation ID to your app server.sendRegistrationToServer(installationId)}
Java
/*** There are three scenarios when `onRegistered` is called:* 1) Every time a manual `register()` call finishes successfully* 2) Whenever the FID is changed and the app is re-registered with FCM via the new FID* 3) Automatically on app startup or routine sync when auto-initialization is enabled.* Under #2, there are three scenarios when the existing FID is changed:* A) App is restored to a new device* B) User uninstalls/reinstalls the app* C) User clears app data*/@OverridepublicvoidonRegistered(@NonNullStringinstallationId){Log.d(TAG,"Registered installation ID: "+installationId);// Send the Firebase Installation ID to your app server.sendRegistrationToServer(installationId);}
Manually register when auto initialization is disabled
If you must disable auto-initialization, theFCMSDK will not automatically sync or trigger theonRegistered()callback
at startup. It is strongly recommended to re-enable auto initialization after
notification permissions are granted. To learn more, seeRe-enable auto-initialization.
// Trigger manual registration if auto-initialization is turned off.// Consider calling this every time the app starts to guarantee sync status.FirebaseMessaging.getInstance().register().addOnCompleteListener(this){task->if(!task.isSuccessful()){// Registration failed. Consider retrying the registration with exponential backoff.Log.w(TAG,"Failed to register with Firebase Cloud Messaging",task.exception)}// Success! The Firebase Installation ID can be used to target messages to this app// instance and will be delivered asynchronously to your `onRegistered()` callback.}
Java
// Trigger manual registration if auto-initialization is turned off.// Consider calling this every time the app starts to guarantee sync status.FirebaseMessaging.getInstance().register().addOnCompleteListener(task->{if(!task.isSuccessful()){// Registration failed. Consider retrying the registration with exponential backoff.Log.w(TAG,"Failed to register with Firebase Cloud Messaging",task.exception)}// Success! The Firebase Installation ID can be used to target messages to this app// instance and will be delivered asynchronously to your `onRegistered()` callback.});
Access theFCMregistration token (deprecated)
On initial startup of your app, theFCMSDK generates a registration
token for the client app instance. If you want to target single app instances or
create device groups, you'll need to access this token by extendingFirebaseMessagingServiceand overridingonNewToken. Because the
token could be rotated after initial
startup, you are strongly recommended to retrieve the latest updated registration
token.
FirebaseMessaging.getInstance().token.addOnCompleteListener(OnCompleteListener{task->if(!task.isSuccessful){Log.w(TAG,"Fetching FCM registration token failed",task.exception)return@OnCompleteListener}// Get new FCM registration tokenvaltoken=task.result// Log and toastvalmsg=getString(R.string.msg_token_fmt,token)Log.d(TAG,msg)Toast.makeText(baseContext,msg,Toast.LENGTH_SHORT).show()})
Java
FirebaseMessaging.getInstance().getToken().addOnCompleteListener(newOnCompleteListener<String>(){@OverridepublicvoidonComplete(@NonNullTask<String>task){if(!task.isSuccessful()){Log.w(TAG,"Fetching FCM registration token failed",task.getException());return;}// Get new FCM registration tokenStringtoken=task.getResult();// Log and toastStringmsg=getString(R.string.msg_token_fmt,token);Log.d(TAG,msg);Toast.makeText(MainActivity.this,msg,Toast.LENGTH_SHORT).show();}});
Monitor token generation
TheonNewTokencallback fires whenever a new token is generated.
Kotlin
/*** Called if the FCM registration token is updated. This may occur if the security of* the previous token had been compromised. Note that this is called when the* FCM registration token is initially generated so this is where you would retrieve the token.*/overridefunonNewToken(token:String){Log.d(TAG,"Refreshed token:$token")// If you want to send messages to this application instance or// manage this apps subscriptions on the server side, send the// FCM registration token to your app server.sendRegistrationToServer(token)}
/*** There are two scenarios when onNewToken is called:* 1) When a new token is generated on initial app startup* 2) Whenever an existing token is changed* Under #2, there are three scenarios when the existing token is changed:* A) App is restored to a new device* B) User uninstalls/reinstalls the app* C) User clears app data*/@OverridepublicvoidonNewToken(@NonNullStringtoken){Log.d(TAG,"Refreshed token: "+token);// If you want to send messages to this application instance or// manage this apps subscriptions on the server side, send the// FCM registration token to your app server.sendRegistrationToServer(token);}
After you've obtained the token, you can send it to your app server and store
it using your preferred method.
Check for Google Play services
Apps that rely on the Play Services SDK should always check the device for a
compatible Google Play services APK before accessing Google Play services
features. To learn more, seeset up Google Play
services. It is recommended to do
this in two places: in the main activity'sonCreate()method, and in itsonResume()method. The check inonCreate()makes sure that the app can't be
used without a successful check. The check inonResume()makes sure that if
the user returns to the running app through some other means, such as through
the back button, the check is still performed.
When aFCMregistration is generated, the library uploads the
identifier and configuration data to Firebase. If you prefer to prevent auto
registration, disable Analytics collection and FCM auto initialization (you must
disable both) by adding these metadata values to yourAndroidManifest.xml:
Enter the message text. All other fields are optional.
SelectSend test messagefrom the right pane.
In the field labeledAdd an FCM registration token, enter the
registration token you obtained in a previous section of this guide.
SelectTest.
The targeted client device, with the app in the background, should receive the
notification.
For insight into message delivery to your app, go to theDevOps & Engagement>Messaging>Reportsdashboardin theFirebaseconsole. This dashboard records the number of messages sent
and opened on Apple and Android devices, along with data for "impressions"
(notifications seen by users) for Android apps.
Next steps
After you have completed the setup steps, here are a few options for moving
forward withFCMfor Android:
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Missing the information I need","missingTheInformationINeed","thumb-down"],["Too complicated / too many steps","tooComplicatedTooManySteps","thumb-down"],["Out of date","outOfDate","thumb-down"],["Samples / code issue","samplesCodeIssue","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2026-06-30 UTC."],[],[]]