Is it possible to prevent a remote notification from being displayed?
Asked Answered
V

6

23

I'd like to better control what notifications are being displayed to my users and selectively silence some of them. In order to do this I have implemented a UNNotificationServiceExtensionin my app, which allows me to intercept and modify notifications even when my app is not running. The problem however is that even if I don't call didReceive(_:withContentHandler:) the system will still display the remote notification after approximately 30 seconds. How can I prevent this from happening?

Valiancy answered 19/4, 2017 at 15:19 Comment(6)
Silent Push is no option for your specific case?Magee
@Magee Silent notifications are throttled and Apple suggests not using more than a few per hour.Valiancy
Well, so in your case you need frequent push notifications per hour but want to surpress the notification to the user?Magee
Yes, the idea is that I may want, for example, to display a summary instead of bombarding the user with notifications.Valiancy
Can you fix it server side so that it sends the summary from there?Gaiety
@Gaiety That wouldn't make a difference because I still can't delete the previous remote notifications I received.Valiancy
M
32

As of iOS 11, it is not possible to suppress push notifications from being displayed using a UNNotificationServiceExtension.

In WWDC 17's Best Practices and What’s New in User Notifications, Teja states explicitly that such a thing cannot be done (starting at 22:17 min):

All work should be either about modifying or enhancing this notification. The service extension also doesn't have the power to drop this notification or prevent it from being displayed. This notification will get delivered to the device. If instead you want to launch your application in the background and run some additional processing, you should send a silent notification. You can also send a silent notification and launch your app in the background and your app can determine whether or not to schedule a local notification if you want to present a conditional notification.

From iOS 13.3 the notification service entitlement com.apple.developer.usernotifications.filtering allows for filtering notifications (as pointed out in Aviharsh Shukla's comment).

Malloch answered 11/9, 2017 at 14:15 Comment(5)
The question is why not? In that same video they do explicitly say the extension can't prevent display of the notification. But why didn't say why not. Is there some other mechanism they intended? In our case, we have multiple shifts of employees using the same phone. Its possible a phone could get previous user's notifications. The extension could filter them out, but we can't hide it. Best we can do is redact. Thats far from ideal.Glynda
am having the same scenario as stated by @David, did someone find solution to this?Hawse
Check this out developer.apple.com/documentation/bundleresources/entitlements/…Exosmosis
@AviharshShukla, thanks. that's exactly what I was looking for - the ability of the extension to drop a notification.Utah
If anyone is not able to find the WWDC17 video attached in question, here's the video link.Utah
C
20

Just for completeness:

When the app is not active (in the background or killed) Landschaft's answer does apply: one cannot suppress any push notification.

But if the app is active in the foreground it is possible to suppress push notifications.

Instead of using the app extension, one needs to implement the willPresent function from the UNUserNotificationCenterDelegate.

Here one can filter the notifications and in the completionHandler return how it is allowed to be presented:
• display nothing: completionHandler([])
• display only alert: completionHandler([.alert])
• display alert with sound: completionHandler([.alert, .sound])
• etc...

We wanted to display local notifications but never display push notifications as we handle them in-app with a custom UI:

func userNotificationCenter(_ center: UNUserNotificationCenter, 
                            willPresent notification: UNNotification, 
                            withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
    if response.notification.request.trigger is UNPushNotificationTrigger {
        completionHandler([])
    } else {
        completionHandler([.alert, .badge])
    }
}
Consideration answered 19/8, 2019 at 9:55 Comment(1)
This is the right ExplanationBozen
U
10

Starting from iOS 13.3 it is possible. You can prevent it from being displayed in User Notification Extension. All you need to do is to be granted from Apple the Notification Service Entitlement and set apns-push-type header field to alert.

You can check this for all the details: https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_developer_usernotifications_filtering

Unific answered 22/3, 2021 at 19:30 Comment(2)
just sharing apple link will not help. Try to explain how to do this. ThanksScevo
As of today, you must request this feature to be enabled by Apple. It is not entitled by default.Quanta
Q
3

Try this code if you want to alert the particular type notification only,

I have added here to display the alert of two type of notification i.'tokenupdate' and ii.'notificationv1' rest of type will not display alert of notification.

Check below code, Hope this help you.

    func userNotificationCenter(_ center: UNUserNotificationCenter,
                            willPresent notification: UNNotification,
                            withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
    let userInfo = notification.request.content.userInfo
   
    let type =  userInfo[AnyHashable("type")] as? String
    if type == "tokenupdate"{
        handleNotification(userInfo: userInfo)
        completionHandler([.alert,.badge,.sound])
    }
    else if  type == "notificationv1"{
        let deleteType =  userInfo[AnyHashable("AppointmentFlag")] as? String
        if deleteType?.replacingOccurrences(of:" ", with: "") == "B"{
            let ids =  userInfo[AnyHashable("id")] as? String
            AppointmentManager().deleteById(id: "\(ids!)")
        }
        completionHandler([.alert,.badge,.sound])
    }

  
  
}
Quinn answered 4/9, 2023 at 13:42 Comment(0)
D
0

It's really easy to miss a comment above by @Lepidopteron and falsely assume there is absolutely no way to suppress the push notification - there is, and it's called silent push notification. It has a few limitations though. As stated in Apple's docs, you can send only 2-3 of these an hour, and there is no delivery guarantee.

Demission answered 11/3, 2020 at 7:46 Comment(0)
R
0

swift 5 iOS 11.x

I got this to work, but it is a bit of dance. Basically you need to send a silent notification to the device you don't want to send you a notification and then get that device to check the list of devices it shouldn't send notifications too BEFORE sending the notification.

The willPresent works too, perfectly... but as mentioned only if your application is running in the foreground. Obviously it has to check its list of banned devices too.

Roguery answered 14/3, 2020 at 17:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.