Remote Notification Payload issue : iOS - ios

So I'm using the firebase push notification in my app. Notification is working fine with the following payload,
{
"to": "cMXdSK_ud0LpqMoju85FvT:APA91bFMke92QR1IvcLeLhG5XrvwcE0OfSLGpJW1ds9-FFDornoeorMlKOn6IEtDYsuvwlRrwJnHJy0BPl_udcbqac39WF1cllsEV3l------------",
"notification": {
"title": "10-inch Aggretsuko Rage #24 (Jumbo Size)",
"subtitle": "Test notification Krunal"
}
}
But when I used the same payload format that mentions in the apple documentation then the notification is sent successfully but not received on the device. Check this payload,
{
"to": "cMXdSK_ud0LpqMoju85FvT:APA91bFMke92QR1IvcLeLhG5XrvwcE0OfSLGpJW1ds9-FFDornoeorMlKOn6IEtDYsuvwlRrwJnHJy0BPl_udcbqac39WF1cllsEV3l------------",
"aps" : {
"alert" : {
"title" : "10-inch Aggretsuko Rage #24 (Jumbo Size)",
"subtitle" : "Test notification Krunal",
},
"category" : "GAME_INVITATION"
},
"gameID" : "12345678"
}
Can someone please explain what's the actual problem with the above payload I want to use that in my flutter app. When I used the notification keyword in the payload that create a problem in the flutter android app. Can someone please help me to solve this problem?

What is happening here is that you're using FCM messages. When you do this, you actually send the notification payload to Firebase. Firebase then transforms this payload into the appropriate payload format for iOS or Android or web and then sends it to the respective messaging service.
For the payload that you've built looking at the Apple documentation to work you would have to send it to APNS.
You can specify Apple specific keys in your FCM message as-well. See the documentation here.
You can use the ApnsConfig object to specify things that are specific to Apple devices.
To set options specific to Android devices you may use the AndroidConfig object.
Now, coming to the problem you mention with the Android app, looking at the 'to' field in your payload, I must assume you are using one of the legacy APIs (XMPP Server Protocol or Legacy HTTP Server Protocol) instead of the ones I have suggested above. In this case, are you sure you have updated the recipient in the 'to' field when sending the payload? If yes, then could you please explain the problem you are seeing in your Android app when using the FCM specific payload.

I think the problem is that Firebase wants a different JSON structure than the proprietary data structure that actually ends up being used on Apple systems. Firebase is doing the conversion for you from your first example.
Your second example is the kind of payload the Apple Simulator can make use of xcrun simctl push so it is still helpful for local testing and development.
The final part of your question about why it is a problem for Android I am not sure about. But I wonder whether you supplied the wrong FCM token because that might encode the intended platform type within in making it incompatible for Android delivery. Firebase seems to always know the right platform specific way to deliver a push message, whether it is Android or iOS, so it must keep a track of that via the FCM token.

Related

Critical Alert support on OneSignal not working

We are having trouble using the new iOS Critical Alerts feature with OneSignal. The app we have is built using Apache Flex and the push notification payloads are being compiled/generated through Distriqt ANE and sent through the OneSignal iOS SDK. We have been approved by Apple for Critical Alerts but when attempting to send the payload through OneSignal, it does not work.
The Distriqt team has built in support for Critical Alerts, which is great, but once it is sent through OneSignal, the payload isn't delivered successfully and the critical alert is not generated. To be clear, general push notifications work fine.
OneSignal has documentation on Critical Alerts, though it is over simplified. The payload needed to trigger Critical Alerts on iOS is clear but there is no way to construct a payload like this through the OneSignal iOS SDK.
In the link, we have performed #1 (Update OneSignal App Payload Structure for iOS) but #2 is unclear. What does the payload need to look like? The code provided does not make that clear. Additionally, what is the referenced 'notification category extension' and if that code is identified, what are we needing to do at that point?
We have contacted OneSignal and have been unsuccessful in understanding how to successfully construct this payload. The documentation says 'iOS features OneSignal SDK supports' but from their support we received this:
Unfortunately our SDK is not setup to handle critical alerts.
One user reported he achieved this with our additional data parameter like this:
"data": {"CRITICAL_ALERT":"YES","CRITICAL_PAYLOAD":{"CRITICAL_VOLUME":"1.0","CRITICAL_SOUND":"Alert.wav"}}
Though that doesn't work. Although a relatively new feature, I am hoping someone in the community has been successful at this and can help. Thanks!
TL;DR Building an iOS Notification Service Extension is the solution. The OneSignal documentation mentions this but in far less detail.
When Critical Alerts was introduced by Apple, they changed the sound parameter that is passed through with an APNS payload. Previously, the sound was only ever a string. For example:
{
“aps” : {
“sound” : “critical-alert-sound.wav”
}
}
With Critical Alerts, it is a dictionary. Example:
{
“aps” : {
“sound” : {
“critical”: 1,
“name”: “critical-alert-sound.wav”,
“volume”: 1.0
}
}
}
The string version is still valid and is used for non-critical alerts. Based on inference and testing, when passing the sound parameter to OneSignal, it only supports the initial 'string' version. When OneSignal sends the payload to Apple, it passes it as a string thus even trying to pass a sound dictionary to OneSignal won't work because it gets parsed down before it gets to Apple. By the time Apple communicates back with your device, the dictionary is gone, thus preventing the device from ever recognizing it as a Critical Alert.
This is where the Notification Service Extension comes in. From Apple's documentation:
A UNNotificationServiceExtension object provides the entry point for a Notification Service app extension, which lets you customize the content of a remote notification before it is delivered to the user. A Notification Service app extension doesn't present any UI of its own. Instead, it is launched on demand when a notification of the appropriate type is delivered to the user’s device. You use this extension to modify the notification’s content or download content related to the extension.
In short, you can intercept the notification JSON payload coming from Apple and modify it just before the user sees it.
In order for the information to be passed to the device correctly from OneSignal->Apple->Device, you need to:
1) Set the additional_data_is_root_payload value on your OneSignal account to true. This is done through an Update an App API call on OneSignal. I used Postman for this. To be clear, this is needed to be done one time, it is not something needed to be repeated every time you make an notification API call.
2) In your OneSignal API payload, set the mutable_content parameter to true.
As mentioned above, you can use values in the OneSignal data parameter of the payload. The data payload is an open field that can be used for any additional information you want to pass through the OneSignal->Apple->Device flow and does get delivered to the device/app which you can then parse however you would like. In my example, we use:
"data": {"CRITICAL_ALERT":"YES"}
The data payload is arbitrary, it just needs to match the checks you do in the Notification Service Extension.
We then create our Notification Service Extension in XCode. There are some great step-by-step instructions here on creating an extension. This is done through XCode so if you are building a native app, it's simply done through your XCode project for your application. If you are using a framework like Adobe AIR, it is quite a bit more complicated and I will detail that in a different post. Keep in mind that the Notification Service Extension is basically a separate 'app' bundled with the parent app. It is compiled into a file with extension 'appex' and even though it is a separately bundled binary, it is specifically targeted to your parent app.
Once the extension is created, your XCode project will have a file named NotificationService.swift with a class that has the didReceive method within it. We then added this code:
self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
if let bestAttemptContent = bestAttemptContent {
// Modify the notification content here...
if ((request.content.userInfo["CRITICAL_ALERT"] as? String) == "YES"){
bestAttemptContent.sound = UNNotificationSound.defaultCriticalSound(withAudioVolume: 1.0)
}
contentHandler(bestAttemptContent)
}
You can see that we check the data payload (request.content.userInfo) to see if the CRITICAL_ALERT key is set with a value of YES. If so, we add a 'critical sound' to the notification which effectively turns it into a critical alert. In this case, we kept it simple with the defaultCriticalSound function but you can also use criticalSoundNamed if you want to define your own sound. You could also pass the sound you want to use for the alert through the data payload and then parse it and add it in the Notification Service extension if you wanted to create specific sounds for specific notifications.
At this point, we tested this through the OneSignal interface once we had deployed the app to our devices. This can be accessed by logging into your OneSignal account and then going to 'Messages' -> 'New Push' and choosing the devices you would like to send the push to:
Hopefully this is helpful to others using OneSignal for Critical Alerts (and hopefully they update their system soon to no longer need a Notification Service Extension).

Localized Notifications iOS 10 using FCM

We have a Django backend server using pyfcm to deliver Notifications throgh Firebase Cloud Messaging (FCM). I just updated to the today released Version 1.3.0. I want to send a notification using the loc-key and loc-args parameters so it can be displayed in the language the user is using on his phone. The notification reaches the device, it vibrates and makes the default sound for a new notification, but it will not displayed. It just happens nothing except for the sound and vibration.
This is the payload generated by the server which is sent to the fcm endpoint:
{
"notification": {
"loc-args": ["Demo (#demo)"],
"loc-key": "notification-follow",
"sound": "Default"
},
"priority": "high",
"to": "..."
}
On the client side, this is what is received by the phone:
[
AnyHashable("gcm.message_id"):0:1496257581534217 %f910cc44f910cc44,
AnyHashable("aps"):{
category = profile;
sound = Default;
},
AnyHashable("gcm.notification.alert"):{
"title-loc-key":" notification-follow",
"title-loc-args":[
"Demo (#demo)"
]
}
]
Is there anything I have to do before the message is displaying? Sending the message without the loc-key and loc-args but with message-body presents the notificaion on the device. Maybe the payload is wrong? How should it look like to do what I want?
The key, notification-follow in this case, is listed and translated in the Localizable.strings files in any available language.
Ok, problem solved. It was pyFCM. I thought it would be an error with this library, so the developer pseudo-fixed it. But it worked properly, and now it doesn't work anymore. The trick is to give body_loc_args an array, otherwise it will give you an InvalidParameters error.

Firebase Messages to iOS without APNs?

Is it possible to send data messages to iOS devices in FCM without using APNs?
I need to send some "live" data to my iOS client app while it is running, instead of polling my servers.
There are 2 reasons I want FCM not to use Apple notifications:
I don't want any kind of system notification/badge/alert to be shown to the user when the app is not running. This is pure app data transfer while the app is running, the rest of the messages can be ignored.
When using Apple notifications the user will be asked the first time if (s)he wants to grant my app notification permissions. If denied my whole app will stop working since the data will not be updated.
I found this post at Firebase Google Groups here where some of the Firebase guys hints that if I don't use iOS specific keys like sound, body, badge, content_available or others:
{
"to" : "<device_id>",
"data" : {
"customKey1" : "value1",
"customKey2" : "value2",
"customKey3" : "value3",
}
}
then they will not use APNs.
All I need is a guarantee of a delivery while my app is in foreground, I wonder if there is a way to configure FCM or messages themselves to reach that goal.
Just a follow up on this. I'm finding that with React Native using this library https://rnfirebase.io/docs/v5.x.x/messaging/receiving-messages i am able to receive data only messages to the iOS simulator (which doesnt support APNS) so looks like data only bypasses APNS.

Firebase messaging not working for "data" messages in iOS

I have an app running on iOS 9.3.5. I need to be able to send a push notification to my app when it's in the foreground or background. I don't actually need to include any data, I just need to ping the app so it will "phone home". So I don't need/want the user to see any notifications.
Since the company is already using Firebase for their Android app, I've set that up in the iOS app. If I send a message to https://fcm.googleapis.com/fcm/send with the notification key in the payload, it's received on the iPhone. When I try it with the data key instead, I get nothing. In both cases I get a success response from the POST. I've implemented the follow callbacks:
application:didReceiveRemoteNotification:
userNotificationCenter:willPresentNotification:withCompletionHandler:
applicationReceivedRemoteMessage:(FIRMessagingRemoteMessage *)remoteMessage
None of those are called when sending a message with the data key.
Edit:
This is the payload I'm using.
{ "data": {
"message": "phonehome",
},
"to" : "xxxxx"
}
After doing some more testing it looks like I get that message when the app is in the foreground but not the background. When I switch to the foreground then application:didReceiveRemoteNotification: gets called.
Edit 2: Added content_available and that did the trick. Thanks!
{ "to" : "xxxx", "content_available" : true }
It's a little bit hard to suggest without a sample payload, However, do try to use the priority parameter as high or content_available to true.

How to handle iOS Push Notifications in Different language

I am working on an app in which, I have implemented Push Notifications. Now I have to give support for Multiple language for Push notifications.
Please suggest whether, Localization for push notifications should be on App side or Server side.
And How to handle the language of push displayed on Banner when app is not running?
Thanks In Advance
This is an old question but it deserves a new answer.
Localized push notifications can be solved either server side or in the app.
To send localized notifications server side requires that the server knows the users language preference and like aronspring suggested, a good time to do that is when registering the push token.
To do it locally on the phone you need to supply all possible notifications and their translations in the app bundle Localizable.strings file. The server would then instead of sending the text to be displayed, send the key to the corresponding translation in Localizable.strings.
Example aps payload:
"aps" : {
"alert" : {
"loc-key" : "SOME_MESSAGE"
}
}
For a better explanation read more here: Local and Remote Notification Programming Guide
Like you've just pointed out, in the scenario when your app is not running the OS will receive the notification and not run any code within your app to translate them, and will display them as they are received. So they will need to be translated server side before being sent. The app shouldn't have to worry about what language they are sent in - no code needs to be written app side for this.
It might be an idea to store the device locale when you register the push token to known what language the device is set to.

Resources