Android-Make FCM work when the app is in the background

Neeraja Gandla
3 min readMar 20, 2021

--

FCM Data messages to trigger OnMessageReceived even when the app is in the background

Image taken from https://firebase.google.com/docs/cloud-messaging

As I was debugging one of my applications that use FCM, I noticed that the OnMessageReceived callback is triggered only when the app is in the foreground i.e. the app is opened in the mobile. If the app is in the background, I saw that the notification was received in the system tray but the OnMessageReceived callback is not triggered.

I had important data sent through the “data” payload of the message. Based on the data I was launching an appropriate intent when the user clicks on a notification. As the callback was not triggered, I couldn’t launch the intent anymore with the data.

As I researched about this issue, I discovered that the notification and the data payloads in FCM message have particularly defined purposes. They are explained briefly here.

A typical FCM message format is as follows:

{
“notification”: {
“title”: “AppName”,
“sound”: null,
“body”: “Hey! You have a Message”
},
“data”: {
“param1”: null,
“param2”: [
238
],
“id”: 1
},
“to”: “ — device push token here — ”
}

This was the message format we were using. It had both “notification” and “data” payloads. As per the above link, this is stated:

Messages with both notification and data payloads: When in the background, apps receive the notification payload in the notification tray, and only handle the data payload when the user taps on the notification.

It’s said that the key-value parameters in the “data” payload will be loaded as arguments to the activity mentioned in the “click_action” parameter of the notification payload-if the app is in the background when the push is sent out.

Or we can only use the “data” payload and get rid of the “notification” payload. Then it becomes a data message and it always seems to trigger the OnMessageReceived callback. So I have decided to try with this approach. However I didn’t want to lose the title and body that come in the “notification” payload. So I shifted those parameters as new key-value pairs in the “data” payload. The modified message format looked as follows:

{
“data”: {
“title”: “AppName”,
“body”: “Hey! You have a message”
“param1”: null,
“param2”: [
238
],
“id”: 1
},
“priority”:”high”,
“to”: “ — device push token here — ”
}

When I had to use the title and body from the above format, I used

Map<String, String> dataMap = remoteMessage.getData();
String title = dataMap.get(“title”);
String body = dataMap.get(“body”);
String param1 = dataMap.get("param1");
String param2 = dataMap.get("param2");

. In a similar way I also got the other parameters. This works because the “data” is always received as a set of key-value pairs at the device end.

This has solved my issue. I’m now getting the OnMessageReceived callback even if the app is in the background when the push is sent out.

Bundle bundle = new Bundle();
PendingIntent pendingIntent = null;
bundle.putString("param1", param1);
bundle.putString("param2", param2);
pendingIntent = new NavDeepLinkBuilder(this)
.setComponentName(HomeActivity.class)//Activity
.setGraph(R.navigation.mobile_navigation)
.setDestination(R.id.navigation_offers)//Destination Fragment
.setArguments(bundle)
.createPendingIntent();

I see that there are also many other possibilities with the FCM payloads. But this particular approach resolved the issue that I had. You can try the same if you are struggling with a similar issue.

If you have any queries or are aware of a better way to solve this problem please do post a comment. I would love to learn more regarding the possibilities that FCM provides.

Hope this article helped you with the issue.

Happy Learning! Cheers!

--

--

Neeraja Gandla
Neeraja Gandla

Written by Neeraja Gandla

I’m an Android App Developer by Profession. I would like to write out my thoughts and learning to let others learn through my experiences.

Responses (1)