I migrated from GCM to FCM like instructed here.
Whenever I send a message, the onMessageSent method is not invoked.
I use following source code to send messages:
Map<String,String> data = new HashMap<String,String>();
data.put(GcmConstants.ACTION, GcmConstants.ACTION_CHAT);
data.put(Constants.CHAT_FLAG, Constants.FLAG_NEW_CHAT);
ObjectMapper mapper = new ObjectMapper();
String chatJsonInString = mapper.writeValueAsString(Helper.chatToJson(chat));
data.put(Constants.CHAT_JSON, chatJsonInString);
String receiverJsonInString = mapper.writeValueAsString(Helper.userToJson(receiver));
data.put(Constants.RECEIVER_JSON, receiverJsonInString);
String id = Integer.toString(getNextMsgId(ctxt));
FirebaseMessaging fm = FirebaseMessaging.getInstance();
fm.send(new RemoteMessage.Builder(senderId + "#gcm.googleapis.com").setMessageId(id).setData(data).build());
Why is not working?
If you look at the official website example here, then you will see this comment :
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// [START_EXCLUDE]
// There are two types of messages data messages and notification messages. Data messages are handled
// here in onMessageReceived whether the app is in the foreground or background. Data messages are the type
// traditionally used with GCM. Notification messages are only received here in onMessageReceived when the app
// is in the foreground. When the app is in the background an automatically generated notification is displayed.
// When the user taps on the notification they are returned to the app. Messages containing both notification
// and data payloads are treated as notification messages. The Firebase console always sends notification
// messages. For more see: https://firebase.google.com/docs/cloud-messaging/concept-options
// [END_EXCLUDE]
// TODO(developer): Handle FCM messages here.
at the start of onMessageReceived. My understanding from this is that you must have a data component in your message, for the callback to be triggered.
I based my code on this and the callbacks are triggered.
Yes, solved my problem. I put google-services.json into the wrong folder. Next time I should following "get started guide" for implementing the client more precisley.
Related
I'm using Firebase Cloud Messaging to send notifications and ShortcutBadger to update the unread messages count on our app badge. I've extended the FirebaseMessagingService class and implemented the override method onMessageReceived, which seems to be working fine since I get notifications when my app is in the background or killed. However, when I add the ShortcutBadger call inside this method, I no longer receive notifications and the ShortcutBadger call does not work.
ShortcutBadger requires a Context and, since FirebaseMessagingService extends Service, it is a context, which is why I simply pass this. I also have ShortcutBadger working in other parts of my code, so I know it works.
Any suggestions would be appreciated.
public class Notifications extends FirebaseMessagingService {
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
ShortcutBadger.applyCount(getApplicationContext(), 1); // <-- now is working
}
}
EDIT: SERVER SIDE CODE
Here's the server-side code that sends the Firebase message.
Notification notification = new Notification.Builder(null)
.title(msg.getTitle())
.badge(msg.getBadge())
.body(msg.getMessage())
.build();
Message message = new Message.Builder()
.timeToLive(timeToLive)
.delayWhileIdle(true)
.notification(notification)
.addData("text", msg.getMessage())
.addData("title", msg.getTitle())
.addData("line1", msg.getSubtitle())
.addData("badge", String.valueOf(msg.getBadge()))
.addData("qummute_notification", "true")
.build();
Result result = send(message, deviceKey, retries);
It's been suggested that I send the message without the Notification payload. Will try that and see what happens.
Have you made sure that you are not calling ShortcutBadger.removeCount(Context context) while testing?
Try using ShortcutBadger.applyCountOrThrow(Context context, int badgeCount) to see if any exceptions are thrown.
The onMessageReceived(RemoteMessage remoteMessage) is called on a background thread. Perhaps the phone/launcher you are testing on is using a badge that cannot be created and shown from a background thread.
You need to handle this situation from server side.Remove Notification from your JSON and Use data.
Remove Notification Hole object,
"notification": {
"title": "My Title if any",
"body": "location",
"sound": "default"
},
From where you are sending the notification you need to change that code,
For Server side code should be like below then your onMessageReceived method call even if app is in the background or killed.
{
"registration_ids": [
"cBbGxlj5JRI:APA91bFRLp3tDoBo_P5lGYGUZ4F6iJ55yBJq4GInL7RVV2asHR5PovqnMX-ekIdl_xOYyRyJmSe3SkxYMa3mzIvqml3MmLYZUh8JWygixIebhzhb_l4xv0Q-v3werKl_UO069G1uOyvq"
],
"data": {
"title": "alt_ctgry - Vehicle Number - extra detail(if any)",
"body": "location"
},
"priority": "high"
}
if you want to create notification then write your own code for notification.
For Notification data access use below code,
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
Log.e("FCM", "Call onMessageReceived\n" + remoteMessage + "");
String title = remoteMessage.getData().get("title");
String body = remoteMessage.getData().get("body");
createNotification(title, body);
}
which seems to be working fine since I get notifications when my app is in the background or killed
No, onMessageReceived is called when your app in foreground but not background IF you have notification payload.
In your server side code you add notification payload, so previously your onMessageReceived also was not called when app in background but notification was shown by OS from your payload.
If you want to handle your push all the time you need to remove notification payload, but remember that it could break pushes on iOS if you have an iOS app.
I have function in Firebase Cloud Functions which is used to send notifications to specific users within my app and has as the notificationContent the following code:
const notificationContent = {
notification: {
title: "My Notification Title",
body: "My Notification Body",
icon: "default",
sound : "default"
}
};
I have tried to use collapse_key: "unique_key" but it has no effect. I read the has an effect only when the device is offline. I also have used a tag: "unique" but every time a new notification arrives, it will override the oldest one.
I there any way in which I can achieve this with Firebase? If I receive more then one notification, to be grouped in a single one?
Thanks in advance!
If you want to use more customizable and advanced notification features.
You should only send FCM with data payload, and create notification at android client side.
Remember that if you send FCM with notification payload or notification + data payload, the notification will be created by android core system and BroadcastReceiver's onReceive method won't being called if your app is on background.
If you send FCM with data payload, it will call onReceive all the time, so you can produce custom notification manually at android client side. (most app uses latter method.)
I hope this link would be helpful.
I had this same confusion and realized I misunderstood what collapseKey and tag are for.
collapseKey will limit the number of notifications a client receives while they're offline, tag is what will stack notifications together in the drawer.
So for a typical cloud function, it should look like this:
const notification = {
notification: {
'title': 'Interesting title',
'body': 'Hello, world'
},
'data': {
'whatever': whatever,
},
'android':{
'collapseKey': collapseKey,
'priority': 'high',
'notification': {
'tag': tag,
}
},
'token': fcmToken
};
admin.messaging().send(notification)
Note that the "tag" parameter sits inside of the android notification, not the top-level notification.
The easiest and most flexible solution is to extend the FirebaseMessagingService and handle the notification yourself. But first instead of using notification on your notificationContent in your cloud function, you have to change that to data so that you send a data message instead of a notification message. The difference is that the notification message will have an implicit collapse key (the package name of the app), while the data message won't have one. But the data message needs to be handled on the client or else it won't be displayed.
Here's a sample of what you'll need for your FirebaseMessagingService:
public class MyFCMService extends FirebaseMessagingService {
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
if (remoteMessage.getNotification() != null) {
//this notification was sent from the Firebase console, because in our cloud function, we are using the DATA tag, not the notification tag
//so here we have to handle the notification that was sent from the console
...
} else if (remoteMessage.getData().get(KEY) != null) {
//this data message was sent from our cloud function
//KEY is one of the keys that you are using on the cloud function
//in your example, you are using the keys: title, body, icon, sound
//display the notification to the user
...
notificationManager.notify(TAG, ID, notificationBuilder.build());
//you have to use the same TAG and the same ID on each notification if you want your 2nd notification to simply update the text of the first one, instead of showing as a new notification
}
}
}
PS. When you send a notification from your cloud function (well if you use the data tag, it's actually a data message, not a notification message), then this method will be called, regardless if the app is in the background or in the foreground. HOWEVER, when you send a notification from the firebase console, this method will be called ONLY if the app is in the foreground. If the app is in the background, the Firebase SDK will handle the notification and show it to the user. In some cases, it makes sense to show a notification only when the user is not running the app, for example if you want to advertise some new features of the app. In that case, what you can do is use a unique tag on the notification console (e.g. "display_in_foreground") and check that tag on the client. If you have set that to true, you can show the notification even to users that are currently running the app, or if it's false you can choose not to show the notification. This check will happen only if the app is in the foreground. If it's in the background, this won't be called at all and the SDK will handle to show the notification.
I am using cordova plugin add phonegap-plugin-push plugin for push notification
In forground notification works fine.and i can handle event also.
When my app is in background then i got notification as well but on click of push notification my event is not fire.
I am using below code
$cordovaPushV5.initialize(options).then(function() {
// start listening for new notifications
$cordovaPushV5.onNotification();
// start listening for errors
$cordovaPushV5.onError();
// register to get registrationId
if (PNdeviceToken == null) //becuase registration will be done only the very first
{
$cordovaPushV5.register().then(function(registrationId) {
// save `registrationId` somewhere;
window.localStorage.setItem('PNdeviceToken', registrationId);
$rootScope.fcmToken = registrationId;
console.log(registrationId)
alert("first time registered id -- " + registrationId)
})
} else {
$rootScope.fcmToken = PNdeviceToken;
alert("already saved registered id -- " + $rootScope.fcmToken)
}
});
$rootScope.$on('$cordovaPushV5:notificationReceived', function(event, data) {
console.log(event)
console.log(data)
})
When i tap on background push notiction then $cordovaPushV5:notificationReceived event not fire, How can I solve this problem?
How can i handle background push notification event?
I had the Same issue and got it resolved it after 2 days of research.
Handling the notification events is same whether the app is in foreground or background.
We have to set "content-available" : "1" in the data field while pushing notifications. Else it wont call notificationReceived event if app is in background.
Also note this is not possible as of now through Google Firebase Console.
We have to send our custom payload messages (data or notification or both) seperately using any one of the firebase servers.
Detailed info can be found on the plugin's GitHub Docs Page on background notifications.
Quoting from there -
On Android if you want your on('notification') event handler* to be called when your app is in the background it is relatively simple.
First the JSON you send from GCM will need to include "content-available": "1". This will tell the push plugin to call your on('notification') event handler* no matter what other data is in the push notification.
*on('notification') event handler = $cordovaPushV5:notificationReceived event in your case.
See this answer for sending custom payload messages using PHP and NodeJS
I'm trying to send push notifications throught FCM services.
In my MainActivity I write this code:
mRegistrationBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// checking for type intent filter
if (intent.getAction().equals(Config.REGISTRATION_COMPLETE)) {
// gcm successfully registered
// now subscribe to `global` topic to receive app wide notifications
FirebaseMessaging.getInstance().subscribeToTopic(Config.TOPIC_GLOBAL);
displayFirebaseRegId();
} else if (intent.getAction().equals(Config.PUSH_NOTIFICATION)) {
// new push notification is received
String message = intent.getStringExtra("message");
Toast.makeText(getApplicationContext(), "Push notification: " + message, Toast.LENGTH_LONG).show();
}
}
};
In order to subscribe user to a topic.
From backend I make a call to FCM service at this link : https://fcm.googleapis.com/fcm/send
in which I pass this JSON:
{
"to":"/topics/global",
"data":{
"title":"test",
"is_background":false,
"message":"testmessage",
"image":"",
"payload":{
"team":"Test",
"score":"5.6"
},
"timestamp":"2017-05-23 11:55:35"
}
}
and I get this response:
{\"message_id\":8863205901902209389}
But my device doesn't show any notifaction, exept if I use Firebase console with "user segment" or "single device" . Also in Firebase console doesn't works "topic" way.
Thank you in advance for any response.
There are two types of FCM messages.
Notification Messages
Data Messages
On the client side, Notification messages are handled by FCM and automatically displayed in the notification window. If you are using Data Messages, your app needs to handle the received message and create a notification.
The sample payload in your question is a data message and hence it is not displayed in notification (I assume you didn't do any handling). The notifications sent via FCM console are always notification messages and hence those are automatically displayed.
Refer to this FCM page for more details on this.
When app is in background, the notification message is deliver by Notification, when the notification is tap, app is launch, how can i get the message body?
the intent is this:
Bundle[{google.sent_time=1470813025421, from=568540028909,
google.message_id=0:1470813025865549%31bd1c9631bd1c96,
collapse_key=com.google.firebase.quickstart.fcm}]
no message body in intent, only message id!
Thanks!
try this
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// TODO(developer): Handle FCM messages here.
// If the application is in the foreground handle both data and notification messages here.
// Also if you intend on generating your own notifications as a result of a received FCM
// message, here is where that should be initiated. See sendNotification method below.
Log.d(TAG, "From: " + remoteMessage.getFrom());
Log.d(TAG, "From: " + remoteMessage.getData().get("message"));
// Log.d(TAG, "Notification Message Body: " + remoteMessage.getNotification().getBody());
// if you sending data with custom key
Log.d(TAG, "Notification Message of custom key: " +remoteMessage.getData().get("your key"));
sendNotification(remoteMessage.getData().get("message"));
}
I am sorry but what you are trying to do is not possible.
Currently it's not possible to access the (body, title, icon ...) information of a
notification-message from the activity that is launched when the notification is opened.
You can instead access the data component of the notification message.
One possible alternative is to use data-message messages and create your own custom notification and custom logic.
see notification-message vs data-message here:
https://firebase.google.com/docs/cloud-messaging/concept-options#notifications_and_data_messages
PS: if would be useful if you could report a Feature Request through the firebase support page.
In this way the team can correctly prioritize future features.
https://firebase.google.com/support/contact/bugs-features/