I am using Firebase Cloud Messaging to send data notifications to other users. I'm sending a json similar to this:
{
"message":{
"to":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"notification":{
"title":"Portugal vs. Denmark",
"body":"great match!"
},
"data" : {
"type" : "MSG",
"id" : "abcdefg123456...."
}
}
}
And this code to receive notifications:
class MyFirebaseMessagingService : FirebaseMessagingService() {
override fun onMessageReceived(remoteMessage: RemoteMessage) {
remoteMessage.notification?.let { notificacao ->
//How to read payload?
enviarNotificacao(notificacao.title ?: "", notificacao.body ?: "")
}
}
How do I read the data contained in "id" and "type"?
The id and type are both inside a data payload, to be able to read these values then try the following:
override fun onMessageReceived(remoteMessage: RemoteMessage) {
Log.d(TAG, "From: ${remoteMessage.from}")
// Check if message contains a data payload.
remoteMessage.data.isNotEmpty().let {
Log.d(TAG, "Message data payload: " + remoteMessage.data)
}
// Check if message contains a notification payload.
remoteMessage.notification?.let {
Log.d(TAG, "Message Notification Body: ${it.body}")
}
// 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.
}
remoteMessage.data will contain both the id and type
Check here for more info:
https://firebase.google.com/docs/cloud-messaging/android/receive
You can send data this way :
{
"to": "wOAT...",
"data": {
"title": "Notification title",
"message": "Notification message",
"key1" : "value1",
"key2" : "value2",
"key3" : "value3"
}
}
and fetch data this way :
MyFirebaseMessagingService
class MyFirebaseMessagingService : FirebaseMessagingService() {
override fun onMessageReceived(p0: RemoteMessage) {
val data = p0.data
val title = data["title"]
val message = data["message"]
val key1= data["value1"]
val key2= data["value2"]
val key3= data["value3"]
showNotification(title, message, ...)
}
}
Related
When I don't send the notification object in the JSON request to the Firebase API, the onMessageReceive is triggered normally and my notifications work as intended, but, when I use the notification or the android object in the JSON that I send as params the onMessageReceive is not triggered when the app is in background.
I've been trying to debug this but I can't figure it out.
I have a simple class in my server that user Firebase API to send the push notifications.
In the params that I send to the server, I'm sending the following attributes.
"apns": {
"title": title.nil? ? "Testing notification" : title,
"body": body.nil? ? "This is a test push notification, liking it?" : body,
"mutable_content": true,
"sound": sound.nil? ? "enabled" : sound
},
"android": {
"title": title.nil? ? "Testing notification" : title,
"body": body.nil? ? "This is a test push notification, liking it?" : body,
"sound": sound.nil? ? "enabled" : sound
},
or the following for cross plataforms.
"notification": {
"title": title.nil? ? "Testing notification" : title,
"body": body.nil? ? "This is a test push notification, liking it?" : body,
"mutable_content": true,
"sound": sound.nil? ? "enabled" : sound
},
This configuration is suggested by google in the following official documentation
Firebase Documentation
The only way it actually works is when I DO NOT SEND the notification or android object and generate the notification with the data I send in the data attribute of the JSON object sended to the Firebase API
params = {
"#{key}": to,
# "apns": {
# "title": title.nil? ? "Testing notification" : title,
# "body": body.nil? ? "This is a test push notification, liking it?" : body,
# "mutable_content": true,
# "sound": sound.nil? ? "enabled" : sound
# },
# "android": {
# "title": title.nil? ? "Testing notification" : title,
# "body": body.nil? ? "This is a test push notification, liking it?" : body,
# "sound": sound.nil? ? "enabled" : sound
# },
"data": {
"title": title,
"body": body
}
}.to_json
The notifications sent through the Firebase console don't work either.
¿Any ideas?
Use Below Xml Code in andorid manifest
<service
android:name=".services.MyFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
Create MyFirebaseMessaginfService Class to recive Firebase Notification When App is close.
public class MyFirebaseMessagingService extends FirebaseMessagingService {
LocalBroadcastManager broadcaster;
#Override
public void onCreate() {
broadcaster = LocalBroadcastManager.getInstance(this);
}
#Override
public void onNewToken(#NonNull String token) {
Log.d(TAG, "Refreshed token: " + token);
Const.FireBaseTokenID=token;
Log.e(TAG, "onComplete:Service "+Const.FireBaseTokenID );
}
public MyFirebaseMessagingService() {
getFireBaseID();
}
public static void getFireBaseID() {
FirebaseInstanceId.getInstance().getInstanceId()
.addOnCompleteListener(new OnCompleteListener<InstanceIdResult>() {
#Override
public void onComplete(#NonNull Task<InstanceIdResult> task) {
if(!task.isSuccessful()){
Log.w(TAG, "getInstance ID Failed "+task.getException() );
return;
}
String token = task.getResult().getToken();
Log.e(TAG, "onComplete:Service Method "+token );
}
});
}
#Override
public void onMessageReceived(#NonNull RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
String call_api=remoteMessage.getData().get("callapi");
String play_id=remoteMessage.getData().get("play_id");
String clue_number=remoteMessage.getData().get("clue_number");
String title=remoteMessage.getData().toString();
Log.e(TAG, "onMessageReceived: callapi "+call_api );
Log.e(TAG, "onMessageReceived: play_id "+play_id );
Log.e(TAG, "onMessageReceived: clue number "+clue_number );
Log.e(TAG, "onMessageReceived: title "+title );
Intent intent= new Intent("remoteMessage");
intent.putExtra("call_api", call_api);
intent.putExtra("play_id", play_id);
intent.putExtra("clue_number", clue_number);
intent.putExtra("title", title);
broadcaster.sendBroadcast(intent);
}
}
You should send with format data, same:
{
"message":{
"token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"data":{
"Nick" : "Mario",
"body" : "great match!",
"Room" : "PortugalVSDenmark"
}
}
}
I'm trying to get the notification params in onCreate, but I only get the google.* fields.
My FCM Service:
override fun onMessageReceived(message: RemoteMessage?) {
Log.e("Push", Gson().toJson(message))
}
This will show me when app is in foreground:
{
"zza": {
"mMap": {
"google.delivered_priority": "high",
"google.sent_time": 1565619574704,
"google.ttl": 2419200,
"google.original_priority": "high",
"gcm.notification.e": "1",
"gcm.notification.title": "New meeting",
"from": "308737816494",
"gcm.notification.booking_id": "339",
"google.message_id": "0:1565619574708538%545adad5545adad5",
"gcm.notification.body": ".....",
"google.c.a.e": "1"
}
}
}
Notice "gcm.notification.booking_id": "339", this is the field I need.
When app is in background or killed, and I click the notification, I have the next code in my launcher activity:
private fun checkNotifications(intent: Intent?) {
val bookingId = intent?.getStringExtra("gcm.notification.booking_id")
Log.e("Push", "bookind id $bookingId)")
Log.e("PUSH", Gson().toJson(intent?.extras))
The problem is here that I don't get any gcm.* filters, just google.*. And of course that bookindId is null.
{
"mMap": {
"google.delivered_priority": "high",
"google.sent_time": 1565622016732,
"google.ttl": 2419200,
"google.original_priority": "high",
"from": "308737816494",
"google.message_id": "0:1565622016737416%545adad5545adad5",
"collapse_key": "com.wolfpack.planetoffinance"
}
}
Server sided code;
def options
{
notification: {
title: titles[notification.notification_type.to_sym],
body: bodies[notification.notification_type.to_sym],
booking_id: notification.booking_id
}
}
end
```def call
#other_user = other_user
response = FCM_CLIENT.send(registration_ids, options)
notification.user.devices.where(uuid: response[:not_registered_ids]).destroy_all
end
def call
#other_user = other_user
response = FCM_CLIENT.send(registration_ids, options)
notification.user.devices.where(uuid: response[:not_registered_ids]).destroy_all
end
In my project, I need to send a notification from server to client. I am able to send notifications from FCM console but when I send a notification from server to client, remoteMessage.getNotification() always return null. While data is received correctly. When I send both data and notification only data is a non-null while the notification is null.
I already checked this question. But the solution isn't working for me.
Below is a snippet of client and server side code along with a screenshot while debugging client app.
Client App:(onMessageReceived)
override fun onMessageReceived(remoteMessage: RemoteMessage?) {
super.onMessageReceived(remoteMessage)
Log.e(TAG, "From: " + remoteMessage?.from)
// Check if message contains a data payload.
if ((remoteMessage?.data?.size ?: 0) > 0) {
Log.e(TAG, "Message data payload: ${remoteMessage?.data}")
}
val a = remoteMessage?.notification
if (a != null) {
Log.e(TAG, "Message Notification Body: " + remoteMessage.notification?.body)
}
}
server side code(node.js)
var request = require('request');
// Set the headers
var headers = {
'Content-Type':'application/json',
'Authorization': 'key=AIzaSyAzMLMp....'
}
// Configure the request
var options = {
url: 'https://fcm.googleapis.com/fcm/send',
method: 'POST',
headers: headers,
form: {
"to": "eZoeSIRba6g:AP...",
"notification" : { "body" : "my body"} }
}
// Start the request
request(options, function (error, response, body) {
if (!error && response.statusCode == 200) {
// Print out the response body
console.log(body)
}
console.log(body + " error : " + error)
})
while if I use following part then the code works fine.
form: {
"to": "eZoeSIRba6g:APA91bEYrP...",
"data" : { "body" : "my body"} }
Screenshot while debugging the app.(Check value of variable 'a')
If someone has any idea of how to resolve this issue then please help me.
Thank you in advance.
{
"to" : "YOUR_FCM_TOKEN_WILL_BE_HERE",
"data" : {
"body" : "First Notification",
"title": "Collapsing A",
"key_1" : "Data for key one",
"key_2" : "Hellowww"
}
}
Use a JSON like this , then your onMessageReceived will be called.
I send from Firebase Messages in this structure:
{
"to": "/topics/myapp",
"data": {
"id" : "id123",
"title" : "lksdjkrfrfrereflsjd",
"body" : "fsdfsd",
"de": {
"key1" : "val1",
"key2" : "val2"
},
"en": {
"key3" : "val3",
"key4" : "val4"
}
}
}
in my override fun onMessageReceived(remoteMessage: RemoteMessage?) method my remoteMessage object has a data field which is from type: Map<String, String>
How can I access de and en from remoteMessage ?
EDIT: It is developed for Android
I'm trying to use the Firebase Cloud Messaging. I send the notifications from a Node.js server to my apps that are registered to the notification system.
My problem is that on Android 5.1 the notification is "FCM Message" even if I setted the title attribute in the nofitification json. It works fine in Android 6.0. I tried to reboot my device as well.
And this is the code I use to send the notification:
function sendNotificationToUser(userToken, message, onSuccess) {
request({
url: 'https://fcm.googleapis.com/fcm/send',
method: 'POST',
headers: {
'Content-Type' :' application/json',
'Authorization': 'key='+API_KEY
},
body: JSON.stringify({
notification: {
"title": 'My App Name',
"body": message,
"sound": 'default'
},
to : userToken
})
}, function(error, response, body) {
if (error) { console.error(error); }
else if (response.statusCode >= 400) {
console.error('HTTP Error: '+response.statusCode+' - '+response.statusMessage);
}
else {
onSuccess();
}
});
}
As you can see the notification title I send is "My App Name" but on device it shows "FCM Message".
What do I have to do?!
You need to pass the title and then receive it in remoteMessage.getNotification().getTitle() , this will catch title and then display in the top or pass complete JSON from web and receive like this
JSONObject jsonObject = new JSONObject(remoteMessage.getData());
Here is the complete method:
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// ...
// TODO(developer): Handle FCM messages here.
// Not getting messages here? See why this may be: https://firebase.google.com/support/faq/#fcm-android-background
Log.d(TAG, "From: " + remoteMessage.getFrom());
// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
}
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
}
// 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.
}
Ref link
I found that it is a problem related to onMessageReceived callback.
As you can see on the receive a FCM guide
This is expected. (Tested upto Android 10)
FCM has different behaviours for app status (foreground and background / killed).
You should handle this by the payload you sent from server, according to your use case.
The msg sent from server has to be sent in either "notification" or "data" format, from dashboard or server side api.
Note: From firebase dashobard you can only send "notification" body and not data. In such cases, FCM will directly display the notif without giving a callback to your app.
Server side
Below are sample formats :
Notification Type Format
Note : Android System will by default display the notification in the notification tray and you don't need to display it.
{
"to": "your_token_id",
"notification" : {
"title" : "FCM Notification title!",
"body" : "FCM Notification subtext!",
"content_available" : true,
"priority" : "high"
}
}
Data Format (For receiving callback in app, in foreground and background)
Note : You have to handle callback and display notif on your own.
{
"to": "your_token_id",
"data" : {
"title" : "FCM Notification Title ",
"subtext" : "FCM Notification Sub Title",
"type" : "999",
"priority" : "high"
}
}
Android Client
To handle the payload received in your Android receiver, checl the official guide here
override fun onMessageReceived(remoteMessage: RemoteMessage) {
Log.d(TAG, "From: ${remoteMessage.from}")
// Check if message contains a data payload.
remoteMessage.data.isNotEmpty().let {
Log.d(TAG, "Message data payload: " + remoteMessage.data)
if (/* Check if data needs to be processed by long running job */ true) {
// For long-running tasks (10 seconds or more) use WorkManager.
scheduleJob()
} else {
// Handle message within 10 seconds
handleNow()
}
}
// Check if message contains a notification payload.
remoteMessage.notification?.let {
Log.d(TAG, "Message Notification Body: ${it.body}")
}
// 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.
}
Check the documentation here
This is how i get the title from remote messages:
var title = ""
override fun onMessageReceived(remoteMessage: RemoteMessage) {
if (remoteMessage.notification != null) {
title = remoteMessage.notification!!.title!!
}
}
val notificationBuilder = NotificationCompat.Builder(applicationContext, channelId)
.setContentTitle(title)