FCM custom sound not working on iOS when in background mode - ios

Did something change with FCM recently? Our apps use custom sound in push notifications. This has been working fine on both Android and iOS, whether in foreground, background, or closed. But recently something seems to have changed as the same PHP code we've been using suddenly stopped working for custom sounds when the app is closed or in background mode? (The notification is delivered, but it just uses the default device sound).
I was able to get it working again on Android by just including the sound files in /app/src/res/raw (we used to keep them there, but for a long time now it wasn't needed yet always worked... apparently it's needed again). Ok Android solved.
But for iOS it still has stopped working! I'm not sure if it's something I'm doing wrong in xCode or if I need to change the PHP code used to trigger the notifications. So here's both to review:
I am using:
xCode 11.6
iOS target 11.0
Testing on real device, iOS 13.6.1
Sound files are at {Project Name}/Resources/ and were added with "Copy items if needed" and "Create groups" both checked
Server side code to trigger notifications (which always worked fine before and has not been changed):
{
"notification": {
"title": "Test Title",
"body": "Test Body",
"sound": "sound_file.mp3",
},
"registration_ids": ["APA...g","fl...CS"]
}
Please help... thought I was past all of this years ago...ugggg!

Detail information:
https://medium.com/#ThatJenPerson/authenticating-firebase-cloud-messaging-http-v1-api-requests-e9af3e0827b8
Sample code:
{
"message":{
"token":"ewrTK.....",
"notification":{
"title":"Breaking News",
"body":"New news story available."
},
"data":{
"title":"Notification title",
"body":"Notfication body"
},
"apns":{
"payload":{
"aps":{
"sound":"notification.mp3"
}
}
}
}
}

We just touched base with the Firebase dev team and they were able to reproduce the issue. They have just created an internal ticket to fix this. Will follow up here on the resolution progress

After several additional rounds communication with Firebase, here is the current status update and their response:
I would like to let you know that this issue was just recently
identified as a bug with our Legacy API that’s not properly handling
the custom sound for iOS. Our FCM gurus have identified the fix for
this issue, and the fix is about to be released on our production, but
we can’t share any exact details or timeline for the release. The fix
should let you send notifications properly based on your custom sounds
configuration and there should be no code changes needed on your end.
Also, it should still properly handle the notification sounds if the
app is closed or in background state for your iOS application.
We are furthermore told that for the moment, migration from FCM HTTP to HTTP v1 is the only work around. Will post here again once we hear confirmation on the fix to the Legacy API (which most people reading this as using). Stay tuned...

We created a ticket with Google/Firebase support.
Their answer:
There's no ongoing issue on our end that may cause the custom sound to not work. However, by specifying a custom sound, the sound file must be on the user's device already, either in the app's bundle or in the library/Sounds folder of the app's container. You can refer to this documentation for more information.
For FCM, there isn't any extra sound processing, only passing the payload field, so as long as the payload on the client shows "sound" file is successfully passed down, there may be an issue with the setup. If there's no recent change for your application and the sound files, then this may be something caused on Apple's end. With that, it's best to check this with them.
We discovered that we apparently use the legacy HTTP API so we tested the newer HTTP v1 version. (described here: https://firebase.google.com/docs/cloud-messaging/migrate-v1 )
This solved the problem for us. Custom sound is back.
In the mean time Firebase support replied the following and now acknowledges there is a problem with the legacy HTTP API.
Thanks for sharing your observations, Mark.
We’ve received similar reports regarding this issue and that indicates
that this is not an unusual issue in relation to the increasing
reports on the Stack Overflow discussion that you’ve mentioned too.
With that, this issue was just recently identified as a bug with our
Legacy API that’s not properly handling the custom sound for iOS. Our
engineering team has identified the fix for this issue, and we
couldn’t provide a definite timeline at the moment for the release in
our production. I’ll let you know once I have an update for this
issue.
For now, you might consider using our HTTP v1 API to send your
messages. Apologies for the inconvenience this may have caused you.

On my side, no matter what sound name I set, I always receive on ios side "sound": "default"
Sending:
{
"notification": {
"title": "Alert",
"body": "Test Message",
"sound": "alert.aiff",
},
"registration_ids": ["APA...g","fl...CS"]
}
Receiving:
{
aps = {
alert = {
body = "Test Message";
title = Alert;
};
"content-available" = 1;
sound = default;
};
}
The only reason for this to happen is that FCM set sound to default while it redirect to APNS. Need ask google

Please check guys, Google has fixed this issue !!

Related

Do I need APNs certificates if I'm using APNs Auth Key?

I'm writing an cross-platform app with Flutter and Firebase. I've been working on sending notifications, and it works perfectly on android. I send messages via the firebase admin functions sdk with no problems. The request looks like this:
const payload = {
notification: {
title: title,
body: body,
},
}
return admin.messaging().sendToDevice(tokens, payload, {
mutableContent: true,
contentAvailable: true,
apnsPushType: "background",
})
But when I try to send messages to iOS devices, I get the following error from the shell:
"error": {
"errorInfo": {
"code": "messaging/third-party-auth-error",
"message": "A message targeted to an iOS device could not be sent
the required APNs SSL certificate was not uploaded or
has expired. Check the validity of your development and
production certificates."
},
"codePrefix": "messaging"
}
I was under the impression that since I'm using a APNs key generated in the apple developer console, that I would not need any sort of SSL certificate. My key is uploaded to the Firebase console and iOS devices are successfully reporting their device tokens, so I'm not sure why I can't get a message through.
I've tried sending messages from the CLI and also from the FCM console online. Both have failed.
I've also enabled Push Notifications and Background Modes with background fetch and remote notifications.
Any help or suggestions would be appreciated.
This is really stupid, but the issue was an incorrect Bundle ID in firebase. When I first hooked up firebase it gave me a default bundle id (com.firebase.io or something dumb like that). Later when I actually put my app on testflight i called it something else entirely. So even though I followed all the directions on the FlutterFire website for setting up apple here it didn't work bc the bundle ids didn't match.
So I had to delete the firebase app, replace the googleservicesinfo.plist file (thought it might have been sufficient to just change the bundle id field in that file (idk for sure tho)) and then replaced it in the firbase console. Had to reupload the auth key too with the "new" app.
Hope that makes sense. Comment if you have any other questions!

Not all subscribed iOS devices to topic receive data notification, most often none at all. Notification without data works as expected

My app is implemented in React Native and is using Firebase for notifications. We have webhooks on the web app that are triggered on certain events. Those webhooks then send a request to the respective Firebase Cloud Function. With information from the request's header they get the topic they must send the notification to; from the request's body it gathers the information to be sent as data to the device. They are sent as data notifications only, the handler (using the React Native FCM API) then shows a local notification already translated with i18n using the react-native-push-notifications package. Everything works fine until I hit the weird situation described below.
Everything was doing alright both on Android and iOS until I launched the app on Test Flight for internal testing and then it stopped working after some time on iOS. Eventually, I noticed that when more than one iPhone subscribed to the same topic it eventually lead to inconsistencies in the delivery of the data notifications. The first iPhone to subscribe to the topic usually worked, the others didn't, the first one most of the time eventually stopped working as well or sometimes it just kept working while the others still didn't. I used the Firebase Console to send some test notification to the subscribed devices and it they actually received it. I then changed my Cloud Functions' code to avoid sending any data and just send some example body and title and it turns out the problem was here. As soon as I send something through the data field in the admin.messaging.Message object to be sent as argument to the admin.messaging().send method, they aren't received by the iPhone devices subscribed to the topic (or it's received by one or two max, the first ones to currently subscribe to the topic. But they usually stop receiving them after a while as well).
This is really really weird and being so inconsistent makes it practically impossible to debug with my current knowledge. Some things to keep in mind:
All Android devices still receive the notifications without a problem
I've watched the iPhone's console through Xcode to see if there was some error when processing the notification, in case they were actually getting the notification but they it failed before it was shown to the user. But nothing is logged by the SpringBoard process, making me conclude the notifications aren't actually getting to the device
I've manually sent notifications with cURL to APNs (with this guide). They were received fine
All notifications without data, regardless of the iOS specific apn headers, payload, etc, are received
What can be the cause of the problem? Or there's something in my code causing this strange behavior (which I doubt, since it works fine on Android and works fine in iOS as well on specific scenarios), there's some type of bug on Firebase's side causing some notifications to not be sent or, finally, there's some error on Apple's APNs side causing this. Highly doubt the last one, if the fault lays on any exterior factor it probably should be on Firebase's handling of topics.
Really would appreciate some help. Thanks in advance. Sorry If I didn't gave enough information, I actually never had the need to do a question on Stack Overflow. I'll leave below an example of a cloud function as well.
exports.orderPending = functions
.region("europe-west2")
.https.onRequest((req, res) => {
if (req.method == "POST") {
res.status("200").send("Webhook successful");
const topic = req.headers["code"];
const message = {
data: {
id: JSON.stringify(req.body.order.id),
event: "orderPending",
order: JSON.stringify(req.body.order),
},
topic,
android: {
priority: "high",
},
apns: {
payload: {
aps: {
contentAvailable: true,
},
},
headers: {
"apns-push-type": "background",
"apns-priority": "5",
"apns-topic": "APP BUNDLE ID HERE",
},
},
};
functions.logger.log(req.body.order.id);
functions.logger.log(topic);
admin.messaging().send(message)
.then((response) => {
console.log("Successfully sent message: ", response);
})
.catch((error) => {
console.log("Error sending message: ", error);
});
}
});
Turns out the data payload was exceeding the 4KB APNs limit but since when you send by topic it doesn't show any errors at all I had no way of knowing. So yeah, add this to your checklist

iOS 10 Service Extension Inconsistent

While there is a similarity to another question here:
iOS 10 don't call Notification Service Extension
I wish to provide a more concrete issue with concrete misbehavior. Consider the following push payload:
{
"service-alert":{
"title":"[Service]Title",
"subtitle":"[Service]Subtitle",
"body":"[Service]Body may be substituted."
},
"image":"https://some.small/thumbnail.jpg",
"aps":{
"badge":1,
"alert":{
"title":"[Default]Title",
"subtitle":"[Default]Subtitle",
"body":"[Default]A simple body of text."
},
"sound":"default",
"mutable-content":1
}
}
(the "service-alert" dictionary is for testing over-rides on the default alert text for devices that support it)
I'm debugging in Xcode on my iOS 10 device (iPhone 6+), I set a breakpoint in the Service Extension to verify it receives an opportunity to modify the push before presenting.
When I send the push, there are times when the Service Extension is hit (breakpoint hit), I can verify that the push payload is correct, and the displayed push shows only the default "aps" payload. No image. No modified title/subtitle/body.
My breakpoint in serviceExtensionTimeWillExpire is not hit. The notification mechanism appears to be "working" yet the result is incorrect.
When I send the exact same push again, it works. The image is loaded from the "image" URL and the modified "service-alert" text is displayed as designed. Sometimes I have to send the same push 2 or 3 times before it works, but then it seems consistent after that. So, if I see a modified notification once, from that point on every push test appears to work properly.
I feel, but do not have conclusive data to support yet, that a period of inactivity causes the Service Extension to be flushed and it is too slow to wake up when called upon. If so, this makes it useless, because it will never be fully awake when a push is received.
Current environment:
Xcode 8.2 beta (8C30a)
iOS 10.2 betas 2, 3, and 4
Debug scheme
Can anyone confirm/deny this behavior on iOS 10 beta and/or non-beta?
Have I found a 10.2 bug, or is this "normal behavior?"
Using this Pay load Push will come along with default sound
{
"aps" : {
"alert": {
"title": "main title",
"subtitle":"Subtitle",
"body": "Custom message"
},
"badge" : 0,
"sound" : "default"
}
}
}

iOS custom push notification sounds using GCM

I am trying to play a custom sound when receiving a push notification to my iOS app. I am using GCM on my server to push to Android and Apple devices.
By defaults I was sending the following in my push notification payload:
"sound":"default". This was working no problems, 100%.
As soon as I changed it to: "sound":"sound.wav" I was no longer receiving the "sound" tag in my payload in the debugger and naturally no sound was playing when the device received the payload.
Obviously I have added sound.wav to my bundle and checked it in the bundle resources.
Can anybody shed some light on this problem?
There are few things which can cause this.
The sound file "sound.wav" should be a second long and limited size in KBs.
Make sure your payload is like this:
{
"title": "Some title",
"data": [
{
"version": "1.0"
}
],
"aps": {
"badge": 1,
"sound": "soundfilenameinbundle.wav",
"alert": "Some Alert to Show"
}
}
Please make sure "sound" tag goes in "aps".
As you have said you have added the sound file, can you also check if it is added in the required target.
Sometimes big sized payloads also cause this. Try by reducing your payload size by removing some data for testing and check
As you said you cannot see "sound" tag in the payload. I suspect the problem in payload itself. Can you try changing file name.
Also try on iOS 7/8/9 to check if the problem is not OS specific.
I hope this will help.
Thanks Suhail,
The problem is with Google Cloud Messaging. They only support the "default" value for the sound tag. So whenever I change it to anything but that the GCM server does not send the sound tag at all.
Hope they fix it soon...
Details here:
https://developers.google.com/cloud-messaging/http-server-ref

Google Cloud Messaging showing success message but not sending iOS

So I have run into a very strange problem with Google Cloud Messaging. The problem I am having is that it is registering the devices successfully, and when a message is sent I get a success message from Google. But the devices never receive any messages.
The message I get back from GCM is:
"result": "Push notification sent successfully: {\"multicast_id\":6008387530769664000,\"success\":1,\"failure\":0,\"canonical_ids\":0,\"results\":[{\"message_id\":\"0:1442824842607522%73fc535e73fc535e\"}]}"
To make things even more confusing, my implementation was working about 2 weeks ago and I have not changed anything to date. The Android version of the app is receiving messages with no problems it is only the iOS implementation that is not working.
Any help would be much appreciated!
Thanks!
So I finally solved this issue after of pulling the last remaining hairs out of my head.
It turns out the devices are receiving the messages but GCM sets the priority to the lowest priority by default. This means the device receives the notification but never displays it. This priority is used for silent notifications to wake the app up in the background. I discovered this because I kept receiving the message in the console saying:
Low Priority Push: [com.test.app] - Background Refresh Not Supported
Priority is a value between 1 and 10 so I then set the priority to 10 and got the message instantly on the device. My GCM POST request body now looks like this:
{
"to": "GCM token here",
"notification": {
"sound": "default",
"badge": "2",
"title": "default",
"body": "Test Push!",
},
"priority" : 10,
}
I really hope this helps others as I have spent a week pulling my hair out regarding this.
(ノಠ益ಠ)ノ
EDIT:
You can set "priority" to "high" and that works exactly the same as setting it to "10" (priority is a value between 0 and 10. Google coverts the text to the number for iOS
Instead of adding "priority" : 10,
You should add the following line:
"content_available" : true,
In APNS server (iOS), The content_avaialble changes to 1 which leads the push notification in background. And adding "priority":10, will drain more iphone battery. In my case I don't even have anything related to priority, but it still works.

Resources