FCM Notification is not received when my app foreground service is killed, to be more clear I'm trying to keep my app always running in the background and I used the foreground services to achieve this, sometimes the app not killed by the ANDROID system and the foreground notification appears for more than 15 hours, But other times it killed after 1 hour or less or 2hours and less when my foreground notification is killed and I send FCM notification it didn't receive by my device!! what is the problem here! how can I solve it!
-
https://stackoverflow.com/questions/37711082/how-to-handle-notification-when-app-in-background-in-firebase – Usama Altaf Jan 12 '21 at 10:16
-
@UsamaAltaf hello, I saw this it didn't help since I can handle the notification the idea is I can't do that when My foreground service is off! is there a relation between these two approaches? I mean between the FG service and FCM notifications? – Reham Alraee Jan 12 '21 at 10:41
1 Answers
Handling Notifications in Foreground
When the app is closed, your notifications are processed by the Google Service process, which take care of displaying your notifications as required, including the default click action (opening the app) and the notification icon.
When the app is in foreground, the received messages are processed by the app, and since there’s no logic to handle it, nothing will happen!
To fix this, we need our own FirebaseMessagingService, let’s create one. Create a new class that extends it and implement the onMessageReceived method. Then get the Notification object from the remoteMessage and create your own Android Notification.
public class NotificationService extends FirebaseMessagingService {
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
Notification notification = new NotificationCompat.Builder(this)
.setContentTitle(remoteMessage.getNotification().getTitle())
.setContentText(remoteMessage.getNotification().getBody())
.setSmallIcon(R.mipmap.ic_launcher)
.build();
NotificationManagerCompat manager = NotificationManagerCompat.from(getApplicationContext());
manager.notify(123, notification);
}
}
Then add the Service in your AndroidManifest.xml
<service android:name=”.NotificationService”>
<intent-filter>
<action android:name=”com.google.firebase.MESSAGING_EVENT”/>
</intent-filter>
</service>
Now if you try again, you will display notifications while your app is in foreground!
In real life, your onMessageReceived content will be slightly more complex, you will want different smart actions depending on the type of notification, you will want to show a nicer large icon (the one that appears on the notification body) and for sure to change the status bar icon.
The problem you have now is that your onMessageReceived is ONLY called when the app is in foreground, if you app if is background, the Google Services will take care of displaying your message.
The solution? don’t use the “notification” message payload and use “data” instead. Using Data
The last step to solve this foreground/background problem is to ditch the notification object from your message payload.
Rather than sending:
{
"to": "the device token"
"notification":{
"title":"New Notification!",
"body":"Test"
},
"priority":10
}
Send:
{
"to": "the device token"
"data":{
"title":"New Notification!",
"body":"Test"
},
"priority":10
}
This way, your notifications will be always handled by the app, by your NotificationService, and not by the Google Service process.
You will need to change your code as well to handle the data payload:
// Old Way
//.setContentTitle(remoteMessage.getNotification().get(“title”))
//.setContentText(remoteMessage.getNotification().get(“body”))
// New Way
.setContentTitle(remoteMessage.getData().get(“title”))
.setContentText(remoteMessage.getData().get(“body”))
Your whole NotificationService will look like this now:
public class NotificationService extends FirebaseMessagingService {
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
Notification notification = new NotificationCompat.Builder(this)
.setContentTitle(remoteMessage.getData().get(“title”))
.setContentText(remoteMessage.getData().get(“body”))
.setSmallIcon(R.mipmap.ic_launcher)
.build();
NotificationManagerCompat manager = NotificationManagerCompat.from(getApplicationContext());
manager.notify(123, notification);
}
}
One more advantage of using data instead of notification object is that you can put anything you want in the “data” object. For example a user ID, a URL to an image… any information that you might want to use to build the notification or to pass to the click action. Note that all will be treated as Strings. For example,
"data":{
"title":"New Notification!",
"body":"Test",
"user_id": "1234",
"avatar_url": "http://www.example.com/avatar.jpg"
},
This difference is also explained in the Handling Messages section of this document: https://firebase.google.com/docs/cloud-messaging/android/receive
Conclusion
Note that if you keep the “notification” object in your payload, it will behave just like before. You need to get rid of the “notification” and only provide the “data” object.
- 1,036
- 1
- 4
- 23
-
Is this solution will isolate the FCM behavior from my APP FOREGROUND SERVICE? – Reham Alraee Jan 12 '21 at 11:00
-
-
hello, this didn't help!! I think you didn't get the point I tried to explain ,, my problem is not in receiving the notification when the app in the foreground, The PROBLEM IS When My foreground service becomes off I can't receive any FCM notifications – Reham Alraee Jan 19 '21 at 15:25