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),
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:)
...
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? – BaucisHowever, 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