问题
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 of the other two types?
回答1:
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 see here.
Main changes are:
- group notifications
- provisional notifications
- critical notifications
- ability to interact with the notifications in the extensions
There are too many settings that need to be set right for it to work. I'll try to dissect them and make it 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 for remote and silent notifications
- 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 localNotifications 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!).
Some random notes:
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
To be able to show badges/alerts/sounds, you need to request permission from the user:
UNUserNotificationCenter.current().requestAuthorization([.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
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 (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 background, they 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.
Curious... Can you tell me what should my payload look like?
I highly recommend you see Apple§ documentation. It's very clear.
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 are two criterions:
- The payload's
aps
dictionary must include thecontent-available
key with a value of1
. - The payload's
aps
dictionary must not contain thealert
,sound
, orbadge
keys.
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.
For Remote 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 bycontent_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
to1
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
to1
.
(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 👆
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 implementapplication(_:didReceiveRemoteNotification:fetchCompletionHandler:)
.Similarly, if you disabled 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 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 myself, 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!
回答2:
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.
回答3:
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
来源:https://stackoverflow.com/questions/42275060/what-is-difference-between-remote-notification-and-silent-notification-in-ios