Related
I'm sending notification using a firebase cloud function. When I'm sending the payload with notification key, notification sends but method not invoked. But with data key, nothing happened.
Here is my code for FirebaseMessagingService
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
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());
sendNotification(remoteMessage.getData().get("title"), remoteMessage.getData().get("body"));
if (/* Check if data needs to be processed by long running job */ true) {
// For long-running tasks (10 seconds or more) use Firebase Job Dispatcher.
scheduleJob();
} else {
// Handle message within 10 seconds
handleNow();
}
}
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
sendNotification(remoteMessage.getNotification().getTitle(), remoteMessage.getNotification().getBody());
}
}
private void sendNotification(String title, String messageBody){
String channelId = getString(R.string.default_notification_channel_id);
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent,
PendingIntent.FLAG_ONE_SHOT);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.drawable.ic_logo)
.setContentTitle(title)
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// Since android Oreo notification channel is needed.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(channelId,
"Channel human readable title",
NotificationManager.IMPORTANCE_DEFAULT);
notificationManager.createNotificationChannel(channel);
}
notificationManager.notify(0 , notificationBuilder.build());
}
Here is my firebase cloud function
exports.sendNotification = functions.database
.ref("/deals/{userId}/{dealId}")
.onCreate((data, context) => {
const dataValue = data.val();
const topic = context.params.userId;
const payload = {
data: {
title: "New deal created",
body: dataValue.user.name + " added a new deal."
},
topic: topic
};
// Send a message to devices subscribed to the provided topic.
return admin
.messaging()
.send(payload)
.then(response => {
// Response is a message ID string.
console.log("Successfully sent message:", response);
})
.catch(error => {
console.log("Error sending message:", error);
});
});
Also I set up a debugpoint on onMessageReceived() but it did not get fired up.
I figured out the problem. The issue is after doing some changes and building the android project we need to subscribe to topic again.
When your app is in background , firebase will not trigger
OnMessageReceived instead it will show a notification alert
+
make sure you have subscribed the correct topic
+
make sure play services are updated on your device.
I'm building an Android app which will receive push notifications. I've got Firebase Cloud Messaging setup and pretty much working, such that I can send the following payload to a valid token and the notification and data are received.
Using url https://fcm.googleapis.com/fcm/send
{
"to":"<valid-token>",
"notification":{"body":"BODY TEXT","title":"TITLE TEXT","sound":"default"},
"data":{"message":"This is some data"}
}
My app receives it correctly and can deal with it.
The only slight wrinkle is that I get the following exception thrown in the debug:
Error while parsing timestamp in GCM event
java.lang.NumberFormatException: Invalid int: "null"
at java.lang.Integer.invalidInt(Integer.java:138)
...
It doesn't crash the app, it just looks untidy.
I've tried adding a timestamp item to the main payload, the notification, the data, and also tried variations such as time but can't seem to get rid of the exception (and google as I might, I can't find an answer).
How do I pass the timestamp so it stops complaining?
Edited: Here is my onMessageReceived method, but I think the exception is thrown before it gets here
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
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());
//TODO Handle the data
}
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
}
}
Thanks in advance,
Chris
Even though notification is apparently a supported element (according to the Firebase web docs), the only way I could get rid of the exception was to remove it entirely, and use the data section only, and then in my app create a notification (rather than letting firebase do the notification).
I used this site to work out how to raise the notifications: https://www.androidhive.info/2012/10/android-push-notifications-using-google-cloud-messaging-gcm-php-and-mysql/
My notification now looks like the following:
$fields = array("to" => "<valid-token>",
"data" => array("data"=>
array(
"message"=>"This is some data",
"title"=>"This is the title",
"is_background"=>false,
"payload"=>array("my-data-item"=>"my-data-value"),
"timestamp"=>date('Y-m-d G:i:s')
)
)
);
...
<curl stuff here>
...
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
My onMessageReceived looks like this:
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d(TAG, "From: " + remoteMessage.getFrom());
// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
Log.e(TAG, "Data Payload: " + remoteMessage.getData().toString());
try {
JSONObject json = new JSONObject(remoteMessage.getData().toString());
handleDataMessage(json);
} catch (Exception e) {
Log.e(TAG, "Exception: " + e.getMessage());
}
}
}
which calls handleDataMessage which looks like this:
private void handleDataMessage(JSONObject json) {
Log.e(TAG, "push json: " + json.toString());
try {
JSONObject data = json.getJSONObject("data");
String title = data.getString("title");
String message = data.getString("message");
boolean isBackground = data.getBoolean("is_background");
String timestamp = data.getString("timestamp");
JSONObject payload = data.getJSONObject("payload");
// play notification sound
NotificationUtils notificationUtils = new NotificationUtils(getApplicationContext());
notificationUtils.playNotificationSound();
if (!NotificationUtils.isBackgroundRunning(getApplicationContext())) {
// app is in foreground, broadcast the push message
Intent pushNotification = new Intent(ntcAppManager.PUSH_NOTIFICATION);
pushNotification.putExtra("message", message);
LocalBroadcastManager.getInstance(this).sendBroadcast(pushNotification);
} else {
// app is in background, show the notification in notification tray
Intent resultIntent = new Intent(getApplicationContext(), MainActivity.class);
resultIntent.putExtra("message", message);
showNotificationMessage(getApplicationContext(), title, message, timestamp, resultIntent);
}
} catch (JSONException e) {
Log.e(TAG, "Json Exception: " + e.getMessage());
} catch (Exception e) {
Log.e(TAG, "Exception: " + e.getMessage());
}
}
this then calls showNotificationMessage
/**
* Showing notification with text only
*/
private void showNotificationMessage(Context context, String title, String message, String timeStamp, Intent intent) {
notificationUtils = new NotificationUtils(context);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
notificationUtils.showNotificationMessage(title, message, timeStamp, intent);
}
And subsequently notificationUtils.showNotificationMessage
public void showNotificationMessage(String title, String message, String timeStamp, Intent intent) {
showNotificationMessage(title, message, timeStamp, intent, null);
}
public void showNotificationMessage(final String title, final String message, final String timeStamp, Intent intent, String imageUrl) {
// Check for empty push message
if (TextUtils.isEmpty(message))
return;
// notification icon
final int icon = R.mipmap.ic_launcher;
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
final PendingIntent resultPendingIntent =
PendingIntent.getActivity(
mContext,
0,
intent,
PendingIntent.FLAG_CANCEL_CURRENT
);
final NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
mContext);
final Uri alarmSound = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE
+ "://" + mContext.getPackageName() + "/raw/notification");
showSmallNotification(mBuilder, icon, title, message, timeStamp, resultPendingIntent, alarmSound);
playNotificationSound();
}
private void showSmallNotification(NotificationCompat.Builder mBuilder, int icon, String title, String message, String timeStamp, PendingIntent resultPendingIntent, Uri alarmSound) {
NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();
inboxStyle.addLine(message);
Notification notification;
notification = mBuilder.setSmallIcon(icon).setTicker(title).setWhen(0)
.setAutoCancel(true)
.setContentTitle(title)
.setContentIntent(resultPendingIntent)
.setSound(alarmSound)
.setStyle(inboxStyle)
.setWhen(getTimeMilliSec(timeStamp))
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(mContext.getResources(), icon))
.setContentText(message)
.build();
NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(ntcAppManager.NOTIFICATION_ID, notification);
}
More detail in the link above, and it's a lot of handling but at least the exception's gone and I'm in control of the notifications.
I've updated com.google.firebase:firebase-messaging to 17.3.4 and issue disappeared.
I was running into this same error, I resolved by adding a ttl value to the payload.
{
"to":"<valid-token>",
"notification":{"body":"BODY TEXT","title":"TITLE TEXT","sound":"default"},
"data":{"message":"This is some data"},
"ttl": 3600
}
I had the same problem, I've just set "body" parameter in notification and error dissapeared.
What worked for me:
Upgrading, not only firebase-messaging, but all Firebase libraries to the last version. In android/app/build.gradle:
dependencies {
implementation "com.google.firebase:firebase-core:16.0.0" // upgraded
implementation "com.google.firebase:firebase-analytics:16.0.0" // upgraded
implementation 'com.google.firebase:firebase-messaging:17.3.4' // upgraded
// ...
implementation "com.google.firebase:firebase-invites:16.0.0" // upgraded
// ...
}
Not all of them are at version 17.x
Format below (no notification body, nor are there any arrays) fixed the timestamp exception for me:
{
"to": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
"data": {
"message": "message",
"title": "hello",
}
}
Tested fine with http://pushtry.com/
The only reason I included the long 'eeee...' is that is the exact size of my token.
replace
"notification" : {
"title" : "title !",
"body" : "body !",
"sound" : "default"
},
"condition" : "'xxx' in topics",
"priority" : "high",
"data" : {
....
by (remove notification) :
{
"condition" : "'xxxx' in topics",
"priority" : "high",
"data" : {
"title" : "title ! ",
"body" : "BODY",
......
}
And on you code :
Replace :
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
remoteMessage.getNotification().getTitle();
remoteMessage.getNotification().getBody();
}
by
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
remoteMessage.getData().get("title");
remoteMessage.getData().get("body");
}
In my case My error was "AndrodManifest.xml"
I miss one service (actually Android studio's firebase assistant is missing my permission. :) )
original
<service android:name=".fcm.MyFirebaseInstanceIDService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
</application>
solution
<service android:name=".fcm.MyFirebaseInstanceIDService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
<service android:name=".fcm.MyFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
</application>
I'm building an Android app which will receive push notifications. I've got Firebase Cloud Messaging setup and pretty much working, such that I can send the following payload to a valid token and the notification and data are received.
Using url https://fcm.googleapis.com/fcm/send
{
"to":"<valid-token>",
"notification":{"body":"BODY TEXT","title":"TITLE TEXT","sound":"default"},
"data":{"message":"This is some data"}
}
My app receives it correctly and can deal with it.
The only slight wrinkle is that I get the following exception thrown in the debug:
Error while parsing timestamp in GCM event
java.lang.NumberFormatException: Invalid int: "null"
at java.lang.Integer.invalidInt(Integer.java:138)
...
It doesn't crash the app, it just looks untidy.
I've tried adding a timestamp item to the main payload, the notification, the data, and also tried variations such as time but can't seem to get rid of the exception (and google as I might, I can't find an answer).
How do I pass the timestamp so it stops complaining?
Edited: Here is my onMessageReceived method, but I think the exception is thrown before it gets here
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
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());
//TODO Handle the data
}
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
}
}
Thanks in advance,
Chris
Even though notification is apparently a supported element (according to the Firebase web docs), the only way I could get rid of the exception was to remove it entirely, and use the data section only, and then in my app create a notification (rather than letting firebase do the notification).
I used this site to work out how to raise the notifications: https://www.androidhive.info/2012/10/android-push-notifications-using-google-cloud-messaging-gcm-php-and-mysql/
My notification now looks like the following:
$fields = array("to" => "<valid-token>",
"data" => array("data"=>
array(
"message"=>"This is some data",
"title"=>"This is the title",
"is_background"=>false,
"payload"=>array("my-data-item"=>"my-data-value"),
"timestamp"=>date('Y-m-d G:i:s')
)
)
);
...
<curl stuff here>
...
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
My onMessageReceived looks like this:
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d(TAG, "From: " + remoteMessage.getFrom());
// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
Log.e(TAG, "Data Payload: " + remoteMessage.getData().toString());
try {
JSONObject json = new JSONObject(remoteMessage.getData().toString());
handleDataMessage(json);
} catch (Exception e) {
Log.e(TAG, "Exception: " + e.getMessage());
}
}
}
which calls handleDataMessage which looks like this:
private void handleDataMessage(JSONObject json) {
Log.e(TAG, "push json: " + json.toString());
try {
JSONObject data = json.getJSONObject("data");
String title = data.getString("title");
String message = data.getString("message");
boolean isBackground = data.getBoolean("is_background");
String timestamp = data.getString("timestamp");
JSONObject payload = data.getJSONObject("payload");
// play notification sound
NotificationUtils notificationUtils = new NotificationUtils(getApplicationContext());
notificationUtils.playNotificationSound();
if (!NotificationUtils.isBackgroundRunning(getApplicationContext())) {
// app is in foreground, broadcast the push message
Intent pushNotification = new Intent(ntcAppManager.PUSH_NOTIFICATION);
pushNotification.putExtra("message", message);
LocalBroadcastManager.getInstance(this).sendBroadcast(pushNotification);
} else {
// app is in background, show the notification in notification tray
Intent resultIntent = new Intent(getApplicationContext(), MainActivity.class);
resultIntent.putExtra("message", message);
showNotificationMessage(getApplicationContext(), title, message, timestamp, resultIntent);
}
} catch (JSONException e) {
Log.e(TAG, "Json Exception: " + e.getMessage());
} catch (Exception e) {
Log.e(TAG, "Exception: " + e.getMessage());
}
}
this then calls showNotificationMessage
/**
* Showing notification with text only
*/
private void showNotificationMessage(Context context, String title, String message, String timeStamp, Intent intent) {
notificationUtils = new NotificationUtils(context);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
notificationUtils.showNotificationMessage(title, message, timeStamp, intent);
}
And subsequently notificationUtils.showNotificationMessage
public void showNotificationMessage(String title, String message, String timeStamp, Intent intent) {
showNotificationMessage(title, message, timeStamp, intent, null);
}
public void showNotificationMessage(final String title, final String message, final String timeStamp, Intent intent, String imageUrl) {
// Check for empty push message
if (TextUtils.isEmpty(message))
return;
// notification icon
final int icon = R.mipmap.ic_launcher;
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
final PendingIntent resultPendingIntent =
PendingIntent.getActivity(
mContext,
0,
intent,
PendingIntent.FLAG_CANCEL_CURRENT
);
final NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
mContext);
final Uri alarmSound = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE
+ "://" + mContext.getPackageName() + "/raw/notification");
showSmallNotification(mBuilder, icon, title, message, timeStamp, resultPendingIntent, alarmSound);
playNotificationSound();
}
private void showSmallNotification(NotificationCompat.Builder mBuilder, int icon, String title, String message, String timeStamp, PendingIntent resultPendingIntent, Uri alarmSound) {
NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();
inboxStyle.addLine(message);
Notification notification;
notification = mBuilder.setSmallIcon(icon).setTicker(title).setWhen(0)
.setAutoCancel(true)
.setContentTitle(title)
.setContentIntent(resultPendingIntent)
.setSound(alarmSound)
.setStyle(inboxStyle)
.setWhen(getTimeMilliSec(timeStamp))
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(mContext.getResources(), icon))
.setContentText(message)
.build();
NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(ntcAppManager.NOTIFICATION_ID, notification);
}
More detail in the link above, and it's a lot of handling but at least the exception's gone and I'm in control of the notifications.
I've updated com.google.firebase:firebase-messaging to 17.3.4 and issue disappeared.
I was running into this same error, I resolved by adding a ttl value to the payload.
{
"to":"<valid-token>",
"notification":{"body":"BODY TEXT","title":"TITLE TEXT","sound":"default"},
"data":{"message":"This is some data"},
"ttl": 3600
}
I had the same problem, I've just set "body" parameter in notification and error dissapeared.
What worked for me:
Upgrading, not only firebase-messaging, but all Firebase libraries to the last version. In android/app/build.gradle:
dependencies {
implementation "com.google.firebase:firebase-core:16.0.0" // upgraded
implementation "com.google.firebase:firebase-analytics:16.0.0" // upgraded
implementation 'com.google.firebase:firebase-messaging:17.3.4' // upgraded
// ...
implementation "com.google.firebase:firebase-invites:16.0.0" // upgraded
// ...
}
Not all of them are at version 17.x
Format below (no notification body, nor are there any arrays) fixed the timestamp exception for me:
{
"to": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
"data": {
"message": "message",
"title": "hello",
}
}
Tested fine with http://pushtry.com/
The only reason I included the long 'eeee...' is that is the exact size of my token.
replace
"notification" : {
"title" : "title !",
"body" : "body !",
"sound" : "default"
},
"condition" : "'xxx' in topics",
"priority" : "high",
"data" : {
....
by (remove notification) :
{
"condition" : "'xxxx' in topics",
"priority" : "high",
"data" : {
"title" : "title ! ",
"body" : "BODY",
......
}
And on you code :
Replace :
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
remoteMessage.getNotification().getTitle();
remoteMessage.getNotification().getBody();
}
by
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
remoteMessage.getData().get("title");
remoteMessage.getData().get("body");
}
In my case My error was "AndrodManifest.xml"
I miss one service (actually Android studio's firebase assistant is missing my permission. :) )
original
<service android:name=".fcm.MyFirebaseInstanceIDService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
</application>
solution
<service android:name=".fcm.MyFirebaseInstanceIDService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
<service android:name=".fcm.MyFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
</application>
I'm building an Android app which will receive push notifications. I've got Firebase Cloud Messaging setup and pretty much working, such that I can send the following payload to a valid token and the notification and data are received.
Using url https://fcm.googleapis.com/fcm/send
{
"to":"<valid-token>",
"notification":{"body":"BODY TEXT","title":"TITLE TEXT","sound":"default"},
"data":{"message":"This is some data"}
}
My app receives it correctly and can deal with it.
The only slight wrinkle is that I get the following exception thrown in the debug:
Error while parsing timestamp in GCM event
java.lang.NumberFormatException: Invalid int: "null"
at java.lang.Integer.invalidInt(Integer.java:138)
...
It doesn't crash the app, it just looks untidy.
I've tried adding a timestamp item to the main payload, the notification, the data, and also tried variations such as time but can't seem to get rid of the exception (and google as I might, I can't find an answer).
How do I pass the timestamp so it stops complaining?
Edited: Here is my onMessageReceived method, but I think the exception is thrown before it gets here
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
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());
//TODO Handle the data
}
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
}
}
Thanks in advance,
Chris
Even though notification is apparently a supported element (according to the Firebase web docs), the only way I could get rid of the exception was to remove it entirely, and use the data section only, and then in my app create a notification (rather than letting firebase do the notification).
I used this site to work out how to raise the notifications: https://www.androidhive.info/2012/10/android-push-notifications-using-google-cloud-messaging-gcm-php-and-mysql/
My notification now looks like the following:
$fields = array("to" => "<valid-token>",
"data" => array("data"=>
array(
"message"=>"This is some data",
"title"=>"This is the title",
"is_background"=>false,
"payload"=>array("my-data-item"=>"my-data-value"),
"timestamp"=>date('Y-m-d G:i:s')
)
)
);
...
<curl stuff here>
...
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
My onMessageReceived looks like this:
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d(TAG, "From: " + remoteMessage.getFrom());
// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
Log.e(TAG, "Data Payload: " + remoteMessage.getData().toString());
try {
JSONObject json = new JSONObject(remoteMessage.getData().toString());
handleDataMessage(json);
} catch (Exception e) {
Log.e(TAG, "Exception: " + e.getMessage());
}
}
}
which calls handleDataMessage which looks like this:
private void handleDataMessage(JSONObject json) {
Log.e(TAG, "push json: " + json.toString());
try {
JSONObject data = json.getJSONObject("data");
String title = data.getString("title");
String message = data.getString("message");
boolean isBackground = data.getBoolean("is_background");
String timestamp = data.getString("timestamp");
JSONObject payload = data.getJSONObject("payload");
// play notification sound
NotificationUtils notificationUtils = new NotificationUtils(getApplicationContext());
notificationUtils.playNotificationSound();
if (!NotificationUtils.isBackgroundRunning(getApplicationContext())) {
// app is in foreground, broadcast the push message
Intent pushNotification = new Intent(ntcAppManager.PUSH_NOTIFICATION);
pushNotification.putExtra("message", message);
LocalBroadcastManager.getInstance(this).sendBroadcast(pushNotification);
} else {
// app is in background, show the notification in notification tray
Intent resultIntent = new Intent(getApplicationContext(), MainActivity.class);
resultIntent.putExtra("message", message);
showNotificationMessage(getApplicationContext(), title, message, timestamp, resultIntent);
}
} catch (JSONException e) {
Log.e(TAG, "Json Exception: " + e.getMessage());
} catch (Exception e) {
Log.e(TAG, "Exception: " + e.getMessage());
}
}
this then calls showNotificationMessage
/**
* Showing notification with text only
*/
private void showNotificationMessage(Context context, String title, String message, String timeStamp, Intent intent) {
notificationUtils = new NotificationUtils(context);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
notificationUtils.showNotificationMessage(title, message, timeStamp, intent);
}
And subsequently notificationUtils.showNotificationMessage
public void showNotificationMessage(String title, String message, String timeStamp, Intent intent) {
showNotificationMessage(title, message, timeStamp, intent, null);
}
public void showNotificationMessage(final String title, final String message, final String timeStamp, Intent intent, String imageUrl) {
// Check for empty push message
if (TextUtils.isEmpty(message))
return;
// notification icon
final int icon = R.mipmap.ic_launcher;
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
final PendingIntent resultPendingIntent =
PendingIntent.getActivity(
mContext,
0,
intent,
PendingIntent.FLAG_CANCEL_CURRENT
);
final NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
mContext);
final Uri alarmSound = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE
+ "://" + mContext.getPackageName() + "/raw/notification");
showSmallNotification(mBuilder, icon, title, message, timeStamp, resultPendingIntent, alarmSound);
playNotificationSound();
}
private void showSmallNotification(NotificationCompat.Builder mBuilder, int icon, String title, String message, String timeStamp, PendingIntent resultPendingIntent, Uri alarmSound) {
NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();
inboxStyle.addLine(message);
Notification notification;
notification = mBuilder.setSmallIcon(icon).setTicker(title).setWhen(0)
.setAutoCancel(true)
.setContentTitle(title)
.setContentIntent(resultPendingIntent)
.setSound(alarmSound)
.setStyle(inboxStyle)
.setWhen(getTimeMilliSec(timeStamp))
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(mContext.getResources(), icon))
.setContentText(message)
.build();
NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(ntcAppManager.NOTIFICATION_ID, notification);
}
More detail in the link above, and it's a lot of handling but at least the exception's gone and I'm in control of the notifications.
I've updated com.google.firebase:firebase-messaging to 17.3.4 and issue disappeared.
I was running into this same error, I resolved by adding a ttl value to the payload.
{
"to":"<valid-token>",
"notification":{"body":"BODY TEXT","title":"TITLE TEXT","sound":"default"},
"data":{"message":"This is some data"},
"ttl": 3600
}
I had the same problem, I've just set "body" parameter in notification and error dissapeared.
What worked for me:
Upgrading, not only firebase-messaging, but all Firebase libraries to the last version. In android/app/build.gradle:
dependencies {
implementation "com.google.firebase:firebase-core:16.0.0" // upgraded
implementation "com.google.firebase:firebase-analytics:16.0.0" // upgraded
implementation 'com.google.firebase:firebase-messaging:17.3.4' // upgraded
// ...
implementation "com.google.firebase:firebase-invites:16.0.0" // upgraded
// ...
}
Not all of them are at version 17.x
Format below (no notification body, nor are there any arrays) fixed the timestamp exception for me:
{
"to": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
"data": {
"message": "message",
"title": "hello",
}
}
Tested fine with http://pushtry.com/
The only reason I included the long 'eeee...' is that is the exact size of my token.
replace
"notification" : {
"title" : "title !",
"body" : "body !",
"sound" : "default"
},
"condition" : "'xxx' in topics",
"priority" : "high",
"data" : {
....
by (remove notification) :
{
"condition" : "'xxxx' in topics",
"priority" : "high",
"data" : {
"title" : "title ! ",
"body" : "BODY",
......
}
And on you code :
Replace :
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
remoteMessage.getNotification().getTitle();
remoteMessage.getNotification().getBody();
}
by
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
remoteMessage.getData().get("title");
remoteMessage.getData().get("body");
}
In my case My error was "AndrodManifest.xml"
I miss one service (actually Android studio's firebase assistant is missing my permission. :) )
original
<service android:name=".fcm.MyFirebaseInstanceIDService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
</application>
solution
<service android:name=".fcm.MyFirebaseInstanceIDService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
<service android:name=".fcm.MyFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
</application>
I am making a simple messaging app using firebase cloud messaging service but and I am using cloud functions to handle the notifications, however whenever I test it it always says successful in the logs but the devices receive nothing
Here is the cloud function used :
exports.sendNotifications = functions.database.ref('/meesages/{messageId}').onCreate(event => {
var eventSnapshot = event.data;
var str1 = "Sender : ";
var str = str1.concat(eventSnapshot.child("messageOwner").val());
console.log(str);
var topic = "Messaging";
var payload = {
notification: {
Message: eventSnapshot.child("messageText").val(),
Sender: eventSnapshot.child("messageOwner").val()
}
};
// Send a message to devices subscribed to the provided topic.
return admin.messaging().sendToTopic(topic,payload)
.then(function (response) {
// See the MessagingTopicResponse reference documentation for the
// contents of response.
console.log("Successfully sent message:", response);
})
.catch(function (error) {
console.log("Error sending message:", error);
});
});
Here is the class responsible for handling the notifications part on the android device :
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
showNotification(remoteMessage.getData().get("Sender"), remoteMessage.getData().get("Message"));
}
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
}
}
#Override
public void onDeletedMessages() {
super.onDeletedMessages();
}
private void showNotification(String Message, String Sender) {
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);
Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = (NotificationCompat.Builder) new NotificationCompat.Builder(this)
.setContentTitle("New message : " + Message)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentText("By : " + Sender)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}
}
and yes I made sure to add the topic subscription in the mainactivity class
FirebaseMessaging.getInstance().subscribeToTopic("Messaging");
so what is exactly wrong here ??
The code in onMessageReceived() expects the message to have a data payload. This is explained in the documentation, which includes three tabs, showing notification, data, and combined payloads. Change notification to data:
var payload = {
data: {
Message: eventSnapshot.child("messageText").val(),
Sender: eventSnapshot.child("messageOwner").val()
}
};