Apple Push Notification Collapse Key Equivalent
When using Google push notifications, I am allowed to specify a collapse_key value so a device will not receive multiple notifications of the same collapse_key. Does APNS have a similar feature or does anyone know a way to emulate this functionality?
There is no such feature in iOS. However, since push notifications are sent by a server that is in your control, you can keep track of which notifications you've sent to a particular device, and decide whether or not to send new ones. In other words, you put the logic in your server code, not your iOS app code.
As of iOS 10 and using the HTTP/2.0 APNS API, you can specify apns-collapse-id header and handle the collapse logic in your app.
Collapsed notifications will appear as one single notification on the device that keeps updating with new data. Each time a notification is updated it is pushed to the top of your unread notifications.
Description of apns-collapse-id taken from https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CommunicatingwithAPNs.html:
Multiple notifications with same collapse identifier are displayed to the user as a single notification. The value should not exceed 64 bytes. For more information, see Quality of Service, Store-and-Forward, and Coalesced Notifications.
When a device is online, all the notifications you send are delivered and available to the user. However, you can avoid showing duplicate notifications by employing a collapse identifier across multiple, identical notifications. The APNs request header key for the collapse identifier is apns-collapse-id and is defined in Table 6-2.
For example, a news service that sends the same headline twice in a row could employ the same collapse identifier for both push notification requests. APNs would then take care of coalescing these requests into a single notification for delivery to a device.
With iOS 10 there is a new "apns-collapse-id" which looks like it will handle this sort of need. If you have an Apple developer account you can look at the WWDC 2016 notification session videos (707 intro video https://developer.apple.com/videos/play/wwdc2016/707/).
If APNs attempts to deliver a notification but the device is offline, the notification is stored for a limited period of time, and delivered to the device when it becomes available.
Only one recent notification for a particular app is stored. If multiple notifications are sent while the device is offline, each new notification causes the prior notification to be discarded. This behavior of keeping only the newest notification is referred to as coalescing notifications.
So there's no need for collapse_key in iOS.
FYI, collapse_key is only useful when the device is offline/inactive:
This parameter identifies a group of messages (e.g., with collapse_key: "Updates Available") that can be collapsed, so that only the last message gets sent when delivery can be resumed. This is intended to avoid sending too many of the same messages when the device comes back online or becomes active (see delay_while_idle).
For both iOS and Android (using collapse_key), if the device is offline (ie the Apple/Google push server cannot reach it), the push server overwrites any previous notification, and only keeps the last one.
If the device is online, then I guess it's up to you to do whatever you want with the received notification. At least in Android you can decide whether you want to "pile things up", whether you want to overwrite any previous notification in the notification area, or whether you want to overwrite any previous notification of the same type.
NotificationManager notificationManager = ...; String appName = ...; NotificationCompat.Builder builder = ... // Always use the same id, so only the last notification will be displayed in the notification area. int notId = 0; // Always use a different id, so all notifications will pile up in the notification area notId = new Random().nextInt(100000); // Uses the type of notification as id, so you'll only have up to one notification per type // in the notification area. It's like using collapse_key, but on the app itself. // That type should should be some additional data in the notification you sent. notId = notificationType; Notification notification = builder.build(); notificationManager.notify(appName, notId, notification);
Doody P's answer works for remote notifications, but there is also an equivalent for locally triggered notifications: when you create your UNNotificationRequest, you can just set the identifier parameter to whatever you had been using as a collapse key. After being triggered, the push notification will show only the latest version that you sent with that identifier.
(Although they're still sent through APNs, we send push notifications silently and then retrigger as local notifications because we need to make sure that our users are logged in.)
There are handy code examples & demos of managing delivered notifications in this WWDC talk - the key section is from ~18:00 - 21:00.