I am working on a project where we are using Firebase Cloud Messaging for push notifications. The following JSON is currently being produced by the backend API and sent to FCM:
{
"priority": "normal",
"delay_while_idle": true,
"dry_run": false,
"time_to_live": 3600,
"notification": {
"body_loc_key": "MyCustomNotificationId"
},
"data": {
// contains notification data
},
"registration_ids": [
]
}
This notification should be silent, meaning it should be only received when the iOS application is in the foreground, however sometimes on some devices this notification also finds its way to the iOS notification tray with the app being in the background as if it had parameters to be displayed there.
I have found out the body_loc_key attribute must be present to iOS devices, otherwise the notification won't ever hit the device, whether the application is in the foreground or background.
The problem occured on the following devices:
Apple iPhone 5,
Apple iPhone 6,
with the possibility of others being affected as well.
Is there a different configuration for the JSON sent to FCM you have used with a success, where the notifications are only being sent to the device when the application is in the foreground?
After fiddling with the FCM payload for sime time we have found out the problem was actually the body_loc_key attribute all along.
In order for a notification to be silent and still sent to an apple device, the payload must meet the following criteria:
priority must be set to normal,
content_available must be set to true,
notification attribute must contain data, but should it contain the body_loc_key attribute it must be set to an empty string - "".
Working payload examples:
// Example one
{
"priority": "normal",
"delay_while_idle": true,
"dry_run": false,
"time_to_live": 3600,
"content_available": true,
"notification": {
"body_loc_key": ""
},
"data": {
// contains notification data
},
"registration_ids": [
]
}
// Example two
// (note that body_loc_key has been replaced with badge)
{
"priority": "normal",
"delay_while_idle": true,
"dry_run": false,
"time_to_live": 3600,
"content_available": true,
"notification": {
"badge": 10
},
"data": {
// contains notification data
},
"registration_ids": [
]
}
Changing the body_loc_key to an empty string pretty much fixed the issue. On top of that we have also found out the following about other attributes of the notification attribute:
badge may be present and is processed, notification remains silent,
title_loc_key has no effect, notification remains silent,
body_loc_args has no effect, notification remains silent.
All three additions apply to scenario where the precedent criteria have been met (empty body_loc_key if/when present, etc.).
The reason why your notification is being sent as display-message and not as silent-message is because you are using the notification payload.
In particular you are using the body_loc_key.
You wrote that you read that body_loc_key is required to send silent-messages.
This is not true.
Can you please link the page where you found this?
Related
I am trying to implement cache meachanism for FCM on IOS. I am using Xamarin Forms with CrossGeeks FirebasePushNotificationPlugin
Push notification service works fine. I am using payload pattern as below
{
"data": {
"message" : "my_custom_value",
"other_key" : true,
"body":"test"
},
"notification": {
"body" : "hello",
"title": "firebase",
"sound": "default",
"content_available" : true
},
"priority": "high",
"condition": "'general' in topics"
}
Above pattern appears delivered notification as alert on IOS main screen.
I have written a Dependency Service for getting undeleted or unopened accumulated notifications when app starts. Dependency Service include below codes
await UNUserNotificationCenter.Current.GetDeliveredNotificationsAsync();
When I use above payload, I can get accumulated notifications. But when I use payload pattern as below, I can not.
{
"data": {
"message" : "my_custom_value",
"other_key" : true,
"body":"test"
},
"notification": {
"content_available" : true
},
"priority": "high",
"condition": "'general' in topics"
}
Actually I would like to send 2 payload types for every notification for my cache mechanism because of prevent the user's delete action. After that, I would like to show cached notifications without any lost in my app's notification page.
Shortly my question about "I am not getting silent payload values from UNUserNotificationCenter this approach is possible or not?"
Or can I prevent the user's notification delete action from IOS main screen when my app is terminated.
Note: My minimum OS version is 10.0 in info.plist
Thank you in advance.
The app is on both iOS and Android, for this notification to work on both platforms, I removed notification field from notification json payload. But now iOS does not handle this notification when in background.
This one works on iOS but it has notification field which I do not want.
{
"registration_ids": [
"...",
"..."
],
"priority": "high",
"notification": {
"body": "Notification Body.",
"title": "Notification Title"
},
"data": {
"userId": "11111",
"badge": 10
}
}
This one works in android but not working on iOS when in background:
{
"registration_ids": [
"...",
"..."
],
"mutable_content": true,
"content_available": true,
"data": {
"click_action": "AndroidIntent"
"message": "Notification Body",
"myDataField": "11",
"location": "3",
"imageurl": "http://image.com/13fd.png"
}
}
The bottom one does not even enter my Notification Service Extension. How do I make sure my Notification Service Extension is called without adding a notification field on my json?
I have the same thoughts. I was thinking of receiving data from firebase and push local notification with customized title and body with notification service extention. This idea worked fine in foreground by implementing didReceiveRemoteNotification userInfo: in appDelegate to receive userInfo.
But it didn't work in background mode by enabling content_available. you send notification using APN Servers not Fcm Servers relating to firebase docs. I suggest to have a look in content_available and mutable_content
Remove content_available since this is the property to handle silent notifications.
I created a sample Cordova app which is using "phonegap-push-plugin".
That app doesn't have any complexity. On "deviceready" I run the plugin initialization code as shown here:
var push = PushNotification.init({android: {}, ios: {
sound: true,
alert: true,
badge: true,
categories: {
invite: {
yes: {
callback: 'accept',
title: 'Accept',
foreground: true,
destructive: false
},
no: {
callback: 'reject',
title: 'Reject',
foreground: true,
destructive: false
},
maybe: {
callback: 'maybe',
title: 'Maybe',
foreground: true,
destructive: false
}
},
delete: {
yes: {
callback: 'doDelete',
title: 'Delete',
foreground: true,
destructive: true
},
no: {
callback: 'cancel',
title: 'Cancel',
foreground: true,
destructive: false
}
}
}
}})
push.on('notification', data => {
console.log(data.message);
console.log(data.title);
console.log(data.count);
console.log(data.sound);
console.log(data.image);
console.log(data.additionalData);
})
push.on('emailGuests', data => {
console.log('I should email my guests');
});
push.on('snooze', data => {
console.log('Remind me later');
});
push.on('registration', data => {
console.log(data.registrationId);
console.log(data.registrationType);
});
push.subscribe('xx', console.log)
And this is the log output to console:
=> Successfully subscribe to topic xx
// The first run (after app install) will ask for permissions. If I click allow the lines below are printed to console.
=> dCAtjhCFBcU:APA91bG90c8VhNl_BzZ-2e9fmq_9fN6jfrRNJ1LPCRIpKnZ-AG-eLY4xtX84oJRZBh2D....KtNNQ35GM8ubPF5zr8HqeB6jffs
=> FCM
In order to push I'm sending the following payload to the Legacy Server https://fcm.googleapis.com/fcm/send.
{
"priority": "high",
"to": "/topics/xx", // I tried this but I also tried to specify the device token received upon "registration" event. I did this using to:<device_token> and also using registration_ids: [<device_token>].
"notification": {
"title": "My Message",
"body": "My Message Body",
"badge": 1,
"content-available": "1", // I tried with and without
"category": "identifier", // I tried with and without
"thread-id": "id", // I tried with and without
"sound": "default",
"icon": "default"
},
"data": {
"title": "A short string describing the purpose of the notification",
"body": "The text of the alert message",
"clubId": 1000
},
"notId": 1,
"custom_key1": "value1",
"custom_key2": "value2"
}
Note: I tried every combination possible in what concerns the app state: App in background; app closed; app in foreground; The event "notification" has never fired and the push notification was never received.
The request sent to the FCM server returns a message id when I use the topic (which is understandable since other devices subscribe the topic). For that reason my android that has subscribed to the same topic receives the message. The iOS in the other hand receives nothing!
{
"message_id": 5059997308576486332
}
If I try to specify the token that I received upon registration, I will get a slightly different message. Most of the time the token received upon registration works and the results will contain a string id. But this is temporary since a few minutes later the token become "NotRegistered".
{
"multicast_id": 88880398234xxxxx7,
"success": 0,
"failure": 1,
"canonical_ids": 0,
"results": [
{
"error": "NotRegistered" // <-- This happens after a few minutes. I have to delete the app and reinstall it in order to get a new token.
}
]
}
This is the build configuration
Notifications are correctly enabled on my iOS device. What am I missing?
Updated:
Accessing Apple's APN directly (yup... no FCM!)
I would like to send my push notifications through FCM but in order to determine the cause of the issues described above, I decided to try APN directly. To do this, I had to remove the from the app's config.xml, so phonegap-push-plugin can obtain a token from APN and not from FCM.
Now, using the new token and a server that uses node-apn module to communicate with APN server, I'm able to send push notifications to my iOS app. The downside of this, is that I lose the ability to push to topics since this is a FCM only feature.
The only thing that I still don't know is how to use the topic to target devices in the APN network, that are subscribed by the push.subscribe() method.
Checkout my issue here.
Any help on this too?
So, turns out there's an issue with the push plugin.
This issue only impacts users on iOS device apps that use the FCM.
If you use the APNs it works.
You can check my answer in here: https://github.com/phonegap/phonegap-plugin-push/issues/2644#issuecomment-445346335
And my initial issue reporting in here:
https://github.com/phonegap/phonegap-plugin-push/issues/2613
I am trying to collapse/merge multiple notifications belonging to same event in my app. iOS 10 introduced a key name apns-collapse-id in payload. Document says multiple remote notifications with same apns-collapse-id will merged and shown as single notification.
So we have the payload with apns-collapse-id and thread-id in our notification payload. Unfortunately as there is no much content online explaining how these keys actually works, for safe play we have used the same unique value for both apns-collapse-id and thread-id.
We are expecting the multiple remote notifications with same apns-collapse-id to merge. It is not happenning.
Few people suggested APNS collapse does not come for free and I have to implement UNNotificationContentExtension and handle the notifications manually. I know I can add and remove local notification already posted but not really sure how to update the already posted remote notification.
Here is how our payload looks like
payload {
"aps": {
"alert": {
"title": "Some title : ",
"body": "Some body text"
},
"sound": "default",
"payload": {
"target": {
"some key" : "Some value"
},
"thread_id": "Some_string_155863",
},
"apns-collapse-id": "Some_string_155863",
"mutable-content": 1,
"thread-id": "Some_string_155863",
"badge": 33
},
"thread-id": "Some_string_155863",
"apns-collapse-id": "Some_string_155863",
"mutable-content": 1
}
as you can see apns-collapse-id and thread-id are repeated multiple times in JSON because we aren't sure where exactly to have them
We are not using HTTPS/2 yet, but I believe iOS 10 notfication still supports legacy HTTPS. I am not really a network guy so I don't understand these things completely. Ignore my arrogance towards Https and Http2
Has anybody managed to get apns-collapse-id to work ? Please help.
apns-collapse-id is a request header, so you need to use the HTTP service and not the legacy binary interface.
Im using the new Firebase platform. Am trying to get a push notification sent by my app server and delivered to my iPhone.
I have the setup working where I manually send the message with the Firebase notifications area on the website, but when I try and send the message with a POST to https://fcm.googleapis.com/fcm/send I get no message being delivered to the device.
I'm sending the following (with auth headers)
{ "notification": {
"title": "Portugal vs. Denmark",
"text": "5 to 1"
},
"to" : "<registration token>"
}
I'm getting a 200 response from the POST with the following body:
{
"multicast_id": 5511974093763495964,
"success": 1,
"failure": 0,
"canonical_ids": 0,
"results": [
{
"message_id": "0:1463685441784359%3ad254b53ad254b5"
}
]
}
If I try and send to this device directly through the Firebase website it works, but the above form post doesn't. No idea where to go from here!
On iOS the priority field seems mandatory.
{
"to": "cHPpZ_s14EA:APA91bG56znW...",
"priority": "high",
"notification" : {
"body" : "hello!",
"title": "afruz",
"sound": "default"
}
}
If the API returns you a message_id it means that your message has been correctly accepted and it will eventually be delivered to the device.
On Android, messages are delivered as soon as possible (provided that the device is connected of course).
On Apple devices, IF the application is closed or in background, the notification is sent through Apple infrastructure and can be delayed accordingly with Apple documentation.
To reduce the delay of the prioritymessages sent to Apple device you can use the priority parameter.
More details: https://firebase.google.com/docs/cloud-messaging/concept-options#setting-the-priority-of-a-message
I found the message field to be required, as well as the priority field to deliver a message with a POST.
message is not required (and labeled as optional) in the Firebase Console.
I resolved adding the notification tag in request body without priority.
Here is a recap: