Background push does not work when app is in Not-Running/Suspended state
Asked Answered
B

0

0

I've been studying push notifications, specifically background push. I've followed Apple docs and various stackoverflow posts - Added Push Notifications capability, Remote Notifications in Background modes (as shown below), enter image description here

registered with APNS, obtained a device token and implemented the application(_:didReceiveRemoteNotification:fetchCompletionHandler:) to receive background pushes.

// In AppDelegate.swift

static let sApp: UIApplication = UIApplication.shared
    
func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        
    // Register with APNS for device token.
    RegisterForRemoteNotifications()
        
    return true;
}
func RegisterForRemoteNotifications() {
    
    AppDelegate.sApp.registerForRemoteNotifications()
}
    
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
        
    Log(String(format: "error.localizedDescription = %@", error.localizedDescription))
}
    
// Log(_:) is my custom log function.
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken pDeviceToken: Data) {
        
    // Print the device token as a string.
    Log("pDeviceToken = " + pDeviceToken.hexEncodedString())
}
    
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {

    ....
}
        

I don't have a server.. I'm using commandLine utilities to send background pushes as described here.

This is my curl command,

curl -v --header "apns-push-type:background" --header "apns-priority:5" --header "apns-topic: $TOPIC" --header "authorization: bearer $AUTHENTICATION_TOKEN" --data '{"aps":{"content-available":1},"Purpose":"Background update"}' --http2 https://${APNS_HOST_NAME}/3/device/${DEVICE_TOKEN}

When app is in foreground, I get background pushes without fail i.e., the application(_didReceiveRemoteNotiofication:fetchCompletionHandler:) is invoked to process the background push. But when app is not running, it doesn't work. When app is brought to foreground, the background push which was supposed to happen when app is not running, is now received. Same is when app is in suspended state.

I believe I have everything that is required for background pushes. All push notifications (including background pushes) are supposed to work even when app is not running. But in my case, it happens only when app is in foreground. What's the point of background push which never works when app is not running or in background? In foreground, app can just sync with server by itself. Background push is to update the content when app is not running.

What is missing here?

Environment: iOS 16.0 (real device), Xcode 14.2, phone battery = 100% (connected to Mac).

Update1: Few days after posting this question, the background notification are now waking up the app. Based on comments from Paulw11, I was convinced that this was not supposed to happen. But now, it happens... not consistently, but once in 3 times. Pasting the logs,

application(_:willFinishLaunchingWithOptions:)
...
RequestUserPermission() // Ask user permission to show notifications (not relevant for this post)
RegisterForRemoteNotifications() // Register with APNS
application(_:didFinishLaunchingWithOptions:)
...
CreateMainWindow()
...
application(_:didRegisterForRemoteNotificationsWithDeviceToken:) // Registration with APNS is successful
...
applicationDidBecomeActive(_:)
applicationWillResignActive(_:)
applicationDidEnterBackground(_:)
...
applicationwillTerminate(_:) // swiped the app from app switcher
// New launch due to background notification
application(_:willFinishLaunchingWithOptions:)
RequestUserPermission()
RegisterForRemoteNotifications()
application(_:didFinishLaunchingWithOptions:)
CreateMainWindow()
application(_:didReceiveRemoteNotification:fetchCompletionHandler:)
...
application(_:didRegisterForRemoteNotificationsWithDeviceToken:)
...
Baucis answered 27/4, 2023 at 3:0 Comment(9)
You aren't missing anything. A background push notification will not relaunch a terminated app. A VoIP push can relaunch a terminated app, but you must then report an incoming call via CallKit. You should receive background push notifications when your app is suspended, but these can be rate limited. I wouldn't expect the limit to apply when running under the Xcode debuggerNotate
@Paulw11, App is not attached to debugger though I am using the development apns server and a debug app. Quoting the first line from Apple docs, Use remote notifications (also known as push notifications) to push small amounts of data to devices that use your app, even when your app isn’t running. I have tested user notifications and they do work when app is not running. But not background notifications. Apple doc is wrong here?Baucis
It depends on how you stopped the app - From the method documentation you linked in your question "However, the system does not automatically launch your app if the user has force-quit it. In that situation, the user must relaunch your app or restart the device before the system attempts to launch your app automatically again"Notate
Also, from the first document you linked to "If something force quits or kills the app, the system discards the held notification." - If your app runs for more than 30 seconds without calling the completion handler, it will be terminated and will not be relaunched.Notate
@Notate Thanks. That makes sense. But it's weird that contradicting statements were made in two different places in Apple docs.Baucis
@Paulw11, Can you elaborate on 'how you stopped the app'? Linked doc says However, the system does not automatically launch your app if the user has force-quit it. In that situation, the user must relaunch your app or restart the device before the system attempts to launch your app automatically again. But I suddenly started receiving background notifications... even after swiping the app form the app switcher - which is not supposed to happen after user has force-quit i.e., swipe it from the app switcher', right? (Logs attached in the question).Baucis
@Baucis hi, have you found the way to solve it? I have the same issue with VoIP pushkit?Keffer
@Keffer Nope. According to documentation, Background Push Is not supposed to happen. But Background push works sometimes.. roughly 1 in 3 times for me. Maybe things will be different in a production app.... I have only tested this in a debug app.Baucis
@Alex, Is PushKit also having the same issue? According to this stackoverflow post, PushKit doesn't have this problem. I don't know much about PushKit though. Do post another question if the stackoverflow I linked just now didn't help.Baucis

© 2022 - 2024 — McMap. All rights reserved.