I am sending data-message to my android application via FCM.But when I change the data payload structure,it does not seem to affect.
The FCM payload is
{
"to" : "eF3lccIdYs4:APA91bHpC1xWNl4MZXXXX",
"data" : {
"caller_name" : "Sobin Thomas",
"room" : "2000",
"call_type" : "audio"
},
"time_to_live" : 0
}
If I change it to
{
"to" : "eF3lccIdYs4:APA91bHpC1xWNl4MZXXXX",
"data" : {
"**caller**" : "Sobin Thomas",
"**room_number**" : "2000",
"call_type" : "audio",
**"call_time" : "2018-04-24 12:12:12",**
},
"time_to_live" : 0
}
Old data payload is still getting in the mobile app. And of course the data payload values change
Firebase Cloud Messaging will try to deliver every message, not just the last one. What's likely happening is that your device is receiving multiple messages in short succession, and only displays one.
If you want new messages to replace older message, you'll need to specify a so-called collapse_key. From the documentation:
This parameter identifies a group of messages (e.g., with collapse_key: "Updates Available") that can be collapsed, so that only the last message gets sent when delivery can be resumed. This is intended to avoid sending too many of the same messages when the device comes back online or becomes active.
Related
I am using PushNotifications Capacitor plugin and FCM to send the notifications, everything works fine until I want to send a Push Notification with both notification and data fields on Android.
What I want to do is to send a custom data with the notification and consume the notification on app resume. I am using PushNotifications.getDeliveredNotifications() method to get the notifications on resume, on iOS I get all the notifications with proper data, but on Android data property is replaced with the object below:
{
body: "My Body",
data: {
android.appInfo: "ApplicationInfo{809371c app}",
android.bigText: "My Body",
android.progress: 0,
android.progressIndeterminate: false,
android.progressMax: 0,
android.reduced.images: true,
android.showChronometer: false,
android.showWhen: true,
android.template: "android.app.Notification$BigTextStyle",
android.text: "My Body",
android.title: "My Title",
gameDndOn: false,
specialType: "",
topFullscreen: false,
groupSummary: false,
id: 0,
title: "My Title"
}
}
I see in the FCM docs for Android apps that if both notification and data fields are present and the app is in the background the notification lands in the system tray and data in extras of the intent.
I am getting proper data when I tap on the notification, but in my case I want to get that on resume, without tapping on the notification.
Is there any way to get to that data in that case?
You have to create the message in this format
{
"message":{
"token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"notification":{
"title":"Portugal vs. Denmark",
"body":"great match!"
},
"data" : {
"Nick" : "Mario",
"Room" : "PortugalVSDenmark"
}
}
}
Note : notification structure is critical for receiving a notification. You need to have title and body. This gets displayed in the notification drawer.
data can be customized as per your requirement. This will have the data that you need inside your app.
Suggestion, keep your payload small. Send data which is absolutely necessary and also safe to send over FCM.
Look at this part of the official documentation
For handling push notifications in capacitor, you should use the listeners. Here is the official docs way of doing it.
I'm using com.google.firebase:firebase-messaging:20.0.0 on Android. When I try sending a notification like the one below it always shows the normal title and body instead of title_loc_key and body_loc_key when they are presented in the app! The fun thing is that it's not the case in iOS. In iOS it will always try to first show the localized resources and if it couldn't find them, it will default to normal ones.
{
"to" : "f6_numko7IQ:APA91bFrTN0fmThFDeAFy2...",
"collapse_key" : "type_a",
"notification" : {
"title_loc_key": "resource_name_1",
"body_loc_key": "resource_name_2",
"title": "Default Title",
"body": "Default Body!"
}
}
Is this a known issue? Is there a get around for it?
The solution is to remove the "title" and "body" entries. I know it should work like on iOS but currently it's not.
{
"to" : "f6_numko7IQ:APA91bFrTN0fmThFDeAFy2...",
"collapse_key" : "type_a",
"notification" : {
"title_loc_key": "resource_name_1",
"body_loc_key": "resource_name_2",
}
}
For Android: Using the "v1" api from firebase remove "title" and "body" from root "notification: {....}" and add into the "android": {
"notification": {
"title_loc_key": "push_notification_title",
"body_loc_key": "push_notification_body"
}
},", should work.
But you need to keep in mind the following:
The push notification will be displayed by default by firebase SDK based on the com.google.firebase.MESSAGING_EVENT, when the app is in the background --> opened (the process is in the background) and Notification permission is allowed. Also, you need to be sure that your app has already a channel created with the default_channel_id you defined in the manifest file. For this case, you will not be notified of the onMessageReceived callback provided by "FirebaseMessagingService".
When the app is in the foreground you will not receive any firebase notification, visible on the screen. Based on the Channel you have created at point 1) you need to trigger the notification display if required, by creating a NotificationBuilder .... and displaying it. This catch must happen inside the: onMessageReceived callback provided by "FirebaseMessagingService"
When the app is closed and notification is allowed the push notification will be displayed by default by firebase SDK based on the com.google.firebase.MESSAGING_EVENT. However, if the notification received by the device contains some data: {} payload that can be handled into the onCreate lifecycle method from activity by accessing the this.intent.extras. You will not be notified of the onMessageReceived callback provided by "FirebaseMessagingService".
If notification is disabled you will not get any push notification displayed visually but when the app is in the foreground you will be notified into the onMessageReceived callback provided by "FirebaseMessagingService". When the app is closed or in the background, you will get nothing.
I am currently launching my video calling application on FCM message received event. It works fine. But in Oreo when the battery is very low I am not getting any FCM notifications. But Whatsapp works even in that scenario
I'm sending the following JSON:
{
"to" : "XXXDecviceToken",
"data" : {
"callId" : "Call ID",
"displayName" : "Abhilash",
"room" : "2000"
},
"time_to_live" : 0
}
Seeing your JSON request:
{
"to" : "XXXDecviceToken",
"data" : {
"callId" : "Call ID",
"displayName" : "Abhilash",
"room" : "2000"
},
"time_to_live" : 0
}
There are two issues that can prevent your notification from being delivered when battery is low:
You don't specify a priority, so the default priority is "normal" for data messages:
By default, notification messages are sent with high priority, and data messages are sent with normal priority. Normal priority optimizes the client app's battery consumption and should be used unless immediate delivery is required. For messages with normal priority, the app may receive the message with unspecified delay.
You specify "time_to_live" of 0, which means that if FCM fails to deliver the message immediately, it will never be delivered (since it's not kept in FCM storage).
So, combining "normal" priority with "time_to_live" of 0 is likely to prevent the message from being delivered when battery is low.
To try to overcome this issue, you can either set the priority to "high":
{
"to" : "XXXDecviceToken",
"data" : {
"callId" : "Call ID",
"displayName" : "Abhilash",
"room" : "2000"
},
"time_to_live" : 0,
"priority" : "high"
}
or change "time_to_live" to a positive value (at least enough time to give the message a chance to be delivered after the battery is re-charged).
I use Firebase Cloud Messaging (FCM) HTTP Legacy API protocol to send push notifications in JSON to android mobile devices. For the client side I use react-native-fcm library.
The aim is to send the notification to the particular devices when the application is in 3 states:
1) running
2) background running
3) killed
According to the documentation for FCM there are 3 different types of messages which can be sent via FCM service:
1) notification (has predefined fields)
2) data (set whatever fields you want)
3) mixed (notification + data).
The logic of listening the event for incoming message on the client side using react-native-fcm is the next:
this.notificationEmitterSubscription = FCM.on(FCMEvent.Notification, notif => {
if(notif && notif.fcm){
//received from Firebase
if(!notif.local_notification && notif.title){
let badge = parseInt(notif.badge);
FCM.setBadgeNumber(badge);
this.showNotification(notif.title, notif.body, badge);
}
//notification is clicked
if(notif.opened_from_tray){
FCM.setBadgeNumber(0);
this.executeNavigateAction(notif.fcm.action); //this method just navigates user to a particular screen in the application
}
}
});
Show notification method is implemented in this way:
showNotification(title, body, badge) {
FCM.presentLocalNotification({
body: body,
priority: "high",
title: title,
sound: "default",
large_icon: "ic_launcher",// Android only
icon: "ic_launcher",
show_in_foreground :true, /* notification when app is in foreground (local & remote)*/
vibrate: 300, /* Android only default: 300, no vibration if you pass null*/
lights: true, // Android only, LED blinking (default false)
badge: badge,
local: true,
click_action: NAV_SCREEN_NAME
});
}
notif.title, notif.body and notif.badge are the fields which are set in data section of the message when sending it via FCM API. In other word the message is sent in the (3) mixed form:
{
"registration_ids" : ["FCM_device_token_1", "FCM_device_token_2"],
"notification" :
{
"title" : "fcm notification message title",
"body" : "fcm notification message body",
"badge" : 111
},
"data" :
{
"title" : "fcm data message title",
"body" : "fcm data message body",
"badge" : 222
}
}
If the message is sent as (1) notification (without "data" section in the message, in this case some changes in the reading the fields are necessary, to change notif.title -> notif.fcm.title, but this is not the main point in the question) or mixed (3) then the listener for the notification is NOT triggered when application is (2) background running and (3) killed. As a result, the badge number is not set. BUT despite the fact that the method showNotification(title, body, badge) is not called (because the event listener is not triggered) the message IS shown. It seems that react-native-fcm has internal implementation for this situation to show (1) notification and (3) mixed messages automatically when application is not running. In other words, the listener IS called for (1) notification and (3) mixed messages only when the application is (1) running and IS NOT called when the application is in the (2) background or (3) killed and does NOT show the badge number. However, the message itself IS shown for all situations.
Another approach is to send a (2) data message. This type of FCM message triggers the listener (notificationEmitterSubscription) for all states of the application: (1) running and (2) background running and (3) killed. As a result, badge number is set in all these states. However, despite the fact that method showNotification(title, body, badge) is called whenever a data FCM message is received, method FCM.presentLocalNotification does NOT display the message if the application is killed.
Thus, in few words, I have a question.
How to:
EITHER display a badge number when (1) notification or (3) mixed message is received and the application is in (2) background running or (3) killed
OR display a (2) data message when the application is (3) killed?
Thank you!
The solution has been found. The statement is that: there is no code running if the application is killed, so the messages is handled and displayed out of your code. The message has to be set in the next format to be shown for the killed status:
{
"registration_ids" : ["FCM_token_1", "FCM_token_2"],
"data" :
{
"custom_notification" :
{
"title" : "FCM test title",
"body" : "FCM test body"
},
badge : 1
}
}
In your react-native application in the notification handler the notification is received as a json value of notif.custom_notification property. So, the code looks like this:
this.notificationEmitterSubscription = FCM.on(FCMEvent.Notification, notif => {
if(notif && notif.fcm){
//received from Firebase
if(!notif.local_notification && notif.custom_notification){
let message = JSON.parse(notif.custom_notification);
let body = message.body;
let title = message.title;
let badge = parseInt(notif.badge);
FCM.setBadgeNumber(badge);
this.showNotification(title, body, badge);
}
//notification is clicked
if(notif.opened_from_tray){
FCM.setBadgeNumber(0);
this.executeNavigateAction(notif.fcm.action);
}
}
});
The issue can be solved as a resolved one.
With the Urban airship's library, I was able to implement the push notification ok. Which will trigger the onReceive() method every time I send push a message from a server.
But when I switch to use PushRich notification, whenever I send out a rich message, it won't triiger the onReceive() method.
I want to be able to achieve the same way it dose with the push notification in here.
I tried the richpush simple code from the website, but it seems to be having the same problem.
The fact that I think its possible its because from the sample code onReceive() method has the following code in it.
// Ignore any non rich push notifications
if (!RichPushManager.isRichPushMessage(intent.getExtras())) {
return;
}
Would it mean, it should send intent when we send rich push from server ?
Problem has been solved. After more digging into the Urban airship library. The rich message that contains HTML is actually be put into part of the push message JSON object.
Looks like such in a simple push message
{
"audience" : { "tag" : [ "tag1", "tag2" ] },
"device_types" : [ "ios" ],
"notification" : { "alert" : "New message!" },
"message" : {
"title" : "Message title",
"body" : "<Your message here>",
"content_type" : "text/html"
}
}
The "message" object is actually the Rich message itself. So therefore, catching the intent for a simple push message can from then determine if a rich message exist in the intent.