To try and start out on the right foot, I have been searching SO and other resources all morning for a solution to this problem.
I have an app which works perfectly with silent foreground push notifications, as well as standard push notifications. Capabilities are set as below
The JSON that triggers the notification is as follows
{"device_types":["android","ios"],"notification":{"ios":{"extra":{"requests":{"directives":{"forceUpdate":1}}},"content-available":1}},"audience":{"tag":"userDevice=60218"}}
I have reduced the PushHandler delegate to the bare minimum for testing, from the UA example:
-(void)receivedBackgroundNotification:(UANotificationContent *)notificationContent completionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
// Application received a background notification
UA_LDEBUG(@"The application received a background notification");
// Call the completion handler
completionHandler(UIBackgroundFetchResultNoData);
}
-(void)receivedForegroundNotification:(UANotificationContent *)notificationContent completionHandler:(void (^)(void))completionHandler {
UA_LDEBUG(@"The application received a foreground notification %@",notificationContent);
completionHandler();
}
-(void)receivedNotificationResponse:(UANotificationResponse *)notificationResponse completionHandler:(void (^)(void))completionHandler {
UANotificationContent *notificationContent = notificationResponse.notificationContent;
NSLog(@"Received a notification response");
NSLog(@"Alert Title: %@",notificationContent.alertTitle);
NSLog(@"Alert Body: %@",notificationContent.alertBody);
NSLog(@"Action Identifier: %@",notificationResponse.actionIdentifier);
NSLog(@"Category Identifier: %@",notificationContent.categoryIdentifier);
NSLog(@"Response Text: %@",notificationResponse.responseText);
completionHandler();
}
- (UNNotificationPresentationOptions)extendPresentationOptions:(UNNotificationPresentationOptions)options notification:(UNNotification *)notification {
return options | UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert;
}
I have also looked at the device console (look for x.y.z for the identifier) and I see this:
default 09:48:34.413032 +0200 apsd <private> _notifyForIncomingMessage <private> with guid <private>
default 09:48:34.414156 +0200 apsd Dispatching low priority message on server: <private>
default 09:48:34.414656 +0200 SpringBoard <private> Delivering message from apsd: <private> 3373312264 <private>
default 09:48:34.414772 +0200 SpringBoard <private> responding with an ack for message with guid <private>
default 09:48:34.414816 +0200 SpringBoard <private> making delegate (<private>) calls to deliver message 3373312264 <private> for topic <private>
default 09:48:34.414842 +0200 SpringBoard <private> calling <private> connection:didReceiveIncomingMessage:
default 09:48:34.415254 +0200 SpringBoard <private> returned from <private> connection:didReceiveIncomingMessage:
default 09:48:34.415401 +0200 SpringBoard Received incoming message on topic x.y.z at priority 1
default 09:48:34.416402 +0200 apsd Looking up connection on peer: 3be332c0 found <private>
default 09:48:34.416460 +0200 apsd <private> informed that <private> acknowledges incoming message with guid <private> tracingUUID (null)
default 09:48:34.417113 +0200 apsd APSMessageStore - APSIncomingMessageRecordDeleteMessageForGUID <private>
default 09:48:34.418199 +0200 SpringBoard [x.y.z] Received remote notification request BBC2-437A [ hasAlertContent: 0, hasSound: 0 hasBadge: 0 hasContentAvailable: 1 hasMutableContent: 0 pushType: Background]
default 09:48:34.418312 +0200 SpringBoard [x.y.z] Deliver push notification BBC2-437A
default 09:48:34.418372 +0200 SpringBoard [x.y.z] Request DUET delivers content-available push notification to application
default 09:48:34.418476 +0200 SpringBoard SUBMITTING: <private>
default 09:48:34.419185 +0200 dasd Submitted Activity: com.apple.pushLaunch.x.y.z:FF3864 at priority 5 <private>
default 09:48:34.419315 +0200 dasd <private> was in pre-running. Removing due to submission of <private>
default 09:48:34.425019 +0200 dasd Adding a launch request (<private>) for application <private> by activity <private>
default 09:48:34.425069 +0200 dasd Launch requests for <private>: <private>
default 09:48:34.425219 +0200 dasd Daemon Canceling Activities: {(
com.apple.pushLaunch.x.y.z:3B7016
)}
default 09:48:34.425282 +0200 dasd CANCELED: com.apple.pushLaunch.x.y.z:3B7016 at priority 5 <private>!
default 09:48:34.425471 +0200 dasd Removing a launch request for application <private> by activity <private>
error 09:48:34.425534 +0200 dasd Activity <private> not tracked as being started, ignoring it
default 09:48:34.427417 +0200 dasd With <private> ...Tasks pre-running in group [com.apple.dasd.defaultNetwork] are 1!
default 09:48:34.427594 +0200 dasd Activity launch reason is not a BGTask reason. Returning YES
default 09:48:34.427720 +0200 SpringBoard cancelActivities: 1 activities were not found: <private>
default 09:48:34.427859 +0200 dasd Unconstrained Available=1
default 09:48:34.427892 +0200 dasd com.apple.pushLaunch.x.y.z:FF3864:[
{name: DataBudgetPolicy, policyWeight: 1.000, response: {Decision: Must Not Proceed, Score: 0.00, Rationale: [{[/system/budgets/networking]: Required:1.00, Observed:0.00},]}}
], FinalDecision: Must Not Proceed}
default 09:48:34.427937 +0200 dasd NO LONGER RUNNING [Not in application -> activity mapping] com.apple.pushLaunch.x.y.z:FF3864 ...Tasks running in group [com.apple.dasd.defaultNetwork] are 0!
receivedBackgroundNotification is never triggered.
I have checked everywhere and I seem to have all options set (but clearly do not). Any advice gratefully received.
UPDATE
When I put the app into the background in XCode, I get this message:
Can't end BackgroundTask: no background task exists with identifier 106 (0x6a), or it may have already been ended. Break in UIApplicationEndBackgroundTaskError() to debug
In the debugger, the break is occurring in [UAAsyncOperation setIsFinished]
By setting "content-available":1
you're using silent push notifications. Im not sure if it was any better in previous iOS's, but in iOS 13 this type of notifications have a apns-priority of 5 out of 10.
This means that they might be delayed, grouped and delivered in bursts, or even completely ignored.
For example, if the user force closes the app (swipe up), silent notifications are completely ignored. Also, there's a limitation of how many of those a user can receive per app per day.
Being said so, silent push notifications are not suitable for when you need to guarantee your notifications will get delivered.
Try regular push notifications instead (or maybe use the Notification Service App Extension, if you want to change the content of the notification before displaying it to the user). They might arrive with a little delay, but they will be delivered.