Push notifications and background work
Your app is usually not running. When something happens on the server, you need to reach the device without polling. Push notifications do that, and the platform’s background schedulers let you do follow-up work within the system’s limits.
How push works
Your server never talks to the phone directly. It sends a message to the platform’s push service, which keeps one efficient connection to each device.
- APNs (Apple Push Notification service) delivers to iOS devices.
- FCM (Firebase Cloud Messaging) delivers to Android devices, and can also send to iOS through APNs.
your server -> APNs / FCM -> device OS -> your app
Tokens and their lifecycle
To address a device, the app asks the OS for a push token and sends it to your server, tied to the signed-in user. On iOS you call registerForRemoteNotifications() and receive the token in a delegate callback; on Android the FCM SDK gives you a registration token.
Tokens change: reinstalling, restoring onto a new phone or clearing app data can all produce a new one. So:
- send the token to your server whenever you receive it, not only on first launch;
- store tokens per device, since a user may have several;
- delete a token when APNs or FCM reports it as no longer valid;
- detach the token from the account when the user signs out.
class PushService : FirebaseMessagingService() {
override fun onNewToken(token: String) {
// Upload in the background; the user may be offline.
TokenUploadWorker.enqueue(applicationContext, token)
}
}
Notification messages and data messages
There are two broad kinds of push.
- A notification message contains a title and body that the OS shows itself. It reaches the user even when your app is not running, and your code typically does not run until they tap it.
- A data message (on iOS, a background push with
content-available) carries a payload for your code, without showing anything by itself.
Data and background pushes are less reliable. iOS throttles background pushes and does not deliver them to an app the user has force-quit. Android may deprioritise high-priority FCM messages from an app whose messages rarely lead to a visible notification. For anything the user must see, send a visible notification. Payloads are small, about 4 KB on both services, so send an id and fetch the details.
Ask for permission at the right moment
iOS requires permission to show notifications, and so does Android from version 13. If you ask at first launch, before the user knows why, many will refuse, and after a refusal the system may not show the prompt again; the user has to find your app in Settings.
Ask when the value is obvious, such as after the user follows a delivery. Many apps first explain what they will send on their own screen, then trigger the system prompt. iOS also offers provisional authorisation, which delivers notifications quietly to the notification centre without asking first.
Background work
Neither platform lets you run whenever you like.
- On Android, WorkManager runs deferrable work that must eventually happen, such as uploading a photo or syncing, with constraints like network type or charging. It survives restarts and reboots, but the system chooses the exact time.
- On iOS, BGTaskScheduler schedules
BGAppRefreshTaskfor short refreshes andBGProcessingTaskfor longer maintenance. You register identifiers inInfo.plist, and the system decides when, and whether, to run them.
Keep tasks short, save progress as you go, and expect to be stopped at any point.
Don’t rely on delivery
Push is best effort. Devices are offline, users disable notifications, and messages get collapsed, dropped or delayed. APNs keeps only the most recent notification for an offline device.
Treat push as a hint that something changed, and sync from the server when the app opens, so a missed push costs a delay, not lost data.
Checklist
- Upload tokens on every change, per device, and remove invalid ones.
- Use visible notifications for anything the user must see.
- Ask for notification permission after the user sees why.
- Sync on app open; never let push be the only way data arrives.