Firebase silent notification lose (iOS) - ios

I used FCM for topic messaging with silent notification.
I have android and iOS app.
This is the sample JSON that I used in PHP
{
"to" : "/topics/mytopic",
"priority": "high",
"content_available": true,
"data" : {
"<key>" : "<string>",
"<key2>" : "<string>"
}
I subscripted the same topic with android and iOS, then send to both.
iOS part always lost some messages
EX:
Send 10 messages
android: 10
iOS: 8
I searched the web and only found if battery level is less than 20% it will lost message.
(I test this behavior it's really happened, but not related to my cases. My battery level is always high in my test cases)
I have some questions, can someone help me?
Is any other possible situation to cause lose message?
Is any code I lost and need to check? (EX: iOS part)
Or lost some message is normal, FCM doesn't guarantee to send 100%

Firebase does not guarantee delivery of silent notifications in iOS by using content-available.
As per firebase documentation for content-available,
"Note that silent notifications in APNs are not guaranteed to be delivered, and can depend on factors such as the user turning on Low Power Mode, force quitting the app, etc. On Android, data messages wake the app by default."
Here's a workaround that I think might work for you.
For your iOS device, send a notification payload with mutable_content as true, a dummy notification object and some sort of flag in your data object that indicates this is meant to be a silent notification(something like isSilentNotif=true).
Now write a notificationservice that extends UNNotificationServiceExtension. You will get control in your notification service before the notification is displayed to the user. Here check for the flag you included (isSilentNotif) and hide the notification programmatically if the flag is true and perform the background operation you wanted to perform here.

Related

react native firebase save fcm data only when app is died or closed (IOS)

I'm using react-native-firebase for getting new notification
I would like to send from fcm data-only message, but i can't save this data when IOS app is closed or in background.
For android the solution is 'Headless JS', so if someone know any solution like Headless JS for IOS it's will be helpful.
https://rnfirebase.io/docs/v5.x.x/messaging/introduction
I was looking for IOS background services but all of them working every some minutes and i need to be a real time app
I believe what you are trying to achieve is a silent notification. To achieve this you need to send content_available as true in your FCM payload.
However, as mentioned in the documentation:
"Note that silent notifications in APNs are not guaranteed to be delivered, and can depend on factors such as the user turning on Low Power Mode, force quitting the app, etc"
Refer this SO question for more details on how to achieve silent notifications.

Correct way to send push to wake an app w/an alert banner (and sound)

I'm working on an app that doesn't wake when receiving an alert with content available set to 1.
I understand the newer API (UserNotifications) dictates a paradigm where a background alert should be sent, data received and a new local notification sent to the user, however we're not in a position to currently refactor the payloads sent to APNS. (though we could be if needed)
Assuming our payload is based off the documented payload here (https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/generating_a_remote_notification)
{
“aps” : {
“alert” : {
“title” : “Game Request”,
“subtitle” : “Five Card Draw”
“body” : “Bob wants to play poker”,
},
"content-available": 1 // ** We add this here, to alert the user & wake the app **
“category” : “GAME_INVITATION”
},
“gameID” : “12345678”
}
Note, We further add content-available: 1 to this payload. In our post to APNS we specify the alert type.
Previously, iOS would alert the user of the notification and wake the app if it was in the background. That behavior seems to have stopped as now apps are no longer waking in the background (but alerts still come through).
As we have active users and are always in a time crunch it would awesome to find the quickest way to get the app back up and running in the background and alerting.
Please remove the 'apns-push-type' on the post to apns.
This will revert to the previous functionality where it shows the alert and also wakes up the app. I dont guarantee any time period for how long this will continue to work because this is a required field going forward. So make sure your backend modifies their payload to apns as soon as the front end supports the new architecture.
:) Happy coding Fred!

Send silent (data) notification to iOS device through FCM after swiping app from recent [duplicate]

When I read Apple Docs, they mention 3 types of notification: local, remote, and silent.
Local notification can be inferred from its name, that is sent by the app locally.
However, what is the difference between the other two types?
EDIT: While this answer is fully applicable, there are some additions (not changes) to notifications in iOS 12. I highly recommend watching WWDC 2018: What’s New in User Notifications and read this amazing and must read article.
Main changes are:
grouped notifications along with summary format
provisional notifications ie show notifications directly in notification center without user permission
critical notifications which ignore 'do not disturb' or 'mute'
ability to interact with the notifications in the extensions
ability to completely reset or update actions
ability to deeplink into app's notification Settings from phone's Notification Center
IMPORTANT NOTE: Not sure since when but from the Apple docs, the 'silent notification' has been renamed to 'background notification'
There are too many settings that need to be set right for it to work. I'll try to dissect them and make them easier to understand.
Overall, several things are important.
the overall difference between a silent and user notification
different types of user notifications
how a remote notification, i.e. the payload, is configured from your server
how to enable push notifications and remote notifications from background modes on your project
how to register your token with APNs for remote and silent notifications and APNs architecture
how to request permission for user notifications
enabling 'background app refresh' and 'notifications' from the device
what is content-available
understanding that the iOS is upstream to your app when it comes to receiving a remote notification
what happens when the OS receives notifications when the app has been user-terminated
A note on reliability and APNs architecture
I highly recommend everyone to watch the first 7 minutes of: WWDC 2015: What's new in Notifications. From there, the presenter mentions that there are 2 major types of notifications:
Silent Notifications
They happen in the background, hence you never see any alert/badge/sound. Things get downloaded without you knowing about them.
iOS 11 bug
See here.
iOS 11 initial releases were buggy for silent notifications. Make sure
you have the latest version for your testing, otherwise, it may not
work
User Notifications
As the name says, it has something to do with the user. That is, the user will see an alert/badge or hear a sound. It has 2 types.
Local Notifications
A Local Notification can be triggered in 3 different ways:
UNLocationNotificationTrigger:
You see an alert when you're close to a Walmart store.
UNTimeIntervalNotificationTrigger: e.g. You see an alert every 10 minutes.
UNCalendarNotificationTrigger like December 1st 1:00PM 2017.
Remote Notifications
They are similar to local notifications but they are triggered from the server, e.g. a WhatsApp message that has a From field (Mom) and a body field (I love you!).
Token registration and APNs architecture:
To receive a silent or remote notification, you need to register for a token using:
application.registerForRemoteNotifications()
👆 Registering does NOT require user permission. This makes silent notifications to become seamless. See this moment of the WWDC video
Silent notifications are enabled by default. The user does not need
to approve your -- does not give permission to your app to use them,
and you can just start using them without asking the user for
permission.
From WWDC
Remember APNs is delivered to your users by APNs and not by your server. So your iOS code must send this token to your server. So the server can associate a given device token with the user. When you want to push to a certain user, your server just tells APNs to send a payload to a specific token. What's important to understand is that your server and APNs are two different things
The flow of it looks like this:
 
 
server/provider sends a payload to APNs
APNs send a notification to all target devices of a given account. e.g. your iPhone, Mac could both receive notifications for emails/messages.
Then your iPhone/Mac will deliver that message to the app. APNs don't directly send messages to your app. It sends it to the device. Then the iOS sends it to your app.
For more on this see docs APNs Overview and Sending Notification Requests to APNs
To be able to show badges/alerts/sounds, you need to request permission from the user:
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in
guard error == nil else {
//Display Error.. Handle Error.. etc..
return
}
if granted {
//Do stuff here..
//Register for RemoteNotifications. Your Remote Notifications can display alerts now :)
application.registerForRemoteNotifications()
}
else {
//Handle user denying permissions..
}
}
Question: Do I need to request access once for local notifications and once for remote notifications?
No. Just write the snippet above and it will request access for both remote and local.
Now let's get to the tricky part :D
Xcode Project + iPhone Settings
Do I need to enable something to receive silent notifications?
You must enable Push Notifications from your Xcode capabilities:
If you don't enable this, your app won't receive a token. And without a token, the server doesn't recognize you.
To be able to download stuff from the background, you need to enable: remote notifications from background modes.
To enable backgroundModes, you can do it either using your plist or Xcode capabilities.
The reason you can do it, either way, is because plist is closer to your code and is the old way, perhaps it's there for legacy support. Xcode capabilities is the newer, easy way.
plist:
Item 0 is just an index, it's not the key of a dictionary (something you normally see in plist), the UIBackgroundModes is an array of Strings. The strings must only come from an accepted value from the UIBackgroundModes Array.
Xcode Capabilities:
Check the Remote Notification in Xcode under background modes as below:
If you don't do any of the above, then toggling off notifications with:
will kill Remote & Local Notifications
However, if you do enable background app refresh from plist or Xcode capabilities, then even with notifications turned off for the app, you will still receive silent notifications!
If the user wants to disable silent notifications, he would have to disable both notifications and disable 'background app refresh for your app / across the system.
To disable 'background app refresh' across your system, you have to do this:
Why am I saying all this? To explain to you that settings of silent and push notifications are different for the user and the restrictions for sending them are different. For more, see this moment from the WWDC video. See here instead (the previous link was dead):
Silent notifications are enabled by default.
The user does not need to approve your does not give permission to
your app to use them, and you can just start using them without asking
the user for permission.
But silent notifications are the mechanism behind background app
refresh.
At any point you know that the user can go in settings and disable
them.
So you can't depend on them always being available.
You don't know if the user the turn them off, and you are not getting
a notification anymore.
This also means that silent notifications are delivered with the best
effort.
That means that when the notification arrives on the user's device,
the system is going to make some choices.
It's going to use different signals from the device and from the user
behavior, like power or the time of day to decide when it is a good
time to deliver the notification and launch your app.
It may try to save battery or it may try to match the user behavior
and make the content available when the user is more likely to use it.
Also see here.
CAVEAT: Even if you disable app background refresh and disable allow notifications, you can still receive silent notifications if your app is in FOREGROUND. If your app is in the background, it won't be delivered.
Do I need to enable something to receive remote notifications?
You just need to enable Push Notifications from your Xcode capabilities:
If you don't enable this, your app won't receive a token. And without a token, the server doesn't recognize you.
APNs Payload structure
Curious... Can you tell me what should my payload look like?
I highly recommend you see Apple§ documentation. It's very clear AND ALSO SEE Sending Notification Requests to APNs. Basically platform makes an HTTP/2 call to APNs and sends the desired payload. Sending the correct headers is critical otherwise your notifications are not delivered to the devices!
Thanks, but can you just tell me the important parts?
uhhmm... OK, but just so you know this is from the link I just said:
For Silent Notifications there is a single criterion:
The payload's aps dictionary must include the content-available key
with a value of 1.
Per docs you can send other fields
If there are user-visible updates that go along with the background
update, you can set the alert, sound, or badge keys in the aps
dictionary, as appropriate.
A sample payload would look like this:
{
"aps" : {
"content-available" : 1
},
"acme1" : "bar",
"acme2" : 42
}
acme1, acme2, or just some custom data! But for the aps key, you MUST follow Apple's structure, otherwise, it won't map correctly and you won't be able to read data correctly.
Note: I haven't verified this, but another engineer mentioned that if you have provisional notifications enabled then to ensure silent notifications are delivered you must include an alert field with an empty body. For example:
{
"aps" : {
"content-available" : 1,
"alert" : {
"body" : "",
},
},
}
For User Notifications:
You need an alert key inside your aps.
As an example:
{
"aps" : {
"alert" : "You got your emails.",
"badge" : 9,
"sound" : "bingbong.aiff"
},
"acme1" : "bar",
"acme2" : 42
}
There is also a third option which I will discuss further down the answer.
As for what the fixed aps and alert dictionary keys are, see these Apple docs.
OK, got it. What is content-available?
Very simple. It's just a flag that tells your app that you need to wake up and download something because I have content available for download! For more info, see this exact moment.
By default the content-available flag is not included, i.e., by default the notifications you send won't trigger application(_:didReceiveRemoteNotification:fetchCompletionHandler:) or do something in your app. It would just show the notification. If you want to wake up the app (to do something in the background), you need to include content-available and set it to 1.
§: If you're using Firebase, your payload structure and keys may be slightly different. For example, the key content-available is replaced by content_available. For more, see Firebase documentation and also here.
I know you told me that I can only download something into my app when I'm using silent notifications, but is there a way that I can also wake my app up in the background AND download something for remote notifications?
Yes, but then similar to the silent notification, you must also set the content-available flag to 1, so it would know to wake up and download something. Otherwise, it would just pop and alert/badge/sound but won't download anything.
IMPORTANT NOTES:
If your app has only silent notifications, just enable "push notifications" + "remote notifications" from capabilities and set content-available to 1 for each payload.
If your app has only remote notifications, just enable "push notifications" from capabilities. There's nothing to do for the content-available.
However, if you want your notifications to show an alert/badge/sound and also download something in the background, you must have both "remote notifications" and "push notifications" enabled + set content-available to 1.
(THIRD OPTION)
{
"aps" : {
"content-available" : 1
"alert" : "You got your emails.",
"badge" : 9,
"sound" : "bingbong.aiff"
},
"acme1" : "bar",
"acme2" : 42
}
This moment from WWDC video mentions the 👆
To Quote the Apple Engineer:
Now, you can in a user remote notification, you can set the same
content available flag that you set in silent notifications, and that
allows your app to have some time to download the content or update
the content that it wants to be displayed so that when the user taps
on the notification, your content is available. And the user sees what
it does. This is a way to have a silent notification inside a user
notifications like a summary.
Notifications and iOS Application life-cycle
I'm confused about remote notifications. I thought whenever I get a notification, my app becomes active in the background and downloads something. Can you explain?
e.g. at this moment:
Your iPhone has just received a remote notification with a body of "no sender". To receive this, WhatsApp ** doesn't** have to be running in the background, i.e., you don't need "Remote Notifications" enabled from BackgroundModes. You would still receive the notification even if your app was force-quit or suspended because the process is managed by the OS, not the WhatsApp app. However, if you want to be able to download the actual message or its image/video to WhatsApp (so that once your user opens WhatsApp, the video would be sitting there waiting for the user), well then you need your app to become active. To do so, you need content-available : 1 and implement application(_:didReceiveRemoteNotification:fetchCompletionHandler:) .
Similarly, if you disable cellular data for an app, you would still receive its notifications. However, by tapping on that notification, the user won't be able to make any network requests for that app. They would only be able to open the app.
Or as for another similar scenario, if the server/access point you're connected to has restricted access for, say, WhatsApp, it would still allow you to receive the APNs notifications. However, by tapping on that notification, the user won't be able to make any network requests for that app. They would only be able to open the app.
CAVEAT: If the app was force-quit by the user, then while you do get the notification for the above-mentioned reasons, you can't do anything to bring the app out of its terminated state automatically (even if you had content-available set to 1). None of your delegate methods would be hit. The user must open the app and only then your delegate methods will be reached.
A note on reliability and APNs architecture:
Although notifications are heavily used to deliver the actual content to the app, they are somewhat NOT designed to deliver content to the app. Rather, they are designed to notify the user that "hey something new has arrived (a 2b message or a 50kb small image, or a 10MB image or a 2 GB video). Open the app if you like. By the way, here's a small piece of it (the actual message itself if it can fit, the title of the image or a thumbnail shown in the notification, a title of the video or a thumbnail shown in the video". For more, see iOS APNs “best-effort” fallback. To repeat, you never download the 40MB attachment sent in the email. You just get notified of its existence. You send just enough (a thumbnail view of the attachment) so that the user is informed of what's new and can decide whether or not they need to open the app for more. When I was new to iOS, I thought you actually send the image/video through the push notification. You don't!
Specifically in the case of silent notifications:
When a device receives a background notification, the system may hold
and delay the delivery of the notification, which can have the
following side effects:
When the system receives a new background notification, it discards the older notification and only holds the newest one.
If something force quits or kills the app, the system discards the held notification.
If the user launches the app, the system immediately delivers the held notification.
Pushing Background Updates to Your App docs
APNs sends a limited number of silent notifications—notifications with the content-available key—per day. In addition, if the device has already exceeded its power budget for the day, silent notifications are not sent again until the power budget resets, which happens once a day. These limits are disabled when testing your app from Xcode. See Pushing Background Updates to Your App.
Troubleshooting tips for handling errors returned from ANPs
Even for remote user notifications, the user may be off of the internet and this could cause expired content or APNs could throttle you if you're sending notifications too many or too quickly. See here again
Long story short the APNs and OS are King and you're beneath it. Hence you cannot rely on it to conform to your every command. Having that said it's super reliable in the sense that you see most messaging apps utilize it successfully.
Addendum How to generate push notification certificate, .p12 or .pem and how to test it all out?
Just see this terrific answer. It has the most number of screenshots I've ever seen.
The push notification will let the user know that they receive a notification (Showing the notification popup for example). The silent notification will update, but the user won't get notified about it.
In any case, you can perform actions when notified with silent, just as if it was a push notification. The only difference is the user will not get notify with the popup notification.
With push notification:
With silent notification:
The difference is in the payload:
Push notification:
aps {
content-available: 1
alert: {...}
}
Silent notification:
aps {
content-available: 0
alert: {...}
}
And you have to set in Capabilities the background mode you choose.
Silent push notification reaches device, user does not know anything about the notification but his app gets the notification and app will be given some time to download new content and present it to the user, regardless to the state of the app (i.e. running or not running)
Remote push notification method is called only when your app is running. If app is suspended or not running, then the system wakes up or launches your app and puts it into the background running state before calling the method.
This method is intended for showing the updated content to the user.When this method is called, your app has up to 30 seconds of wall-clock time to perform the download operation and call the specified completion handler block. If the handler is not called in time, your app will be suspended.
For more technical details, you can go through this links:
Apple Notifications
Silent Notifications

What are different types of notifications in iOS and how to configure them correctly?

When I read Apple Docs, they mention 3 types of notification: local, remote, and silent.
Local notification can be inferred from its name, that is sent by the app locally.
However, what is the difference between the other two types?
EDIT: While this answer is fully applicable, there are some additions (not changes) to notifications in iOS 12. I highly recommend watching WWDC 2018: What’s New in User Notifications and read this amazing and must read article.
Main changes are:
grouped notifications along with summary format
provisional notifications ie show notifications directly in notification center without user permission
critical notifications which ignore 'do not disturb' or 'mute'
ability to interact with the notifications in the extensions
ability to completely reset or update actions
ability to deeplink into app's notification Settings from phone's Notification Center
IMPORTANT NOTE: Not sure since when but from the Apple docs, the 'silent notification' has been renamed to 'background notification'
There are too many settings that need to be set right for it to work. I'll try to dissect them and make them easier to understand.
Overall, several things are important.
the overall difference between a silent and user notification
different types of user notifications
how a remote notification, i.e. the payload, is configured from your server
how to enable push notifications and remote notifications from background modes on your project
how to register your token with APNs for remote and silent notifications and APNs architecture
how to request permission for user notifications
enabling 'background app refresh' and 'notifications' from the device
what is content-available
understanding that the iOS is upstream to your app when it comes to receiving a remote notification
what happens when the OS receives notifications when the app has been user-terminated
A note on reliability and APNs architecture
I highly recommend everyone to watch the first 7 minutes of: WWDC 2015: What's new in Notifications. From there, the presenter mentions that there are 2 major types of notifications:
Silent Notifications
They happen in the background, hence you never see any alert/badge/sound. Things get downloaded without you knowing about them.
iOS 11 bug
See here.
iOS 11 initial releases were buggy for silent notifications. Make sure
you have the latest version for your testing, otherwise, it may not
work
User Notifications
As the name says, it has something to do with the user. That is, the user will see an alert/badge or hear a sound. It has 2 types.
Local Notifications
A Local Notification can be triggered in 3 different ways:
UNLocationNotificationTrigger:
You see an alert when you're close to a Walmart store.
UNTimeIntervalNotificationTrigger: e.g. You see an alert every 10 minutes.
UNCalendarNotificationTrigger like December 1st 1:00PM 2017.
Remote Notifications
They are similar to local notifications but they are triggered from the server, e.g. a WhatsApp message that has a From field (Mom) and a body field (I love you!).
Token registration and APNs architecture:
To receive a silent or remote notification, you need to register for a token using:
application.registerForRemoteNotifications()
👆 Registering does NOT require user permission. This makes silent notifications to become seamless. See this moment of the WWDC video
Silent notifications are enabled by default. The user does not need
to approve your -- does not give permission to your app to use them,
and you can just start using them without asking the user for
permission.
From WWDC
Remember APNs is delivered to your users by APNs and not by your server. So your iOS code must send this token to your server. So the server can associate a given device token with the user. When you want to push to a certain user, your server just tells APNs to send a payload to a specific token. What's important to understand is that your server and APNs are two different things
The flow of it looks like this:
 
 
server/provider sends a payload to APNs
APNs send a notification to all target devices of a given account. e.g. your iPhone, Mac could both receive notifications for emails/messages.
Then your iPhone/Mac will deliver that message to the app. APNs don't directly send messages to your app. It sends it to the device. Then the iOS sends it to your app.
For more on this see docs APNs Overview and Sending Notification Requests to APNs
To be able to show badges/alerts/sounds, you need to request permission from the user:
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in
guard error == nil else {
//Display Error.. Handle Error.. etc..
return
}
if granted {
//Do stuff here..
//Register for RemoteNotifications. Your Remote Notifications can display alerts now :)
application.registerForRemoteNotifications()
}
else {
//Handle user denying permissions..
}
}
Question: Do I need to request access once for local notifications and once for remote notifications?
No. Just write the snippet above and it will request access for both remote and local.
Now let's get to the tricky part :D
Xcode Project + iPhone Settings
Do I need to enable something to receive silent notifications?
You must enable Push Notifications from your Xcode capabilities:
If you don't enable this, your app won't receive a token. And without a token, the server doesn't recognize you.
To be able to download stuff from the background, you need to enable: remote notifications from background modes.
To enable backgroundModes, you can do it either using your plist or Xcode capabilities.
The reason you can do it, either way, is because plist is closer to your code and is the old way, perhaps it's there for legacy support. Xcode capabilities is the newer, easy way.
plist:
Item 0 is just an index, it's not the key of a dictionary (something you normally see in plist), the UIBackgroundModes is an array of Strings. The strings must only come from an accepted value from the UIBackgroundModes Array.
Xcode Capabilities:
Check the Remote Notification in Xcode under background modes as below:
If you don't do any of the above, then toggling off notifications with:
will kill Remote & Local Notifications
However, if you do enable background app refresh from plist or Xcode capabilities, then even with notifications turned off for the app, you will still receive silent notifications!
If the user wants to disable silent notifications, he would have to disable both notifications and disable 'background app refresh for your app / across the system.
To disable 'background app refresh' across your system, you have to do this:
Why am I saying all this? To explain to you that settings of silent and push notifications are different for the user and the restrictions for sending them are different. For more, see this moment from the WWDC video. See here instead (the previous link was dead):
Silent notifications are enabled by default.
The user does not need to approve your does not give permission to
your app to use them, and you can just start using them without asking
the user for permission.
But silent notifications are the mechanism behind background app
refresh.
At any point you know that the user can go in settings and disable
them.
So you can't depend on them always being available.
You don't know if the user the turn them off, and you are not getting
a notification anymore.
This also means that silent notifications are delivered with the best
effort.
That means that when the notification arrives on the user's device,
the system is going to make some choices.
It's going to use different signals from the device and from the user
behavior, like power or the time of day to decide when it is a good
time to deliver the notification and launch your app.
It may try to save battery or it may try to match the user behavior
and make the content available when the user is more likely to use it.
Also see here.
CAVEAT: Even if you disable app background refresh and disable allow notifications, you can still receive silent notifications if your app is in FOREGROUND. If your app is in the background, it won't be delivered.
Do I need to enable something to receive remote notifications?
You just need to enable Push Notifications from your Xcode capabilities:
If you don't enable this, your app won't receive a token. And without a token, the server doesn't recognize you.
APNs Payload structure
Curious... Can you tell me what should my payload look like?
I highly recommend you see Apple§ documentation. It's very clear AND ALSO SEE Sending Notification Requests to APNs. Basically platform makes an HTTP/2 call to APNs and sends the desired payload. Sending the correct headers is critical otherwise your notifications are not delivered to the devices!
Thanks, but can you just tell me the important parts?
uhhmm... OK, but just so you know this is from the link I just said:
For Silent Notifications there is a single criterion:
The payload's aps dictionary must include the content-available key
with a value of 1.
Per docs you can send other fields
If there are user-visible updates that go along with the background
update, you can set the alert, sound, or badge keys in the aps
dictionary, as appropriate.
A sample payload would look like this:
{
"aps" : {
"content-available" : 1
},
"acme1" : "bar",
"acme2" : 42
}
acme1, acme2, or just some custom data! But for the aps key, you MUST follow Apple's structure, otherwise, it won't map correctly and you won't be able to read data correctly.
Note: I haven't verified this, but another engineer mentioned that if you have provisional notifications enabled then to ensure silent notifications are delivered you must include an alert field with an empty body. For example:
{
"aps" : {
"content-available" : 1,
"alert" : {
"body" : "",
},
},
}
For User Notifications:
You need an alert key inside your aps.
As an example:
{
"aps" : {
"alert" : "You got your emails.",
"badge" : 9,
"sound" : "bingbong.aiff"
},
"acme1" : "bar",
"acme2" : 42
}
There is also a third option which I will discuss further down the answer.
As for what the fixed aps and alert dictionary keys are, see these Apple docs.
OK, got it. What is content-available?
Very simple. It's just a flag that tells your app that you need to wake up and download something because I have content available for download! For more info, see this exact moment.
By default the content-available flag is not included, i.e., by default the notifications you send won't trigger application(_:didReceiveRemoteNotification:fetchCompletionHandler:) or do something in your app. It would just show the notification. If you want to wake up the app (to do something in the background), you need to include content-available and set it to 1.
§: If you're using Firebase, your payload structure and keys may be slightly different. For example, the key content-available is replaced by content_available. For more, see Firebase documentation and also here.
I know you told me that I can only download something into my app when I'm using silent notifications, but is there a way that I can also wake my app up in the background AND download something for remote notifications?
Yes, but then similar to the silent notification, you must also set the content-available flag to 1, so it would know to wake up and download something. Otherwise, it would just pop and alert/badge/sound but won't download anything.
IMPORTANT NOTES:
If your app has only silent notifications, just enable "push notifications" + "remote notifications" from capabilities and set content-available to 1 for each payload.
If your app has only remote notifications, just enable "push notifications" from capabilities. There's nothing to do for the content-available.
However, if you want your notifications to show an alert/badge/sound and also download something in the background, you must have both "remote notifications" and "push notifications" enabled + set content-available to 1.
(THIRD OPTION)
{
"aps" : {
"content-available" : 1
"alert" : "You got your emails.",
"badge" : 9,
"sound" : "bingbong.aiff"
},
"acme1" : "bar",
"acme2" : 42
}
This moment from WWDC video mentions the 👆
To Quote the Apple Engineer:
Now, you can in a user remote notification, you can set the same
content available flag that you set in silent notifications, and that
allows your app to have some time to download the content or update
the content that it wants to be displayed so that when the user taps
on the notification, your content is available. And the user sees what
it does. This is a way to have a silent notification inside a user
notifications like a summary.
Notifications and iOS Application life-cycle
I'm confused about remote notifications. I thought whenever I get a notification, my app becomes active in the background and downloads something. Can you explain?
e.g. at this moment:
Your iPhone has just received a remote notification with a body of "no sender". To receive this, WhatsApp ** doesn't** have to be running in the background, i.e., you don't need "Remote Notifications" enabled from BackgroundModes. You would still receive the notification even if your app was force-quit or suspended because the process is managed by the OS, not the WhatsApp app. However, if you want to be able to download the actual message or its image/video to WhatsApp (so that once your user opens WhatsApp, the video would be sitting there waiting for the user), well then you need your app to become active. To do so, you need content-available : 1 and implement application(_:didReceiveRemoteNotification:fetchCompletionHandler:) .
Similarly, if you disable cellular data for an app, you would still receive its notifications. However, by tapping on that notification, the user won't be able to make any network requests for that app. They would only be able to open the app.
Or as for another similar scenario, if the server/access point you're connected to has restricted access for, say, WhatsApp, it would still allow you to receive the APNs notifications. However, by tapping on that notification, the user won't be able to make any network requests for that app. They would only be able to open the app.
CAVEAT: If the app was force-quit by the user, then while you do get the notification for the above-mentioned reasons, you can't do anything to bring the app out of its terminated state automatically (even if you had content-available set to 1). None of your delegate methods would be hit. The user must open the app and only then your delegate methods will be reached.
A note on reliability and APNs architecture:
Although notifications are heavily used to deliver the actual content to the app, they are somewhat NOT designed to deliver content to the app. Rather, they are designed to notify the user that "hey something new has arrived (a 2b message or a 50kb small image, or a 10MB image or a 2 GB video). Open the app if you like. By the way, here's a small piece of it (the actual message itself if it can fit, the title of the image or a thumbnail shown in the notification, a title of the video or a thumbnail shown in the video". For more, see iOS APNs “best-effort” fallback. To repeat, you never download the 40MB attachment sent in the email. You just get notified of its existence. You send just enough (a thumbnail view of the attachment) so that the user is informed of what's new and can decide whether or not they need to open the app for more. When I was new to iOS, I thought you actually send the image/video through the push notification. You don't!
Specifically in the case of silent notifications:
When a device receives a background notification, the system may hold
and delay the delivery of the notification, which can have the
following side effects:
When the system receives a new background notification, it discards the older notification and only holds the newest one.
If something force quits or kills the app, the system discards the held notification.
If the user launches the app, the system immediately delivers the held notification.
Pushing Background Updates to Your App docs
APNs sends a limited number of silent notifications—notifications with the content-available key—per day. In addition, if the device has already exceeded its power budget for the day, silent notifications are not sent again until the power budget resets, which happens once a day. These limits are disabled when testing your app from Xcode. See Pushing Background Updates to Your App.
Troubleshooting tips for handling errors returned from ANPs
Even for remote user notifications, the user may be off of the internet and this could cause expired content or APNs could throttle you if you're sending notifications too many or too quickly. See here again
Long story short the APNs and OS are King and you're beneath it. Hence you cannot rely on it to conform to your every command. Having that said it's super reliable in the sense that you see most messaging apps utilize it successfully.
Addendum How to generate push notification certificate, .p12 or .pem and how to test it all out?
Just see this terrific answer. It has the most number of screenshots I've ever seen.
The push notification will let the user know that they receive a notification (Showing the notification popup for example). The silent notification will update, but the user won't get notified about it.
In any case, you can perform actions when notified with silent, just as if it was a push notification. The only difference is the user will not get notify with the popup notification.
With push notification:
With silent notification:
The difference is in the payload:
Push notification:
aps {
content-available: 1
alert: {...}
}
Silent notification:
aps {
content-available: 0
alert: {...}
}
And you have to set in Capabilities the background mode you choose.
Silent push notification reaches device, user does not know anything about the notification but his app gets the notification and app will be given some time to download new content and present it to the user, regardless to the state of the app (i.e. running or not running)
Remote push notification method is called only when your app is running. If app is suspended or not running, then the system wakes up or launches your app and puts it into the background running state before calling the method.
This method is intended for showing the updated content to the user.When this method is called, your app has up to 30 seconds of wall-clock time to perform the download operation and call the specified completion handler block. If the handler is not called in time, your app will be suspended.
For more technical details, you can go through this links:
Apple Notifications
Silent Notifications

Firebase Notifications working strategy for iOS

I am working on a chat application and I have successfully integrated Firebase in my iOS app. And now, Firebase Notifications is not clear to me. I have setup everything properly as per the documentation, and now I am getting notification to my device when I send notification from the Firebase Console. I want to know how Firebase will handle or send notification to a particular user. Do we need to send device info to Firebase? Or how does it work?
I want to know how Firebase will handle or send notification to a particular user.
The Firebase Server acts as a middle-man that handles the queuing of your messages.
For example, for Downstream Messaging, you send a push notification from your App Server or using the Firebase Console, the message is delivered to the FCM Server, storing it until such time that the device it has to send it to is available to receive it (or until such time you want it to be delivered, see Lifetime of a Message).
You can check out this Lifecycle Flow of GCM (since I think for this part, it's still the same for FCM):
Lifecycle Flow
Send and receive downstream messages.
Send a message. The app server sends messages to the client app:
The app server sends a message to GCM connection servers.
The GCM connection server enqueues and stores the message if the device is offline.
When the device is online, the GCM connection server sends the message to the device.
On the device, the client app receives the message according to the platform-specific implementation. See your platform-specific documentation for details.
Receive a message. A client app receives a message from a GCM connection server.
Note that this the one I mentioned is only for Downstream Messaging. You can check out the docs if you're also interested to learn about the flow for Upstream Messaging.
Do we need to send device info to Firebase?
It depends on your use-case. Although I think it is highly advisable for you to store all the registration tokens for future use.
Or how does it work?
Besides from what I already mentioned above, I'm just gonna go ahead and quote the How does it work? from the official docs:
How does it work?
An FCM implementation includes an app server that interacts with FCM via HTTP or XMPP protocol, and a client app. You can compose and send messages using the app server or the Notifications console.
Firebase Notifications is built on Firebase Cloud Messaging and shares the same FCM SDK for client development. For testing or for sending marketing or engagement messages with powerful built-in targeting and analytics, you can use Notifications. For deployments with more complex messaging requirements, FCM is the right choice.
I recently ran into the same problem when dealing with FCM.
You need to set both data and notification objects in your message payload like it is described here.
https://firebase.google.com/docs/cloud-messaging/concept-options#notifications
Messages with both notification and data payloads
App behavior when receiving messages that include both notification
and data payloads depends on whether the app is in the background or
the foreground—essentially, whether or not it is active at the time of
receipt.
When in the background, apps receive the notification payload in the
notification tray, and only handle the data payload when the user taps
on the notification. When in the foreground, your app receives a
message object with both payloads available. Here is a JSON-formatted
message containing both the notification key and the data key:
{
"to" : "APA91bHun4MxP5egoKMwt2KZFBaFUH-1RYqx...",
"notification" : {
"body" : "great match!",
"title" : "Portugal vs. Denmark",
"icon" : "myicon"
},
"data" : {
"Nick" : "Mario",
"Room" : "PortugalVSDenmark"
}
}
Also, you need to set high priority if you want to deliver push notifications on the device.
https://firebase.google.com/docs/cloud-messaging/concept-options#setting-the-priority-of-a-message
Setting the priority of a message
You have two options for assigning delivery priority to downstream
messages: normal and high priority. Delivery of normal and high
priority messages works like this:
Normal priority. This is the default priority for message delivery.
Normal priority messages won't open network connections on a sleeping
device, and their delivery may be delayed to conserve the battery. For
less time-sensitive messages, such as notifications of new email or
other data to sync, choose normal delivery priority.
High priority
FCM attempts to deliver high priority messages immediately, allowing
the FCM service to wake a sleeping device when possible and open a
network connection to your app server. Apps with instant messaging,
chat, or voice call alerts, for example, generally need to open a
network connection and make sure FCM delivers the message to the
device without delay. Set high priority only if the message is
time-critical and requires the user's immediate interaction, but
beware that setting your messages to high priority contributes more to
battery drain compared with normal priority messages. Valid values are
normal and high. For more details, see the server reference for HTTP
or XMPP.
For iOS client apps, normal and high priority are analogous to APNs
priority levels 5 and 10. For full details on iOS-specific behavior,
see the APNs documentation. For details on Android-specific behavior,
see Optimizing for Doze and App Standby.
Here is an example of a normal priority message to notify a magazine
subscriber that new content is available to download:
{
"to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"priority" : "high",
"notification" : {
"body" : "This week's edition is now available.",
"title" : "NewsMagazine.com",
"icon" : "new"
},
"data" : {
"volume" : "3.21.15",
"contents" : "http://www.news-magazine.com/world-week/21659772"
}
}
You don't need to send anything to Firebase if you have successfully configured your project for Firebase.
https://firebase.google.com/docs/cloud-messaging/ios/client

Resources