4

Roughly during the third quarter of last year, I was able to use UNNotificationServiceExtension to not only decrypt incoming push notification contents (a common use case) but also remove previously delivered notifications every time a new one arrived.

I used UNUserNotificationCenter.current().getDeliveredNotifications to retrieve delivered notifications and then remove those I needed to remove.

However, as the new year rolled up, I suddenly noticed that my app was no longer removing previously delivered notifications from the notification center, despite the code still being present in the service extension and not throwing any errors, and despite the other code in the service extension working just fine.

Upon debugging, I found that UNUserNotificationCenter.current().getDeliveredNotifications now returns an empty array of notifications even when there are several delivered on the lock screen.

And UNUserNotificationCenter.current().removeAllDeliveredNotifications() simply does nothing, so even just using that call, without retrieving or filtering delivered notifications, doesn't remove anything.

Does anyone know if there's still a way to accomplish this?

Or could Apple have prohibited this functionality?

  • Do you want any delivered notifications to remain present until a new notification is received and scheduled, or, deliver the notification and then remove it? – Alex Marchant Feb 11 '19 at 15:17
  • Ideally, I need to filter by `threadIdentifier` and remove all previously delivered notifications for a specific type instead of stacking them, but I'd also settle for just removing all previously delivered notifications each time a new one comes in. This used to be possible, but `UNUserNotificationCenter.current().removeAllDeliveredNotifications()` has stopped working in the Notification Service Extension for some reason. –  Feb 11 '19 at 19:09
  • If you have the identifier, you can use the function 'UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: [reminder.Identifier])' to remove delivered notifications, does that work for you? – Alex Marchant Feb 11 '19 at 19:45
  • No. As I said in my original post, it's no longer possible to retrieve delivered notification in the service extension either. Nor is it possible to use either `UNUserNotificationCenter.current().removeAllDeliveredNotifications()` or `UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: [reminder.Identifier])`. Essentially, none of the `UNUserNotificationCenter.current()` methods seem to be functional in a `UNNotifiationServiceExtension` anymore, and I have no idea why. –  Feb 11 '19 at 20:01
  • If the API is not behaving correctly, you should file a bug against the API at bugreport.apple.com – Matthew Seaman Feb 12 '19 at 22:00

1 Answers1

2

It seems apns-collapse-id APNs request header might be useful here.

  1. It could be used to update former notification content and bring it to the top.

    Multiple notifications with the same collapse identifier are displayed to the user as a single notification.

  2. According to the docs, apns-collapse-id specifies notification identifier (which normally is random). BE could send a new "delete" notification with the given id in the payload to use it in removeDeliveredNotifications(withIdentifiers:) function.

Tomasz Pe
  • 696
  • 7
  • 19
  • Is there any reason to believe that `removeDeliveredNotifications(withIdentifiers:)` will do anything while `removeAllDeliveredNotifications()` does nothing? Also, `apns-collapse-id` can't be set by any cloud-based backend (as in, I'm not using a 100% custom built backend), since it's part of the APNS HTTP headers. The only properties that I'm able to set are the ones in the [APS JSON dictionary](https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/PayloadKeyReference.html#//apple_ref/doc/uid/TP40008194-CH17-SW2). –  Feb 14 '19 at 17:53
  • I've had problems with `removeAllDeliveredNotifications` (eg. on 11.2) but `removeDeliveredNotifications(withIdentifiers:` was working properly nonetheless. Radars were told to be fixed in 11.3 (eg. [35676570](https://openradar.appspot.com/35676570) ). Here is the [blogpost](https://medium.com/the-guardian-mobile-innovation-lab/how-to-replace-the-content-of-an-ios-notification-2d8d93766446) with some additional possible workaround. However, despite all of that, as mentioned before, you should check for existing opened radars for iOS 12 and open a new one if needed. – Tomasz Pe Feb 15 '19 at 12:09
  • I was using the workaround mentioned in that article of using a custom payload id in userInfo last year, and that's what stopped working, so looks like it's just all broken now. I did submit a bug report, but I guess I'll have to simply settle for letting the same categories of notifications stack for now. –  Feb 16 '19 at 02:27
  • Wow, is this really still a bug? `getDeliveredNotifications` still not working in iOS 13 – Kyle Redfearn Nov 18 '19 at 22:01
  • 2
    @KyleRedfearn Turns out it's actually an asynchronicity issue. Basically, getDeliveredNotifications and all the removal methods are all async. You can make sure the getDeliveredNotifications method runs by only running the Notification Service Extension's `contentHandler()` in the completion block, but there is NO completion block for the notification removal methods. I just recently asked Apple code-level support about this, and the only way to solve this is to use a timer delay (we used DispatchQueue.main.asyncAfter) to run the `contentHandler`, otherwise the extension is killed too quickly. –  Nov 19 '19 at 00:07
  • The method runs for me and I land in the completion block, `getDeliveredNotifications` returns 0 notifications, when there are notifications – Kyle Redfearn Nov 19 '19 at 18:08