Hello my fellow friend, now I want to share to you guys about implementing the Firebase Cloud Messaging from the Back End to the Android side based on my experience, and also the guide to handle the fcm push notification if the device is in foreground and background, also the proper way to make a deep link from the notification into the android app
but before we dive in to the implementation, it’s a good to know about what is fcm
What is FCM
Firebase Cloud Messaging (FCM) is a cross-platform messaging solution that lets you reliably send messages at no cost. It uses push notification to the end user through the API. you can see the image below to know how the fcm work
We can see the Mobile app will send the fcm token to the Backend and save it in server storage (usually Database), then if the Backend want to send a push notification to the mobile, it will send the request with the token to the fcm and then fcm will send the push notification to the mobile app based on the device app token from the backend.
And also because fcm use push notification, fcm will only connect to the mobile if there is a push notification, so it will not drain the mobile device battery.
You can also check this link to learn more about the fcm architecture.
What will we create
To make the learning easier we will create a movie app that will receive a notification when the Backend script is run.
When we click the notification weather the device is in foreground or background, it will navigate it to the desire page using deeplink and when we press back pressed, we will not close the app, but back to the main screen



You can see this project Movie App, and checkout the branch of hilt_notification for the full code, so now let’s start!
Step - step how to implement FCM in Android and Backend
1. Register your app to firebase
First thing to do is create a firebase account, and then create the firebase project, you can create it here https://firebase.google.com/ and goto console then add the project.
2. Connect your app with firebase
Second you have to connect your app with firebase. You can easily connect your app to firebase with Android Studio Tools tab on the Android studio menu bar, then choose firebase, after that choose the Cloud Messaging
(Tools tab → firebase)

After that choose the `Set up Firebase Cloud Messaging` if you want the java code, or choose the `Set up Firebase Cloud Messaging (KOTLIN)` if you want to use kotlin code. After that we will follow the step - step that android studio will show
3. Connect to FCM & Add Dependencies (Step 1 and 2)

The first step is Connect your app to firebase, it will add the google-service.json
in your app, which means that your app now connects with your firebase account.
The second step is Add FCM to your app, it will add fcm dependencies to your app, you can see on the app gradle dependency now it has
com.google.firebase:firebase-messaging-ktx:app_version
And for the next step after those two step, you can start follow this article, it will be the same as what the next step does but with more information
4. Add FirebaseMessagingService
Next we will create a class that extends the FirebaseMessagingService class, it’s a service from fcm sdk for managing the callback from the firebase server
The full code will be like this
class FirebaseMessagingService : FirebaseMessagingService() {override fun onMessageReceived(remoteMessage: RemoteMessage) {// Not getting messages here? See why this may be: https://goo.gl/39bRNJLog.d(TAG, "From: ${remoteMessage.from}")val title = remoteMessage.notification?.title ?: ""val body = remoteMessage.notification?.body ?: ""val data = remoteMessage.data/*** the isUserLogin code is to avoid notifying the user if he already logout* you can get the user is login based from your app flow,* it could be from sharedPreference, database, api, or other data source* */val isUserLogin = trueif(isUserLogin){sendNotification(title = title, description = body, data = data)}}/*** 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.*/override fun onNewToken(token: String) {Log.d(TAG, "Refreshed token: $token")}private fun sendNotification(title: String, description: String, data: MutableMap<String, String>) {val intent = Intent(this, MainActivity::class.java)intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)val daa = data["fcm_navigation_extra"] ?: ""intent.putExtra(FcmUtil.extraName, daa)val pendingIntent = PendingIntent.getActivity(this,FcmUtil.NotificationActivityData.requestCode,intent,PendingIntent.FLAG_IMMUTABLE,)val defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)val notificationBuilder = NotificationCompat.Builder(this,FcmUtil.NotificationActivityData.channelId).setContentTitle(title).setContentText(description).setDefaults(Notification.DEFAULT_SOUND or Notification.DEFAULT_VIBRATE) //Important for heads-up notification.setPriority(Notification.PRIORITY_HIGH) //Important for heads-up notification.setAutoCancel(true).setSmallIcon(getNotificationIcon()).setSound(defaultSoundUri).setContentIntent(pendingIntent).setColor(ContextCompat.getColor(this@FirebaseMessagingService, R.color.black))val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager// Since android Oreo notification channel is needed.if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {val channel = NotificationChannel(FcmUtil.NotificationActivityData.channelId,"notification_activity",NotificationManager.IMPORTANCE_HIGH //Important for heads-up notification)channel.enableVibration(true)notificationManager.createNotificationChannel(channel)}notificationManager.notify(FcmUtil.NotificationActivityData.notificationId,notificationBuilder.build())}private fun getNotificationIcon(): Int = R.drawable.menu_notification_24companion object {private const val TAG = "MyFirebaseMsgService"}}
The code above contains
- onMessageReceived → it’s the callback that will be triggered if the service is receiving a message from the firebase server.
- onNewToken → it’s the callback if the token is created for it’s device, and we should keep it in our server to know the device app token
- sendNotification → it’s for creating heads up notification
5. Android 13 and above notification permission
For the Android 13 and above, there is new notification permission, so make sure to ask the permission, for the detail code you can see here
object PermissionUtil {private fun AppCompatActivity.requestPermissionLauncher(isNeedEducateMessage: Boolean,onSuccess:() -> Unit,onNeedGrantPermission:() -> Unit,onNeedEducationMessage: () -> Unit): ActivityResultLauncher<String> {return registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted: Boolean ->if (isGranted) {onSuccess.invoke()} else {if(!isNeedEducateMessage){onNeedGrantPermission.invoke()} else {onNeedEducationMessage.invoke()}}}}fun AppCompatActivity.askNotificationPermission(onSuccess:() -> Unit,onNeedGrantPermission:() -> Unit,onNeedEducationMessage:() -> Unit) {// This is only necessary for API level >= 33 (TIRAMISU)if (Build.VERSION.SDK_INT >= 33) {if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) ==PackageManager.PERMISSION_GRANTED) {// FCM SDK (and your app) can post notifications.} else {// Directly ask for the permissionrequestPermissionLauncher(isNeedEducateMessage =shouldShowRequestPermissionRationale(Manifest.permission.POST_NOTIFICATIONS),onSuccess = {onSuccess.invoke()},onNeedGrantPermission = {onNeedGrantPermission.invoke()},onNeedEducationMessage = {onNeedEducationMessage.invoke()}).launch(Manifest.permission.POST_NOTIFICATIONS)}}}}
And then you can directly ask for the permission in your decided Activity / Fragment like this.
askNotificationPermission(onSuccess = {},onNeedGrantPermission = {Toast.makeText(this@MainActivity,"permission is needed for receiving the notification",Toast.LENGTH_SHORT).show()},onNeedEducationMessage = {Toast.makeText(this@MainActivity,"you can active the notification from setting",Toast.LENGTH_SHORT).show()})
don’t forget to add the permission in the manifest file
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
And now if we run the app and allow the permission, we can receive the notification, great!
6. Receive the Firebase Token and give it to the Backend
We will receive the token from the firebase as it will represent our device app ID, it will called if the app on your phone dont have fcm token, or if the app on your phone fcm token has compromised, so make sure to place this code on the right place, because we will always need this callback to update the Device App fcm token
Device App Token is the token of the app based on the phone, so for different phone will have different Token, and different app that use fcm in that device will have different token also
FirebaseMessaging.getInstance().token.addOnCompleteListener(OnCompleteListener { task ->if (!task.isSuccessful) {Log.e(TAG, "Fetching FCM registration token failed ${task.exception}")return@OnCompleteListener}/*** Get new FCM registration token**/val token = task.resultLog.e(TAG, "fcm token: $token", )/*** insert / update firebase token,* it should in the same row with your unique identity* in this example it's username, because we will* send the notification based on it username**/val username = "test-user"viewModel.updateFcmToken(uname = username,token = token,)})
7. Create a Backend script to push the notification
After all of the Android part, now we move on to the Backend side, in this code I will be using python3, you may use any backend language you prefer.
But before that, first we need the credential for connecting our project with our firebase account, you can find it in the firebase project console and generate the key. You can find it in firebase on the Project Setting → Service Account → Firebase Admin SDK, and then download the credential by pressing the Generate new private key

After download the credential, you can import it to your Backend script
Now back to the Python code, here I use the Firebase Admin lib, you can download it via pip (for python) or your language package manager
import firebase_adminfrom firebase_admin import credentials, messagingfirebase_cred = credentials.Certificate('/Users/User/yourappcredential.json')firebase_app = firebase_admin.initialize_app(firebase_cred)message = messaging.Message(notification=messaging.Notification(title='New Movie is Arrived!',body='New movie is arrived, please check it here!',),android=messaging.AndroidConfig(priority='high',notification=messaging.AndroidNotification(click_action='FIREBASE_NOTIFICATION_CLICK'),),data = {'fcm_navigation_extra': 'http://movie_app_notification'},token='the_token_from_firebase',)response = messaging.send(message)print(response)
We can see here, there is
1. notification object
the notification object is use to set the title and body that will appear in the notification
2. android object
The android object is for configure the notification, the priority high is for triggering the heads up notification, and the click_action is for notification pending intent when the app in the background
3. data object
The data object will be the extras in the pending intent, it contain deep link that the app will navigate after going to the click_action activity, or you can also add some data there and get it in mobile as extra
4. Token
Token is the fcm device token that we get from the android, it use to send the push notification to the decided token
Foreground notification and background notification
In the previous paragraph I have mention several time about foreground and background notification behavior, so let’s see how we will handle the navigation from both case because it will be different, but before we dive in, we should also put the decided activity a deep link url in the manifest same as the what it’s on the backend
data android:host=“movie_app_notification”
<activity android:exported="true" android:name="com.programmergabut.movieapp.feature.notification.NotificationActivity"android:fitsSystemWindows="true"><intent-filter><action android:name="android.intent.action.VIEW" /><category android:name="android.intent.category.DEFAULT" /><category android:name="android.intent.category.BROWSABLE" /><data android:scheme="http" /><data android:scheme="https" /><data android:host="movie_app_notification" /></intent-filter></activity>
After that we can continue see how to handle the foreground and background notification
1. Foreground notification
In the Foreground notification, the notification is called on the onMessageReceive and we will send a notification with a pending intent to the MainActivity. In the MainActivity, we should implement the onNewIntent because the pending intent will be called there when the MainActivity started, and we can do intent to our desire activity with the deeplink that we send from the Backend and get it as a data object in the onMessageReceive
Pending Intent
the fcm_navigation_extra
is based on the Message object data in the Backend script
val intent = Intent(this, MainActivity::class.java)intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)val fcmData = data["fcm_navigation_extra"] ?: ""intent.putExtra(FcmUtil.extraName, fcmData)
onNewIntent
override fun onNewIntent(intent: Intent) {super.onNewIntent(intent)setupRedirectionFromFcm(intent)}private fun setupRedirectionFromFcm(intent: Intent) {val deepLink = intent.extras?.getString(FcmUtil.extraName)if(!deepLink.isNullOrEmpty()){val redirectionIntent = Intent(Intent.ACTION_VIEW, Uri.parse(deepLink))redirectionIntent.convertToSafeDynamicFeatureModuleIntent(this)startActivity(redirectionIntent)}}private fun Intent.convertToSafeDynamicFeatureModuleIntent(context: Context) {val options = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {context.packageManager.queryIntentActivities(this, PackageManager.ResolveInfoFlags.of(PackageManager.MATCH_DEFAULT_ONLY.toLong()))} else {context.packageManager.queryIntentActivities(this, PackageManager.MATCH_DEFAULT_ONLY)}setClassName(packageName, options[0].activityInfo.name)}
2. Background Notification
In the Background notification, the notification is delivered to the device’s system tray, and the data payload is delivered in the extras of the intent activity, so we should add the action of FIREBASE_NOTIFICATION_CLICK
, this is same as what the click_action value in the backend. So the notification from the background will be navigate to the MainActivity as we put it in the MainActivity action
<activityandroid:name="com.programmergabut.movieapp.feature.main.MainActivity"android:exported="true"android:fitsSystemWindows="true"><intent-filter><action android:name="android.intent.action.MAIN" /><action android:name="FIREBASE_NOTIFICATION_CLICK" /><category android:name="android.intent.category.LAUNCHER" /><category android:name="android.intent.category.DEFAULT" /></intent-filter></activity>
After that we can directly call the setupRedirectionFromFcm function in the onCreate callback, and the rest will be the same, we will intent to the decided activity using deeplink.
override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)...setupRedirectionFromFcm(intent)}
8. Run the script and the notification will appear
Finally you can run the code by typing in the terminal python3 movie_app_fcm.py (for other programming language you can type the language keyword for running the script), and after that it will send the message to the fcm server, and forward it to the mobile, make sure to send it to the correct token 😃

And voila, we got the notification and it will redirect to the notification activity!
🥳🥳🥳
I think that all from this articles, thank you guys for visiting! I hope this information can be useful for all of us.
Thank you and have a good day 👋
For more information you can check here - [https://firebase.google.com/docs/cloud-messaging](https://firebase.google.com/docs/cloud-messaging) - [https://firebase.google.com/docs/cloud-messaging/android/](https://firebase.google.com/docs/cloud-messaging/android/) - [https://firebase.google.com/docs/cloud-messaging/fcm-architecture](https://firebase.google.com/docs/cloud-messaging/fcm-architecture) - [https://www.techtarget.com/whatis/definition/Firebase-Cloud-Messaging-FCM](https://www.techtarget.com/whatis/definition/Firebase-Cloud-Messaging-FCM)