FCM Throwing invalid-argument for IOS notifications - ios

My project had working notifications previously and I can't trace any changes to the payload I've been sending. I've referenced the docs and can't see any issues with my payload. The exact error I am getting is
Request contains an invalid argument
let payload = {
token : oUser.devicetoken,
data : {
referenceid : chatid,
referencetype : 'chat',
referencename : oSender.displayname,
receiverid : userid,
type : 'message',
notificationid : res,
title : title,
body : `${oSender.displayname} : ${body}`
},
android : {
priority : 'high'
},
apns : {
payload : {
aps : {
'content-available' : 1
}
},
headers : {
'apns-push-type' : 'background',
'apns-priority' : '5',
'apns-topic' : 'llc.attebyte.partyme'
}
}
};
My current payload:
After taking a fresh look at the Apple docs for notifications I noticed that I should be using content-available. I had previously been using contentAvailable: true (and it was working). Neither one is working anymore.
There are multiple questions regarding this problem already. This one being the best I've found: firebase cloud messaging Request contains an invalid argument
I verified that the token is correct by sending the device a test notification from the firebase console. I don't think I should be hitting the size limit of 4kb, the message I am sending for testing is something along the lines of 'test' or 'hello' (also the issue is IOS specifi). I've also verified that the headers I am sending are current with the Apple docs.
I can't figure out any differences that would cause notifications to stop working within the last week or so. I know they were working then and I've gone through my Github history to verify the payload hasn't changed (besides my change to content-available I made today while testing.)

While Google takes its time to fix this, we could successfully send silent notifications using the legacy app server protocols:
https://firebase.google.com/docs/cloud-messaging/send-message#send-messages-using-the-legacy-app-server-protocols
The endpoint we are using is https://fcm.googleapis.com/fcm/send.
Here you can find the message structure (note that is quite different from the current API):
https://firebase.google.com/docs/cloud-messaging/http-server-ref
And here how to authorize the requests:
https://firebase.google.com/docs/cloud-messaging/auth-server#authorize-http-requests
Hope it helps while we wait for a definitive fix.

Related

iOS13 apns-push-type header on azure notification hub

Starting from iOS 13 and watchOS 6 Apple requires the presence of the header apns-push-type (the value of this header can be alert or background) for push notification.
According to Apple documentation:
The value of this header must accurately reflect the contents of your notification's payload. If there is a mismatch, or if the header is missing on required systems, APNs may delay the delivery of the notification or drop it altogether.
HEADERS
- END_STREAM
+ END_HEADERS
:method = POST
:scheme = https
:path = /3/device/xxxxxx
host = api.sandbox.push.apple.com
authorization = bearer xxx
apns-id = xxx-xxx-xxx
apns-push-type = alert
apns-expiration = 0
apns-priority = 10
apns-topic = com.example.MyApp
DATA
+ END_STREAM
{ "aps" : { "alert" : "Hello" } }
see Apple doc
Unfortunately using azure notification hub I can only define apscontent but not the header.
{ "aps": { "alert":"Alert message!", "content-available": 1 }, "CustomData": "$(CustomData)" }
How is it handled by azure notification hub?
How can I specify the type of the notification?
After some experiments and a little bit of investigation, this is the current Azure server behavior...
The server inspects the contents of the notification to infer the correct value.
If "content-available": 1 is present and "alert" is missing then the "apns-push-type" = "background" is added to the header.
If a valid "alert" is present then the "apns-push-type" = "alert" is added to the header.
So take care of having a valid APNS JSON body, with correctly populated content-available/alert properties.
See this discussion thread for more info
UPDATE 2019-10-15:
Currently there are some problems with background silent notification
See the following discussion:
https://github.com/Azure/azure-notificationhubs-dotnet/issues/96
UPDATE 2019-11-25:
The server was rejecting installations against APNS that included headers. Now this issue is fixed and the silent notification should work as expected.
This answer is not accurate, background push is not working on azure right now. The headers need to be included during sending a push as shown below and also the hub needs to be configured with a key and not a certificate:
var backgroundHeaders = new Dictionary<string, string> { { "apns-push-type", "background" }, { "apns-priority", "5" } };
Dictionary<string, string> templateParams = new Dictionary<string, string>();
// populated templateParams
var notification = new TemplateNotification(templateParams);
notification.Headers = backgroundHeaders;
// the second parameter is the tag name and the template name as we have it registered from the device.
var resBack = await hubClient.SendNotificationAsync(notification, tags);

Firebase Cloud Messaging to Android works but iOS fails. How to structure payload for iOS?

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.

Old message is not removing in iPhone notification try

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();
}

Authentication for OneSignal to send automatic notifications to a segment using Firebase in Swift 3

I recently started using OneSignal to send notifications on my firebase based iOS project.
While I can send notifications to specific user and an array of users fine, I can't find documentation on how to set up OneSignal authentication with Firebase so that I can target a specific segment of users automatically through the app.
The code that I am using to send notifications to an array of users (working fine):
//to remove the current user ("playerID") from receiving notification
let indexToDelete = playerIDArray.index(of: playerID)
playerIDArray.remove(at: indexToDelete!)
var count = 0
while count < playerIDArray.count {
OneSignal.postNotification(["contents" : ["en" : "\(usersID!) has sent a message"], "include_player_ids" : ["\(playerIDArray[count])"]])
count = count+1
}
However, when I try to send the notification to a segments, like so:
OneSignal.postNotification(["contents" : ["en" : "\(usersID!) has sent a message"], "included_segments" : ["All"]])
I get this error:
2017-03-09 02:35:30.989 MyApp[3658:87978] ERROR: Create notification failed
I know that I am getting this error due to authorization issues, so I was wondering if anyone knows how to set up this authorization using Firebase?
Thanks so much!
you are actually getting this error because you cannot use "included_segments" as a targeting parameter from you app.
You can only use "include_player_ids".
Documentation here:
https://documentation.onesignal.com/docs/ios-native-sdk#section--postnotification-
If you would like to target segments of users, you may do so from your dashboard:
https://documentation.onesignal.com/docs/sending-notifications#section-selecting-users
or from the OneSignal REST API:
https://documentation.onesignal.com/v3.0/reference#section-send-to-segments

Send push notifications to iOS with Amazon SNS and handle them with Localized Formatted Strings

I'm trying to send iOS push notifications from Amazon SNS and i'm able to do it, but i want to use localized formatted string to send the notification and push the message in the right language.
I'm using XCode 7.0.1 and developing with an iPhone 5S, but i think that's not the point.
So this is the message i'm trying to send:
{
"default":"This is the default Message",
"APNS_SANDBOX":"{ "aps" : { "alert" : {
"loc-key" : "GAME_PLAY_REQUEST_FORMAT",
"loc-args" : [ "Jenna", "Frank"]
},"data": { "type": "dashboard", "opponentName":"Juan ","gameCategory":"Multimedia","gameType":"combo","ugid":"123456789" }, "badge" : 9,"sound" :"default"}}"
}
It can be send, but its not changed in the device and the message is "GAME_PLAY_REQUEST_FORMAT", so what i want to be displayed is the value of this key in my Localizable.strings file:
"GAME_PLAY_REQUEST_FORMAT" = "%# and %# have invited you to play";
I've red that you can do it in the apple's documentation (https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/ApplePushService.html#//apple_ref/doc/uid/TP40008194-CH100-SW21)
Hope anyone can help.
Thanks
I'll post the answer here so everyone can see it.
#TĂ Truhoada yes, you need to use loc-keys in the payload. You can see how it works in the following link: Creating the Remote Notification Payload
Use loc-key to pass a key that is defined in your application's Localizable.strings file. The iPhone looks up the key and replaces it with the string found for the current localization.
You can see more information in this link from Erica Sadun: Building Notification Payloads

Resources