Sometimes I have found my self looking for different sources in addition to the original ones because they are not enough to achieve what I’m looking for. In easy words, after I read how to work with Firebase Cloud Messaging’ push notifications in Android, I felt that I needed more clarification, more specific scenarios, how to test its functionality and that is what I’m going to explain in the article.
Firstly, we need a way to test a more accurate scenario, I mean, from Firebase Console in Cloud Messaging section is the easiest way to send and receive notifications. Then a simple notification will be displayed with a title, the text will be what we put on the Message text in the console and the default app icon will complete the notification.
This is cool, and it’s an easy way to see the push notifications in action, but it has a big problem, because if we send a notification while the app is in foreground, it will not be displayed. The best option to test the feature in a clear and easy way is sending the notification using the command line.
How?
We can leverage Firebase to act like our backend server making a POST call to this endpoint:
This is a better approach than the console because we can use more parameters like in the real world.
Using this CURL command (which I took from Miquel Beltran’s article) a notification can be sent:
curl https://fcm.googleapis.com/fcm/send -X POST \
— header “Authorization: key=your_firebase’s_server_auth_key” \
— Header “Content-Type: application/json” \
-d '
{
“to”: “the_device_token”
“notification”:{
“title”:”Notification Test”,
“body”:”Notification Test Body Message”
},
“priority”:10
}'
I recommend using CocoaRest Client to run easily this CURL setting the main URL, the headers and pasting the body in a raw input.
UPDATE 1:
This is not the scope of this article, but I also wrote a little guide to fix the deprecation of getInstance().getToken() to get the registration device token from FCM, then you can fix it as well.
UPDATE 2 (2019–11–04)
For current versions of the FCM library, FirebaseInstanceId class is no longer available, then I wrote how to fix it and still work with FCM just changing a couple of things.
How to handle notifications in foreground
When the app is in foreground, all received messages are processed by the app and if you need to do some logic with them (i.e get the message details and locally save them in a database) or change the UI (use a larger icon or change the status bar icon) of the notification in the onMessageReceived method from the class which extends from FirebaseMessagingService is the place we need to do it:
public class MyFirebaseMessagingService extends FirebaseMessagingService {
public static final String TAG = "MsgFirebaseServ";
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
//check for the data/notification entry from the payload
}
}
If we don’t do anything, the notification will not be displayed.
The most important concept here is that onMessageReceive is ONLY called when the app is in foreground, if the app if is background, the Google Services will take care of displaying the message.
How to handle notifications in background
Instead of sending a “notification” entry in the payload (using the same CURL above), change it for a “data” entry. In this way the notifications will ALWAYS be managed by the app through onMessageReceived (we can also send a lot of more information such as an object id or an specific icon or a type of object):
“data”:{
“title”:”Notification Test”,
“body”:”Notification Test Body Message”,
“object_id”:”112243",
“icon”:”the_icon”,
“objectType”:”MyObjectType”
},
Then the way to get the data will be something like this, and later do the proper logic with that data:
String title = remoteMessage.getData().get(“title”);
String body = remoteMessage.getData().get(“body”);
String objectId = remoteMessage.getData().get(object_id);
String objectType = remoteMessage.getData().get(objectType”);
//remember to check first that remoteMessage.getData() is not null :)
We also need to remember to create our own notification object which will be displayed in the status bar (is the only way to show it):
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
Notification notification = new NotificationCompat.Builder(this)
.setContentTitle(title)
.setContentText(body)
.setSmallIcon(icon)
.build(); NotificationManagerCompat manager = NotificationManagerCompat.from(getApplicationContext());
manager.notify(/*notification id*/0, notification);
}
I know that is not well explained in Firebase’s official doc, but we all can better read and read it again (like me xD ) to finally understand it.
In summary
If we need to do some logic with the information sent from Firebase, and always “guarantee” to receive it and process it (no matter if the app is in background or foreground) always send the payload with a “data” entry. It will be processed always inside the onMessageReceived method.
Do not send the “notification” entry, because in this way onMessageReceived method will never be called, and Google Services process (the device’s SO) will get the message and automatically show it. In this scenario we have the option to get the info (for example the “data” entry) after the user taps on the notification icon in the status bar. Then the notification automatically will call the app’s launcher Activity and through getIntent().getExtras() method obtain the “data”.
The main drawbacks of this are that if the user dismiss a notification, neither data will be obtained nor customisations over the notifications can’t be done.
No comments:
Post a Comment
Note: only a member of this blog may post a comment.