I am using two firebase database projects. I have to send notifications from one database(Project-A) to another database(Project-B). I am sending notifications through API calls in cloud functions( in Project-A) and have to receive in IOS device ( from Project-B). I am sending the device token which is generated by using Project-A's SenderId through API call and saving that token in Project-A's database. In Project-A, using cloud function I am sending a notification to the IOS device in Project-B. In Project-A's firebase console it showing the notification is successfully sent, but in the receiver side, I am not getting any notification.
Payload:
let payload = {
notification: {
title: "Notification Alert",
body: "Notification Body",
sound: "default",
},
'data':{// these is the data it calls in the messagereceived method
'SenderID':senderauthid,
'ReceiverId':receiverauthid,
'SenderPhoneNumber':String(senderphonenumber),
'SenderName':Sendertotalname,
'flag':"3",
}
};//payload
return admin.messaging().sendToDevice(RegisterationTokens, payload).then((response)=> {
console.info("Successfully sent notification")
return res.status(200).json({Token : "Successfully sent notification"});
}).catch(function(error) {
console.warn("Error sending notification " , error)
});//end of notification
On successful notification message sent, I am receiving an error message stating that
errorInfo:
{ code: 'messaging/invalid-apns-credentials',
message: 'A message targeted to an iOS device could not be sent because the required APNs SSL certificate was not uploaded or has expired. Check the validity of your development and production certificates.' },
codePrefix: 'messaging' }
I have already added "APNs Auth Keys" in "APNs Authentication Key" section in firebase console. Do I have to make any changes?
Related
I have a Cloud Functions environment that sends data and notification messages.
At the moment, I am testing FCM messages on an iPhone SE (2016) and an iPhone 7 Plus - and the behaviour is very inconsistent between the 2 devices and I'd like to know why.
iPhone SE (2016) is running iOS 14 beta 1
iPhone 7 Plus is running iOS 14 beta 3
The following cloud function sends a notification and data message - both of these successfully get delivered to both devices:
// These options are global for all my fcm messages
const options = { priority: "high", timeToLive: 30000, content_available: true }
function sendProfile() {
...
const fcmToken = ********
const notif = {
notification: {
title: "test title",
body: "test body"
}
}
admin.messaging().sendToDevice(fcmToken, notif, options);
const dataMsg = {
data: {
id: id,
type: "match",
uid: uid,
name: name,
age: age.toString(),
bio: bio,
img1: String(img1),
img2: String(img2),
img3: String(img3),
pronoun: pronoun,
error: String(bot)
}
}
return admin.messaging().sendToDevice(fcmToken, dataMsg, options);
}
However for the following function:
The notification message successfully gets delivered to both devices
But the data message only gets delivered to the iPhone SE (not the iPhone 7 Plus)
function sendPlace(fcmToken, placeSnapshot, matchName){
let docId = placeSnapshot.id;
let place = placeSnapshot.data();
console.log("sendPlacee: ", place.name, " to: ", fcmToken);
const dataMsg = {
data: {
type: "place",
name: place.name,
latitude: place.l.latitude.toString(),
longitude: place.l.longitude.toString(),
instruction: String(place.instruction),
placeId: docId,
picture: String(place.picture1),
matchName: matchName,
address: place.address
}
}
const notif = {
notification: {
title: "test place function",
body: "test the body message"
}
}
admin.messaging().sendToDevice(fcmToken, notif, options)
return admin.messaging().sendToDevice(fcmToken, dataMsg, options)
}
Only when I remove some of the payload, it successfully sends to the iPhone 7 Plus (I removed the instruction, picture and address key values from the data payload - and then it worked).
Any idea what the problem is here?
Edit: There are no problems with my Android devices.
The Firebase Cloud Messaging relies to the Apple Push Notification service (APNs) to send messages (up to 4KB in size) to the iOS app. In iOS, notifications and data messages are treated differently, in particular:
Notification message: FCM automatically displays the message to end-user devices on behalf of the client app. No callback is generated in this case on the app until the user taps on the notification opening the app (in this case the userNotificationCenter(_:didReceive:withCompletionHandler:) callback is triggered)
Data message:
Data messages are converted by the FCM layer in the so-called background notifications ("content-available" : true). A background notification is a remote notification that doesn’t display an alert, play a sound, or badge your app’s icon, in this case client app is responsible for processing data messages. This kind of notification is designed to wake your app in the background giving it time to initiate downloads from your server and update its content. When a "data" ("background") notification is sent, the callback application(_:didReceiveRemoteNotification:fetchCompletionHandler:) is fired at the time the notification arrives and no sound or alert are triggered automatically. However, take into account this important note from the Apple docs:
The system treats background notifications as low priority: you can use them to refresh your app’s content, but the system doesn’t guarantee their delivery. In addition, the system may throttle the delivery of background notifications if the total number becomes excessive. The number of background notifications allowed by the system depends on current conditions, but don’t try to send more than two or three per hour.
So the problem could be related to the particular conditions of your phones: notifications messages are correctly delivered to both phones but, maybe, the iPhone 7 Plus os is throttling or delaying the reception of the data ones.
Check this blog if you can find some information on the FCM messaging and if you can figure out any issue relates to iPhone 7 plus device where you had to reduce the payload.
https://firebase.googleblog.com/2019/02/life-of-a-message.html
I can send test notifications from Firebase console to my app both on iOS and Android. Therefore, my app is set up properly to receive push notifications on both platforms. However, when I use a cloud function to send notifications. Only, notifications on the Android device are received. No notifications show up on the iOS device. I suspect this may be related to the way that I create the payload in my cloud function. Maybe I am missing something for iOS. If you could give me some tips, that would be great.
I checked if the deviceToken for the iOS device is correct and it was correct.
I sent a test message using firebase console to the same deviceToken for the iOS device and the notification was delivered.
Therefore, I concluded my problem may arise from the cloud function I wrote. Thus, I share below the cloud function:
exports.notifToApp = functions.database.
ref(`/memInfo/{memId}/notifChoice/`).onWrite((snap, context) => {
//send only if exists and new notification OR if doesn't exist
if ((snap.before.exists() && (snap.after.val() !== snap.before.val())) || !snap.before.exists()) {
//get notification body
const notificationTitle = snap.after.val().memName;
const notificationText = snap.after.val().notifText;
//get and loop over notification subscribers
return admin.database().ref(`/notifics/${context.params.memId}/notifSubs/`).once("value", subs => {
if (subs.exists()) {
return subs.forEach(sub => {
//payload for notification
const payload = {
"notification":{
"title": notificationTitle,
"body": notificationText,
"sound": "default",
"click-action": "FCM_PLUGIN_ACTIVITY",
"priority": "high"
}
}
//deliver notification
return admin.messaging().sendToDevice(sub.val().deviceToken, payload).catch(e => {console.log(e);});
});
} else { //end: if returned any value
return 0;
}
});// end: get and loop over notification subscribers
} else { //end: send only if exists and new notification OR if doesn't exist
return 0;
}
});
I do not get any error messages. Function completes successfully with status "OK."
I test using two devices: one android and one iOS. Both device tokens are saved correctly in the database for the cloud function to retrieve and use for sending messages.
I see the notification on the Android device running my app. I wish the notification to show up on the iOS device running the same app.
Test message notification sent from the firebase console shows up on both devices correctly.
I realized that sendToDevice() used the legacy version of payload. I used send() in my function to use the newer version. (see answer: stackoverflow)
admin.messaging().send(payload).catch(e => console.log(e));
I changed the payload to include platform specific fields according to the latest guidelines (see firebase docs)
const payload = {
"token": sub.val().deviceToken,
"notification":{"title": notificationTitle,"body": notificationText},
"android": {"notification": {"sound": "default"}},
"apns": {"payload": {"aps": {"sound": "default"}}}
};
Now it works on both platforms.
I am using push plugin in ionic 3 app, everything is working fine but from my server end we are sending one message at a time and im receiving message to iPhone, but old message should overwrite with new message or once we receive new message then old message is clear automatically..
I'm not able to find anything related to this, please anybody help me to solve this.
const options: PushOptions = {
android: {},
ios: {
alert: 'true',
badge: true,
sound: 'false'
},
windows: {},
browser: {
pushServiceURL: 'http://push.api.phonegap.com/v1/push'
}
};
const pushObject: PushObject = this.push.init(options);
pushObject.on('notification').subscribe((notification: any) =>
console.log('Received a notification', notification));
It sounds like you aren't sending your messages configured to be "collapsible". By default each message will be distinct, not overwriting the last message. FCM documents this well:
https://firebase.google.com/docs/cloud-messaging/concept-options
Non-collapsible and collapsible messages
A non-collapsible message
denotes that each individual message is delivered to the device. A
non-collapsible message delivers some useful content, as opposed to a
collapsible message like a content-free "ping" to the mobile app to
contact the server to fetch data.
...
A collapsible message is a message that may be replaced by a new message if it has yet to be delivered to the device.
...
Or if you are not using FCM, here's a reference to Apple's APN docs directly.
To allow the coalescing of similar notifications, you can include a
collapse identifier within a notification request. Normally, when a
device is online, each notification request that you send to APNs
results in a notification delivered to the device. However, when the
apns-collapse-id key is present in your HTTP/2 request header, APNs
coalesces requests whose value for that key is the same. For example,
a news service that sends the same headline twice could use the same
collapse identifier value for both requests. APNs would then coalesce
the two requests into a single notification for delivery to the
device. For details on the apns-collapse-id key
Update with some code details:
public void sendMessage(String title, String body, Map<String, String> data, boolean shouldCollapse) {
PlatformConfiguration platformConfig = new PlatformConfiguration(30);
if (shouldCollapse)
messageBuilder.setAndroidConfig(platformConfig.getCollapsibleAndroidConfig("test")).setApnsConfig(platformConfig.getCollapsibleApnsConfig("test"));
...
public ApnsConfig getCollapsibleApnsConfig(String collapseKey) {
return getCoreApnsConfig().putHeader("apns-collapse-id", collapseKey)
.setAps(getNonCollapsibleApsBuilder().setCategory(collapseKey).setThreadId(collapseKey).build()).build();
}
public AndroidConfig getCollapsibleAndroidConfig(String collapseKey) {
return getCoreAndroidConfig().setCollapseKey(collapseKey)
.setNotification(
getNonCollapsibleAndroidNotificationBuilder().setTag(collapseKey).build()).build();
}
I've implemented Amazon SNS for push notifications.
I'm sending json in the following structure:
{
"aps":{
"alert":{
"loc-args":["ARGS"],
"loc-key":"KEY",
}
"sound":"default"
}
}
But on iOS client I'm receiving it as escaped string and everything from my message is inside "alert" key
[AnyHashable("aps"): {
alert = "{\"aps\":{\"alert\":{\"loc-args\":[\"ARGS\"],\"loc-key\":\"KEY\"},\"sound\":\"default\"}";
}]
I've also tried different formats from here http://docs.aws.amazon.com/sns/latest/dg/mobile-push-send-custommessage.html but every-time I'm receiving the same escaped string.
Does anyone had the same problem?
So the problem was in publishRequest.setMessageStructure("json"); flag.
I've missed it.
Also notification should be sent in the following format:
{"APNS_SANDBOX":"{\"aps\":{\"alert\":{\"loc-args\":[\"ARGS\"],\"loc-key\":\"KEY\"},\"sound\":\"default\"}}
Please let me ask about Push Notification issue here.
Our server sent out the data in JSON format like this
{
"notification":
{
"body”:”Test Push Notification (42)”,
"node":"1233837”,
"content-available":"1"
},
"priority":"high"
}
The process of sending out push notification to our app is
We sent out notification from our sever to GCM
From GCM, sending out to APNS.
But when we receive push notification in our app, the format is totally changed (as shown in attached image).
If you face with this kinda issue before, could you share with how to solve it, please?
Or is there any way to change in GCM to get normal JSON format?
Try next format to send notification to GCM:
{ "notification": { "body”:”Test Push Notification (42)”, "node":"1233837” }, "priority":10, "content-available":true }
From APNS you app get some like this
{
aps:{
alert:{
*bla bla bla*
},
*bla bla bla*
}}
Just parse it in didReceiveRemoteNotification: method.