We are using FCM to send remote notifications for both iOS and Android. The following are the payloads we are sending from the backend.
options = {
notification: {
title: "title",
body: body,
sound: 'default'
},
priority: "high",
content_available: true,
data: {
type: 'type',
id: id,
}
}
This works for ios and android.
But for some reason, the android side we need to send title,body and sound for keys in data payload and need to remove notification payload.
Now the notifications are not receiving ios side when app is not active, banner notifications are not arriving but the data is receiving when app is active.
We need banners on the iOS side.
Is that notification key is mandatory to display banner in iOS?
How to use the same payload for both iOS and Android.
options = {
priority: "high",
content_available: true,
data: {
title: "title",
body: body,
sound: 'default'
type: 'type',
id: id,
}
}
Also tried adding content_available and priority keys with various combinations.
Gone through all FCM docs and it still confuses. Help/Suggestions appreciated.
A recent feature was added for FCM that gives an option to provide specific params for specific platforms, called Platform Overrides:
Customizing a message across platforms
Messages sent by the FCM v1 HTTP protocol can contain two types of JSON key pairs:
a common set of keys to be interpreted by all app instances that receive the message.
platform-specific blocks of keys interpreted only by app instances running on the specified platform.
Platform-specific blocks give you flexibility to customize messages for different platforms to ensure that they are handled correctly when received. In many scenarios, it makes sense to use both common keys and platform-specific keys in a given message.
When to use common keys
Whenever you're targeting app instances on all platforms — iOS, Android, and web
When you are sending messages to topics
The common keys that are interpreted by all app instances regardless of platform are message.notification.title, message.notification.body, and message.data.
When to use platform-specific keys
When you want to send fields only to particular platforms
To send platform-specific fields in addition to the common keys
Whenever you want to send values to specific platforms only, don't use common keys; use platform-specific key blocks. For example, to send a notification to only iOS and web but not Android, you must use two separate blocks of keys, one for iOS and one for web.
When you are sending messages with specific delivery options, use platform-specific keys to set them. You can specify different values per platform if you want; but even when you want to set essentially the same value across platforms, you must use platform-specific keys. This is because each platform may interpret the value slightly differently — for example, time-to-live is set on Android as an expiration time in seconds, while on iOS it is set as an expiration date.
Example: notification message with platform-specific delivery options
The following v1 send request sends a common notification title and content to all platforms, but also sends some platform-specific overrides. Specifically, the request:
sets a long time-to-live for Android and Web platforms, while setting the APNs (iOS) message priority to a low setting
sets the appropriate keys to define the result of a user tap on the notification on Android and iOS — click_action, and category, respectively.
{
"message":{
"token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"notification":{
"title":"Match update",
"body":"Arsenal goal in added time, score is now 3-0"
},
"android":{
"ttl":"86400s",
"notification"{
"click_action":"OPEN_ACTIVITY_1"
}
},
"apns": {
"headers": {
"apns-priority": "5",
},
"payload": {
"aps": {
"category": "NEW_MESSAGE_CATEGORY"
}
}
},
"webpush":{
"headers":{
"TTL":"86400"
}
}
}
}
See the HTTP v1 reference documentation for complete detail on the keys available in platform-specific blocks in the message body. For more information about building send requests that contain the message body, see Build Send Requests.
Below payload can be used as a common payload for android and iOS. "score" is just a dummy keyword for explanation and you can add more but all the values should be in String.
{
priority: "high",
tokens: [tokens],
data: {
title: <title>,
body:<body>, <-- this data will be used by the android
score: 345.
},
apns: {
headers: {
"apns-priority": "10"
},
payload: {
aps: { <-- payload for iOS
alert: {
title: <title>,
body:<body>
},
data:{
score: 345
}
}
}
}
}
In the above payload,
In android, data which is below tokens, will be used as a data payload and no need of notification for title and body as it is included in the data itself.
For iOS, it requires notification tag for the iOS which is causing the problem for Android. So, it is solved by removing notification and adding the separate apns tag for the iOS and a new tag which is not given in the firebase documentation is "alert". iOS will look for apns payload and "alert" will be a substitute for the "notification".
Related
I am sending push notifications from my server (to a firebase token and not to a topic). I do not differentiate between the platforms, the server just sends the JSON via RestTemplate (Spring Boot App).
If I prepare it for Android, it works, but it does not for for iOS. But if I prepare it for iOS, it does not work for Android.
The case is: I want the notification and the background process (It should display the notification in any case foreground/background/killed and it should take key-value pairs from the data payload).
The problem is: If I use notification in my JSON, the notification would be displayed on iOS and on Android but just the iOS can handle the payload (in foreground/background/killed state). If I remove the notification tag in JSON, then everything works fine (Android and iOS receives the payload in all states, but the iOS does not display the notification).
In Android you can build the notification client side (like me), but in iOS its not possible.
So, how can I send a FCM (JSON) with a firebase-token and it is platform-independent? Both can handle it properly, both receive the payload and displays the message and payload should be handled in every state.
This works on android and displays the message (built client side) but does not work for iOS
{
"content_available": true,
"data":{
"action":"bla",
"value":"true",
"id":"111111"
},
"android":{
"priority":"high"
},
"apns":{
"headers":{
"apns-priority":"10"
}
},
"to":"<MY_FCM_TOKEN>"
}
This displays the FCM for android and iOS, but handles the payload just on iOS
{
"notification":{
"sound":"default",
"title":"Test Title",
"body":"Message of FCM"
},
"content_available": true,
"data":{
"action":"bla",
"value":"true",
"id":"111111"
},
"android":{
"priority":"high"
},
"apns":{
"headers":{
"apns-priority":"10"
}
},
"to":"<MY_FCM_TOKEN>"
}
Or is it possible to declare the notification-tag just for iOS?
Or is it possible to create notifications also client side in iOS when a payload receives?
Before sending a notification on the Server side I am checking whether the the platfomr is iOS or Android by using google's method:
https://iid.googleapis.com/iid/info/IID_TOKEN
Which on success returns a JSON with a 'platform' parameter.
You can find more info here
I want to send two different notifications to Android and iOS. I want to send a notification message to iOS, this way iOS displays a nice notification. For Android I want to send a data message, this way I can handle the notification on Android and also in the background (because I don't get a callback in the background and want to handle it myself).
I looked through the docs, but couldn't find anything about sending to a specific platform. How do I do that?
Also other suggestions on how to do this are welcome, but keep in mind that I specifically want to handle the notification myself through a callback on Android (onMessageReceived)
Update: A recent feature was added for FCM that gives an option to provide specific params for specific platforms, called Platform Overrides:
Customizing a message across platforms
Messages sent by the FCM v1 HTTP protocol can contain two types of JSON key pairs:
a common set of keys to be interpreted by all app instances that receive the message.
platform-specific blocks of keys interpreted only by app instances running on the specified platform.
Platform-specific blocks give you flexibility to customize messages for different platforms to ensure that they are handled correctly when received. In many scenarios, it makes sense to use both common keys and platform-specific keys in a given message.
When to use common keys
Whenever you're targeting app instances on all platforms — iOS, Android, and web
When you are sending messages to topics
The common keys that are interpreted by all app instances regardless of platform are message.notification.title, message.notification.body, and message.data.
When to use platform-specific keys
When you want to send fields only to particular platforms
To send platform-specific fields in addition to the common keys
Whenever you want to send values to specific platforms only, don't use common keys; use platform-specific key blocks. For example, to send a notification to only iOS and web but not Android, you must use two separate blocks of keys, one for iOS and one for web.
When you are sending messages with specific delivery options, use platform-specific keys to set them. You can specify different values per platform if you want; but even when you want to set essentially the same value across platforms, you must use platform-specific keys. This is because each platform may interpret the value slightly differently — for example, time-to-live is set on Android as an expiration time in seconds, while on iOS it is set as an expiration date.
Example: notification message with platform-specific delivery options
The following v1 send request sends a common notification title and content to all platforms, but also sends some platform-specific overrides. Specifically, the request:
sets a long time-to-live for Android and Web platforms, while setting the APNs (iOS) message priority to a low setting
sets the appropriate keys to define the result of a user tap on the notification on Android and iOS — click_action, and category, respectively.
{
"message":{
"token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"notification":{
"title":"Match update",
"body":"Arsenal goal in added time, score is now 3-0"
},
"android":{
"ttl":"86400s",
"notification"{
"click_action":"OPEN_ACTIVITY_1"
}
},
"apns": {
"headers": {
"apns-priority": "5",
},
"payload": {
"aps": {
"category": "NEW_MESSAGE_CATEGORY"
}
}
},
"webpush":{
"headers":{
"TTL":"86400"
}
}
}
}
See the HTTP v1 reference documentation for complete detail on the keys available in platform-specific blocks in the message body. For more information about building send requests that contain the message body, see Build Send Requests.
I remember answering a similar question before but cant seem to find it. There is currently no option to specify which platform a message would be sent. The simplest way you could do this is by using Topics Messaging.
Everytime the token is generated for the first time, you determine from your client app the Platform type and subscribe them to the corresponding topic (e.g. topics/(Android/iOS)_<Your App Name>), then sned the messages as needed.
It's also good to keep track of the registration tokens from your Server, if you're using Firebase DB, you could put them inside a node:
/pushTokens
/android
/{userId} : string
/ios
/{userid}: string
This would let you check from your backend side and adjust your payload as needed when sending single messages.
I was facing same issue with Android Development. We used Laravel on backend side.
On backend side, developer has to maintain different scenario for both platforms.
In Android :
FCM::sendTo($tokens, $option, null, $data);
Here, null is passed as a notification builder. When you pass null in notification and create databuilder($data), you can receive message in onMessageReceived method when app in background.
For iOS :
FCM::sendTo($tokens, $option, $notification, $data);
Here, you can pass notification builder in $notification. So, iOS device can also get notification.
As per my previously asked question, Firebase onMessageReceived not called when app is in the background , I need to change the payload to a 'data' payload as opposed to a 'notification' payload. (See link here -- What is the difference between Firebase push-notifications and FCM messages?).
The problem is, both the IOS and Android app we have utilize Firebase and the IOS app requires the push notification payload to use the 'notification' structure, while Android requires the 'data' payload structure.
My question is therefore, how do you distinguish between Android and IOS tokens / Ids obtained via the firebase sdk?
If our server saves these Ids and needs to send out a push notification, it needs to specify Android vs IOS in order to change the payload structure. Is the only way to accomplish this identification to have an app-based call to the server which differentiates IOS vs Android? Or is there a more sophisticated way using Firebase that will allow us to poinpoint which device it is?
Thanks all.
Information about an app instance is available from the Instance ID Service at this endpoint:
https://iid.googleapis.com/iid/info/IID_TOKEN
On success the call returns HTTP status 200 and a JSON object containing various status for the app instance including the platform:
returns ANDROID, IOS, or CHROME to indicate the device platform to
which the token belongs
I faced the same issue, following is my approach to solve the issue.
Firebase supports "Topic messaging", in which we can send data or notification messages to multiple subscribed devices.
Lets consider user login email id is unique (Lets consider example email id is test#gmail.com), In android application user will subscribe to test_gmail.com_data topic (replace '#' with '_' in email id since topic name doesn't support '#') and in iOS application user will subscribe to test_gmail.com_notification topic, From cloud functions I am sending Data message which is intended to android device on data topic and Notification message which is intended to iOS devices on notification topic.
By this approach I solved the issue, only problem with this approach is we end up sending twice the same message.
Example Code :
const data_message = {
data: {
"sender": "Narendra",
"Message" : "Simple data message"
},
topic:"test_gmail.com_data"
};
const notification_message = {
notification: {
title: "Announcement"
},
data: {
"sender": "Narendra",
"Message" : "Simple data message"
},
topic: "test_gmail.com_notification"
};
promises.push(admin.messaging().send(data_message));
promises.push(admin.messaging().send(notification_message));
I just started working on notifications on iOS and it seems that apple has defined a format for payload to receive notifications.
So currently, I am using this payload and everything is working as expected. I am getting title, subtitle, body sound, image.
{"aps" : {
"alert" : {
"title" : "Introduction To Notification",
"subtitle" : "Session 707",
"body" : "New Notification Look Amazing"
},
"sound" : "default",
"category" : "message",
"badge" : 1,
"mutable-content": 1
},
"attachment-url": "https://pusher.com/static_logos/320x320.png"
}
Lets say I want to have a single payload for both Android and iOS.
Is there a standard format defined in Android for notifications or can you set any data in Android and the client has to manually handle and display these notifications?
How can I create a payload which works for both?
Update for cross-platform payloads: A recent feature was added for FCM that gives an option to provide specific params for specific platforms, called Platform Overrides.
The sample payload you posted seems to be in-line with the official parameters for APNs. When using GCM or FCM, the parameters to be used are different (see the links).
Is there a standard format defined in Android for notifications or can you set any data in Android and the client has to manually handle and display these notifications?
It depends on which type of message payload you're planning to use. There are 2 types of Messages for GCM/FCM, notification and data.
notification messages only have predefined set of parameters available, while data messages can be used to have custom key-value pairs. Both are usually handled by the client, but note that the behavior for Android and iOS are different depending on the message type you use (see the links).
How can I create a payload which works for both?
As I mentioned in comments section in the other post:
You'll have to do the mapping in your own database/app server. Yes. What I was thinking here was every time a registration token is generated on the client app side, you send it to your database/app server along the type of device (i.e. "Android", "iOS"). So that when you'll be sending messages, you'll first have to check the type of device. I did say it's more work, but it's a sure way to give you control over things. AFAIK, it is the developer's responsibility to keep track of the registration tokens and any details that should be associated with it.
You are not allowed to put custom tags inside aps tag. Here's what documentations says about it:
Providers can specify custom payload values outside the Apple-reserved aps namespace. Custom values must use the JSON structured and primitive types: dictionary (object), array, string, number, and Boolean.
So in your case you should do something like:
{
"aps": {
"alert": "Hello World",
"sound": "default"
},
"Person": {
"Address": "Your address",
"Name": "Your Name",
"Number": "XXXXXXXXXX"
}
}
Therefore you can read your custom payload with looking for it's key in main JSON, rather than in "aps":
I'm trying to send a payload using GCM that can be handled on the background or foreground by clients using Android and iOS. The messages are delivered to clients using both platforms that are subscribed in a topic.
Because I need the iOS app to handle the data even when the app is on the background or closed, I'm setting "content_available": true, which works as expected on iOS.
However, when I add that parameter, Android does not handle the received data and instead displays a blank notification.
Here's an example payload:
{
"to": "/topics/946",
"content_available": true,
"data": {
"time": "2016-02-04 18:33:08",
"message": "Hello",
"msgType": "chat",
"senderId": "50",
"senderName": "John"
}
}
The documentation says that data messages should wake the Android app anyway:
On iOS, use this field to represent content-available in the APNS
payload. When a notification or message is sent and this is set to
true, an inactive client app is awoken. On Android, data messages wake
the app by default. On Chrome, currently not supported.
What am I doing wrong?
EDIT: I've already tried using "priority":"high", which does not make any difference.