How to handle notifications using FCM when an application is either in the foreground or in the background

I used firebase to create my project.
He will also use FCM (firebase cloud message).
But there's a problem.
I cannot process FCM (create my own notification) when the application is in the background. The official website tutorial said that
case 1: App foreground -> override "onMessageReceived ()" to create your own notification.
case 2: Application Background -> The system will create a notification directly. We do not need and can not do anything. Since in this case it does not run the onMessageReceived () function.

However, if I cannot do anything when the application is in the background, I cannot create my own notification. (for example, after users click on a notification and a window opens to display detailed information.)

So, how to handle notifications using FCM when the application is in the background?

0
source share
3 answers

There is bad news.
Google will change the source code of Firebase to 'com.google.firebase: firebase-messaging: 11.6.0'.
handelIntent is now the "public final void method". which means we cannot redefine it.
If you want to use the solution, change the version to "com.google.firebase: firebase-messaging: 11.4.2"



Try your way. It works great on the version for building the project - Android 6.0 (api level 23), and I already tried this.

There is a better way than the official tutorial website

The official website said that a notification will be generated by the system when the application is in the background. Thus, you cannot handle this by overriding "onMessageReceived ()". Because "onMessageReceived ()" is launched only when the application is in the foreground.

But there is no truth. In fact, notifications (when the application is in the background) are generated by the Firebase library.

After I traced the firebase library code. I find the best way.

Step 1. Cancel "handleIntent ()" instead of "onMessageReceived ()" in FirebaseMessagingService
why:
Since the method will be launched, either the application is in the foreground or in the background. Thus, we can process the FCM message and create our custom notifications in both cases.

@Override public void handleIntent(Intent intent) { Log.d( "FCM", "handleIntent "); } 


Step 2. Parse the message from FCM
as:
If you do not know the format of the message that you set. Print it and try to parse it.
Here is a basic illustration

 Bundle bundle = intent.getExtras(); if (bundle != null) { for (String key : bundle.keySet()) { Object value = bundle.get(key); Log.d("FCM", "Key: " + key + " Value: " + value); } } 


Step 2. Delete notifications created by the Firebase library when the application is in the background
why:
We can create our custom notification. But the notification generated by the Firebase library will still be (actually it was created by โ€œsuper.handleIntent (intent)". The following is a detailed explanation.). Then we will have two signals. This is rather strange. Therefore, we need to delete the notification created by the Firebase library

how (project build level - Android 6.0 above):
Recognize the notifications we want to remove and receive information. And use "notificationManager.cancel ()" to remove them.

 private void removeFirebaseOrigianlNotificaitons() { //check notificationManager is available NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); if (notificationManager == null ) return; //check api level for getActiveNotifications() if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { //if your Build version is less than android 6.0 //we can remove all notifications instead. //notificationManager.cancelAll(); return; } //check there are notifications StatusBarNotification[] activeNotifications = notificationManager.getActiveNotifications(); if (activeNotifications == null) return; //remove all notification created by library(super.handleIntent(intent)) for (StatusBarNotification tmp : activeNotifications) { Log.d("FCM StatusBarNotification", "StatusBarNotification tag/id: " + tmp.getTag() + " / " + tmp.getId()); String tag = tmp.getTag(); int id = tmp.getId(); //trace the library source code, follow the rule to remove it. if (tag != null && tag.contains("FCM-Notification")) notificationManager.cancel(tag, id); } } 

All my sample code is:

 public class MyFirebaseMessagingService extends FirebaseMessagingService { private static int notificationCount=0; @Override public void handleIntent(Intent intent) { //add a log, and you'll see the method will be triggered all the time (both foreground and background). Log.d( "FCM", "handleIntent"); //if you don't know the format of your FCM message, //just print it out, and you'll know how to parse it Bundle bundle = intent.getExtras(); if (bundle != null) { for (String key : bundle.keySet()) { Object value = bundle.get(key); Log.d("FCM", "Key: " + key + " Value: " + value); } } //the background notification is created by super method //but you can't remove the super method. //the super method do other things, not just creating the notification super.handleIntent(intent); //remove the Notificaitons removeFirebaseOrigianlNotificaitons(); if (bundle ==null) return; //pares the message CloudMsg cloudMsg = parseCloudMsg(bundle); //if you want take the data to Activity, set it Bundle myBundle = new Bundle(); myBundle.putSerializable(TYPE_FCM_PLATFORM, cloudMsg); Intent myIntent = new Intent(this, NotificationActivity.class); myIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); myIntent.putExtras(myBundle); PendingIntent pendingIntent = PendingIntent.getActivity(this, notificationCount, myIntent, PendingIntent.FLAG_UPDATE_CURRENT); //set the Notification NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this) .setSmallIcon(R.mipmap.icon) .setContentTitle(cloudMsg.getTitle()) .setContentText(cloudMsg.getMessage()) .setAutoCancel(true) .setContentIntent(pendingIntent); NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.notify(notificationCount++, notificationBuilder.build()); } /** * parse the message which is from FCM * @param bundle */ private CloudMsg parseCloudMsg(Bundle bundle) { String title = null, msg=null; //if the message is sent from Firebase platform, the key will be that msg = (String) bundle.get("gcm.notification.body"); if(bundle.containsKey("gcm.notification.title")) title = (String) bundle.get("gcm.notification.title"); //parse your custom message String testValue=null; testValue = (String) bundle.get("testKey"); //package them into a object(CloudMsg is your own structure), it is easy to send to Activity. CloudMsg cloudMsg = new CloudMsg(title, msg, testValue); return cloudMsg; } /** * remove the notification created by "super.handleIntent(intent)" */ private void removeFirebaseOrigianlNotificaitons() { //check notificationManager is available NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); if (notificationManager == null ) return; //check api level for getActiveNotifications() if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { //if your Build version is less than android 6.0 //we can remove all notifications instead. //notificationManager.cancelAll(); return; } //check there are notifications StatusBarNotification[] activeNotifications = notificationManager.getActiveNotifications(); if (activeNotifications == null) return; //remove all notification created by library(super.handleIntent(intent)) for (StatusBarNotification tmp : activeNotifications) { Log.d("FCM StatusBarNotification", "tag/id: " + tmp.getTag() + " / " + tmp.getId()); String tag = tmp.getTag(); int id = tmp.getId(); //trace the library source code, follow the rule to remove it. if (tag != null && tag.contains("FCM-Notification")) notificationManager.cancel(tag, id); } } } 
+2
source

FCM No background notification will be sent if your application is killed more, and as you described in your answer about handleIntent() . This may work for some devices and for some old version of FCM, also if you @override method that is not described in the official firebase document, you may encounter some problems here and you use it at your own risk !

What's the solution?

You need to use your own push notification service near FCM, for example Telegram.

OR using the SyncAdapter next to GCM, such as Gmail.

So, if you need it to work successfully like these applications, you should use your own hack .

+1
source

However, if I cannot do anything when the application is in the background, I cannot create my own notification. (for example, after users click on a notification and a window opens to display detailed information.)

So, how to handle notifications using FCM when the application is in the background?

First, you need to create the correct message payload sent to the fcm server. Example:

 { "to": "topic_name", "priority": "high", "data": { "field1": "field1 value" "field2": "field2 value" } "notification" : { "body" : "Lorem ipsum", "title" : "sampke title" "click_action": "SHOW_DETAILS" } } 

data payload - is the actual data that you want to display as the information about the message after the user clicks on the notice, notification payload is how should look the generated notification (there are many attributes that can be set), you do not you need to create a notification yourself, you only need to set its properties here.

To show your activity after the user has dialed notifications, you need to set an intent filter corresponding to click_action :

 <intent-filter> <action android:name="SHOW_DETAILS"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> 

so that an activity that has a filter above the intent will start automatically when the user clicks on the notification. The final step is to retrieve data when activity starts after notification. This is pretty easy. User data is transferred to the action through the packet. Inside the onCreate method for your activity, do something like this:

 Bundle bundle = getIntent().getExtras(); if(bundle.getString("action").equals("SHOW_DETAILS")) /*This indicates activity is launched from notification, not directly*/ { //Data retrieved from notification payload send String filed1 = bundle.getString("field1"); String filed2 = bundle.getString("field2"); } 

All of the above applies if the application does not work or it is in the background. If your application is in the foreground, a notification will not be created. Instead, you will get the onMessageReceived() event so that you can process the same data there (I think you know how).

Link:

https://firebase.google.com/docs/cloud-messaging/http-server-ref https://github.com/firebase/quickstart-android/tree/master/messaging

0
source

Source: https://habr.com/ru/post/1265533/


All Articles