Hello everyone,
We have a feature in our iOS app called "automatic background sync", which syncs data between the mobile app and our backend periodically. It is specifically designed to work when the app is in a backgrounded state.
We use both silent remote notifications that are sent from our backend periodically (using Firebase Cloud Messaging), and also BGAppRefresh task. The sync process should be as reliable as possible and work continuously while the app is in the background, even if the user does not open the app for a long period of time. We enforce a 20 second deadline to call the completion handler to match the 30 second limit.
We have a specific customer that has multiple where the background sync does not work properly: One of them has continuous syncs for about a week, then it stops until the user opens (moves to foreground) the app again. Another user only has a sync when they open the app, then it stops when it is backgrounded.
Looking at their logs: The app remains in the background and is rarely being actively killed, and it likely is not the reason that the user stopped receiving syncs. Their background app refresh setting in iOS settings is enabled. Both user's app stopped waking up and doing the task either from silent remote notifications or background tasks.
Thank you!
Activating an app using these methods, both silent notifications and BGAppRefresh tasks, can't be guaranteed to work "continuously", as you put it.
Both of these methods are executed at the discretion of the system, and will be only run when the device/system state is appropriate for background tasks to run.
Regardless how well behaved your app may be, if the general conditions are not suitable, your processes will not be run.
Specifically for silent notifications, there is a device-wide budget of 1-2 notifications per hour that would be allowed to execute their apps, and if this one user has another app that is doing the same thing as you, the device budgets could be running out before it is your turn, and the app will not be activated. Also, as silent notifications must be low priority, it is possible that they are being held on the server side before being delivered, and device behavior will effect that as well.
As for the cases where launching the app makes a difference, that is also a correct observation. Apps which are not routinely launched by the users may stop being launched in the background.
And as for your comment "is rarely being actively killed" killing the app by the user (swiping it off) will prevent any of this to work until the user relaunches the app themselves again. Once is enough.
Additionally, there are various quotas of what apps (all apps) in general can do in the background vs. the system state. Low battery, excessive use of cellular data, and even the thermal state of the device may cause the system to decide not to run background tasks.
So, most likely the issue is caused by user behavior, how they use their devices, what other apps are using the same resources, and so on. there is little you can do about this.
If you want a reliable way to execute code against sending push notifications, your best bet would be looking into using a Notification Service Extension as discussed at https://developer.apple.com/documentation/usernotifications/unnotificationserviceextension.
The Notification Service Extension will be executed for every visible push notification. So, it could serve your needs, as long as the user has not disabled the visibility of your notifications through various settings.
The service extension will not be executed for push notifications that will not be presented visually, so that is the price you pay for reliable execution.
Argun Tekant / WWDR Engineering / Core Technologies