Silent pushes not delivered to the app on iOS 11

IosPush NotificationIos11

Ios Problem Overview


I noticed that on iOS 11 beta 2, the silent notifications are not delivered to the application:didReceiveRemoteNotification:fetchCompletionHandler regardless the state of the app (background / foreground).

I implemented the UIApplicationDelegete method application:didReceiveRemoteNotification:fetchCompletionHandler and I send the following silent push

{  
  "aps": {  
    "content-available": 1  
  },  
  "mydata": {  
    "foo": "bar"  
  }  
} 

but the delegate method is not called on iOS 11.

It works fine on other versions of iOS and the documentation section Configuring a Silent Notification does not mention that anything else should be done.

Is this a bug in iOS 11 or did I miss something new in iOS 11?

Please note that I'm not talking about or using the UserNotification framework which should not be needed for sending silent pushes.

Here is a sample project that illustrates the issue (you'll have to set your own bundle id)

When you lunch the sample project and send a above payload to the app, you can use the macOS console to see that the push is correctly delivered to the device but not to the app.

UPDATE 10.08

It appears that the behaviour is random. Sometimes after restarting the device, the payload is delivered correctly but it stops working after a while.

As you can see on the following screenshot, the push marked as 1 is delievered only to the device and the push 2 (after device restart) is also delivered to the app.

enter image description here

UPDATE 14.08 - iOS 11 Beta 6

Still the same behaviour. Another thing that is supposed to work but does not is the following. When the application's scheme is set to "Wait for executable to be launched", a silent push is supposed to wake up the app and start it in background.

enter image description here

UPDATE 21.08 - iOS 11 Beta 7

Still the same behaviour and not updates from Apple in the bug report.

#UPDATE 29.08 - iOS 11 Beta 8

Still the same problem. The steps to reproduce I use now are the following:

  • In the Xcode project scheme, select "Wait for executable to be launched"
  • Add a breakpoint in the didReceiveRemoteNotification: fetchCompletionHandler
  • Start the app on device
  • Send the above silent push

Expected: The app is brought from suspended state to background and the didReceiveRemoteNotification: fetchCompletionHandler is called

Actual: nothing happens

UPDATE 06.09 - iOS 11 Beta 10

I'm still having the same buggy behaviour. The ticket from Apple was updated with the following answer:

> Apple Developer Relations September 6 2017, 10:42 PM Engineering has > provided the following feedback regarding this issue: > > We were able to get the sample app running and test the behavior. We > didn’t see any issues when we tested this as described. > > Pushes aren't guaranteed to arrive to the app when it is running in > the background, and the logs here indicate we don't believe the app is > being used enough to launch it. > > We do see us delivering pushes from time to time when conditions are > good. > > We believe this is behaving correctly.

Update 11.09

My Apple bug report was closed and marked as duplicate of 33278611 which remains open

UPDATE 13.09 - iOS 11 GM

Thanks to kam800's comments (see below) I did more testing and came up with those observations:

There seem to be a new daemon in iOS 11 dasd DuetActivitySchedulerDaemon that either completely discards the data push or delays the data push delivery:

Delivery postponed

Console Logs

default	13:11:47.177547 +0200	dasd	DuetActivitySchedulerDaemon	CANCELED: com.apple.pushLaunch.net.tequilaapps.daylight:C03A65 <private>!	lifecycle	com.apple.duetactivityscheduler
default	13:11:47.178186 +0200	dasd	DuetActivitySchedulerDaemon	Removing a launch request for application <private> by activity <private>	default	com.apple.duetactivityscheduler
default	12:49:04.426256 +0200	dasd	DuetActivitySchedulerDaemon	Advancing start date for <private> by 6.5 minutes to Wed Sep 13 12:55:31 2017	default	com.apple.duetactivityscheduler
default	13:21:40.593012 +0200	dasd	DuetActivitySchedulerDaemon	Activity <private>: Optimal Score 0.6144 at <private> (Valid Until: <private>)	scoring	com.apple.duetactivityscheduler
default	13:21:40.594528 +0200	dasd	DuetActivitySchedulerDaemon	Setting timer (isWaking=1, activityRequiresWaking=0) between <private> and <private> for <private>	default	com.apple.duetactivityscheduler

Postponed delivery issues

  • When the data push delivery is postponed and the app is launched, the data push is delivered only when the delivery date is reached which can be several minutes in the future. This defeats completely the purpose of using data pushes to keep the new app's content ready for the next launch. I quote here once again Apple's documentation:

> "Silent notifications improve the user experience by helping you keep > your app up-to-date, even when it is not running."

  • When two data pushes are sent to a suspended app they are postponed by iOS 11 instead of waking up the app directly. When delivery time is reached, only the last data push is delivered! The previous pushes are lost and not delivered via the delegate method resulting in a data loss.
Delivery cancelled

Console Logs

default	13:35:05.347078 +0200	dasd	DuetActivitySchedulerDaemon	com.apple.pushLaunch.net.tequilaapps.daylight:C03A65:[
	{name: ApplicationPolicy, policyWeight: 50.000, response: {Decision: Must Not Proceed, Score: 0.00}}
 ], FinalDecision: Must Not Proceed}	scoring	com.apple.duetactivityscheduler

Cancelled delivery issues

Well in this case, the data push is completely lost and never delivered on iOS 11 while it was delivered correctly on iOS 10.

UPDATE 19.09 - iOS 11 GM

I also noticed that when the application is in the foreground and the notification is not delivered to the app, I see the following logs in the console:

default	08:28:49.354824 +0200	apsd	apsd	<private>: Received message for enabled topic '<private>' onInterface: NonCellular with payload '<private>' with priority 10 for device token: NO	courier-oversized	com.apple.apsd

fault	08:33:18.128209 +0200	dasd	Foundation	<NSXPCConnection: 0x151eee460> connection from pid 55: Exception caught during decoding of received message, dropping incoming message.
Exception: Exception while decoding argument 0 (#2 of invocation):
Exception: value for key 'NS.objects' was of unexpected class 'NSNull'. Allowed classes are '{(
    NSArray,
    NSData,
    NSString,
    NSNumber,
    NSDictionary,
    NSUUID,
    _DASActivity,
    NSSet,
    _DASFileProtection,
    NSDate,
    NWParameters,
    NWEndpoint
)}'.	general	com.apple.foundation.xpc

Ios Solutions


Solution 1 - Ios

So the release notes of iOS 11.1 beta 1 say

> iOS 11.1 beta 1 was just released and they mention: > "Notifications > Resolved Issues > • Silent push notifications are processed more frequently. (33278611)

I did some tests and it seems to be indeed fixed:

Suspended State

When I launch the app in a suspended mode and send a silent push, the app is brought back to background and the didReceiveRemoteNotification:fetchCompletionHandler delegate is called.

Foreground State

In the same way, when the application is in foreground and a silent push is sent, the delegate seems to be called as expected. This was randomly not working in previous iOS 11 versions so I will confirm this after more testing.

Solution 2 - Ios

Just wanted to add my 2 cents in here as I've been hit by this issue too and I've noticed that Apple has closed several radars on this issue saying they couldn't reproduce. An interesting thing I found is that the pushes will get delivered if the app is backgrounded while it's attached to the debugger.

If I kill the debugger, unplug my phone, launch the app, and send the silent push payload I see the app NOT getting woken. I do see the in the Console log that the system cancels delivery of the payload to my app.

I've submitted a radar with a small sample app that reproduces the problem. I've also explicitly noted in the radar that the person working on my ticket must not be running the app attached to the debugger to reproduce the issue. Here's the link: https://bugreport.apple.com/web/?problemID=34461063

Hopefully this will cause some progress to be made on this issue.

Solution 3 - Ios

Looks like a new behaviour of iOS 11. iOS 11 beta 10 provides some descriptive logs regarding this issue:

default	23:18:51.806011 +0200	dasd	com.apple.pushLaunch.com.acme.Acme:F7E7D0:[
	{name: ApplicationPolicy, policyWeight: 50.000, response: {Decision: Can Proceed, Score: 0.50}}
	{name: BatteryLevelPolicy, policyWeight: 1.000, response: {Decision: Can Proceed, Score: 0.87, Rationale: [{batteryLevel == 62}]}}
	{name: DeviceActivityPolicy, policyWeight: 5.000, response: {Decision: Can Proceed, Score: 0.20}}
 ] sumScores:52.279483, denominator:81.410000, FinalDecision: Can Proceed FinalScore: 0.642175}
default	23:18:51.806386 +0200	dasd	'com.apple.pushLaunch.com.acme.Acme:F7E7D0' has compatibility score of 1.000000 with 'com.apple.CFNetwork-cc-111-79:E7272D'. Relaxing scores.
default	23:18:51.806855 +0200	dasd	'com.apple.pushLaunch.com.acme.Acme:F7E7D0' CurrentScore: 0.642175, ThresholdScore: 0.738454 DecisionToRun:0

Looks like every silent push is delivered to the iOS, but dasd daemon uses couple of policies to decide if silent push should be delivered to the app (e.g. battery level). I managed to receive one silent push yesterday night, but my iPhone was connected to charger at that time – probably BatteryLevelPolicy score was high enough to receive that one silent push.

Apple gives no official information about this iOS-side behaviour, there is only information about server-side throttling:

> Silent notifications are not meant as a way to keep your app awake in > the background, nor are they meant for high priority updates. APNs > treats silent notifications as low priority and may throttle their > delivery altogether if the total number becomes excessive. The actual > limits are dynamic and can change based on conditions, but try not to > send more than a few notifications per hour.

I keep my fingers crossed they changed that behaviour, because that would fix my app :) On the other hand, this change is good – one among many things making iPhone battery lasting longer that Android phones.

Solution 4 - Ios

iOS 11.1 beta release notes include: Notifications Resolved Issues Silent push notifications are processed more frequently. (33278611)

Solution 5 - Ios

iOS 11.1 Beta 2 also contains

Notifications
Resolved Issues
• Silent push notifications are processed more frequently. (33278611)

in Release Notes - will test it now.

UPDATE - 11.10.2017 - iOS 11.1 Beta 2

After using our App for 2 days in "real world scenarios" it looks like there is a real improvement in this version of iOS. I am cautiously starting to believe this is fixed.

Solution 6 - Ios

Apple Developer Relations just added a comment to my radar:

> We believe this issue is resolved in the latest iOS 11.2 beta. > > Please test with the latest iOS beta. If you still have issues, please > update your bug report with any relevant logs or information that > could help us investigate. > > https://developer.apple.com/download/

currently installing iOS 11.2 beta - will test silent push behaviour

Solution 7 - Ios

I had similar issue with my app, till iOS 10 I was getting push notifications and application:didReceiveRemoteNotification:fetchCompletionHandler were getting called correctly.But when updated to iOS 11 push notifications stopped working.

Issue with my code was , even though i was using content-available:1 and mutable-content:1 in push notification payload,the Background Fetch option was not turned on. But It was working perfectly till iOS 10.

Make sure you turned ON both these capabilities.

After Turning Background Fetch capability ON it is working Now

Solution 8 - Ios

iOS 11.4.1, Swift 4

I was having issues with silent pushes not arriving (from CloudKit) and I tried everything everyone has mentioned here. Then I decided to try setting a blank alertBody to my CKNotificationInfo() objects like this:

let info = CKNotificationInfo()
info.shouldSendContentAvailable = true
info.alertBody = ""

This made the pushes get sent at a higher priority (but they were still silent pushes) and I no longer got the error in my device logs that the push was being ignored.

I hope that helps someone. :)

Solution 9 - Ios

So this is indeed a bug in iOS 11 and it's now fixed in iOS 11 beta 3. The application:didReceiveRemoteNotification:fetchCompletionHandler is now called correctly when a silent push is received both in foreground or in background.

UPDATE

No it is not fixed and is still happening in iOS beta 3 and 4

Solution 10 - Ios

As a workaround We're adding a "notification" key and inside a "title" with empty string as a value. This is wake up the didReceive callback in the appDelegate.

Solution 11 - Ios

As of writing this answer I am facing the exact same issue as Bill Dunay's answer.

My requirement was to receive silent notifications when the app is in foreground and nothing when the app is in the background/not running. And my workaround was this. I do not use badges hence setting it to zero is not an issue for me.

{
	"aps" : {
		"badge" : 0,
		"sound" : ""
	},
    "mydata": {  
		"foo": "bar"  
	}  
}

Please note I am deliberately not using "content-available". Setting that causes the iOS optimization logic to kick in delaying/cancelling the delivery of the notification.

Solution 12 - Ios

I have been getting the same issue for some notifications (not necessarily silent).

After reviewing all the updates and answers I am able to add two updates that may help:

  • I found that accessing UIApplication.shared.isRegisteredForRemoteNotifications method while receiving a notification causes the application to stall without reporting anything to Xcode. Check if you are running some code after you receive the notification that accesses the method. (https://stackoverflow.com/questions/43052474/isregisteredforremotenotifications-locking-ui-with-semaphore-wait-trap).

  • I discovered that I had a push notification parsing error on the console due to the "title-loc-args" : [3333] not accepting 3333 literally but accepting it as a string "title-loc-args" : ["3333"]. This made my entire interface stall after I access the method above, only on iOS 11, it works on iOS 12.

  • I also found out that, with the exact same code, it works without any issue on iOS 12.0 (16A5366a). But on iOS 11 it is happening.

Solution 13 - Ios

In my case silent notifications was used to update ui after job was done on server site so it was pain in ass to have non relevant content in app. Because our payload for silent notification contains even title and body I implement these methods to get working notifications in active / inactive app, not charging and with Background App Refresh turned off and even in Low Power state.

To get this working I add delegate and create extension with UNUserNotificationCenterDelegate protocol and willPresent notification (iOS 10+) method, that is triggered every time with correct payload. To not show notification when app is active just call completion with badge or sound. I ended up with something like this

    import UserNotifications

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?
    
    // MARK: - Lifecycle
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        UNUserNotificationCenter.current().delegate = self
        return true
    }
    
    //this was only method to handle notifications before
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any],
                     fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        //process silent notification
        completionHandler(UIBackgroundFetchResult.newData)
    }
}

extension AppDelegate : UNUserNotificationCenterDelegate {
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        //proces notification when app is active with `notification.request.content.userInfo`
        if UIApplication.shared.applicationState == .active {
            completionHandler(.badge)
        }else {
            completionHandler(.alert)
        }
    }
}

And to get working these states when app is in background and silent notification don't call my methods I get notifications from notification center directly in applicationDidBecomeActive by:

UNUserNotificationCenter.current().getDeliveredNotifications { (notifications) in
            debugLog(message: "unprocessed notification count: \(notifications.count)")
            if notifications.count > 0 {
                notifications.forEach({ (notification) in
                    DispatchQueue.main.async {
                        //handle `notification.request.content.userInfo`
                    }
                })
            }
        }

Solution 14 - Ios

In my case, "Background App Refresh" was turned off in iPhone settings. Because of this push notification was delivered to the device but not on the app. Turning Background App Refresh on receives the silent push in the app.

This may not be the actual answer for this question, just in case if anyone need to check.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJanView Question on Stackoverflow
Solution 1 - IosJanView Answer on Stackoverflow
Solution 2 - IosBill DunayView Answer on Stackoverflow
Solution 3 - Ioskam800View Answer on Stackoverflow
Solution 4 - IosAndrew GouldView Answer on Stackoverflow
Solution 5 - IosThomas EinwallerView Answer on Stackoverflow
Solution 6 - IosThomas EinwallerView Answer on Stackoverflow
Solution 7 - IosSudeep georgeView Answer on Stackoverflow
Solution 8 - IosClifton LabrumView Answer on Stackoverflow
Solution 9 - IosJanView Answer on Stackoverflow
Solution 10 - IoselkorbView Answer on Stackoverflow
Solution 11 - IosRammohan RajaView Answer on Stackoverflow
Solution 12 - IosRageofflamesView Answer on Stackoverflow
Solution 13 - IosPacyjentView Answer on Stackoverflow
Solution 14 - IosAnishView Answer on Stackoverflow