NotificationServiceExtension. The pattern mirrors iOS Live Activities, but it is implemented in your app code rather than provided by OneSignal as a managed feature. Use it for progress bars, sports scores, ride status, or any other content that should update inside one persistent notification instead of stacking new pushes.
Live Notifications require the user to have push notifications enabled.
Requirements
- Latest OneSignal Android SDK integrated in your app.
- The end user has granted push notification permission.
- A
NotificationServiceExtensionin your app to intercept and render Live Notifications. See Service extensions for background.
How it works
OneSignal is the transport. Your app code defines the schema and renders the UI. The flow:- Your backend calls the Create message API with a
collapse_idand a structuredlive_notificationobject insidedata. - OneSignal delivers the push to the device.
- Your
NotificationServiceExtensionintercepts every push, looks for thelive_notificationkey, and dispatches based on itsevent(start,update, orend). - Your code calls
NotificationManager.notify(id, …)with the same Android notification ID each time, which updates the existing notification rather than posting a new one.
The
live_notification payload, its field names, and the start / update / end event values are a convention introduced by this guide. They are not enforced by OneSignal. You can rename or restructure anything as long as your service extension and your sending backend agree.Live Notifications vs. standard push
Unlike regular push notifications, which post a new notification each time, Live Notifications use one persistent notification updated over time. Two things make this work:collapse_idon the API side keeps later messages tied to the same logical notification. See Collapse ID (mobile push).- A stable Android notification ID on the device side lets
NotificationManager.notify(id, …)replace the visible notification’s contents instead of stacking a new one.
Implementation
1. Add a Notification Service Extension
Create a class that implementsINotificationServiceExtension. Place it at app/src/main/java/<your-package-path>/NotificationServiceExtension.kt, where <your-package-path> matches your app’s package (for example, com/yourcompany/yourapp/).
The class below is complete and runnable. It creates the notification channel on first use, parses the live_notification payload, dispatches by event, and renders a progress notification. Replace com.onesignal.sample.android in the package declaration with your app’s package name (for example, com.yourcompany.yourapp); the same fully qualified name must appear in the Manifest entry in Step 2. The @Keep annotation is required to stop R8 or ProGuard from stripping or renaming the class when minification is enabled. See Service extensions for more on writing service extensions.
NotificationServiceExtension.kt
Channels for Live Notifications should be low importance with badges, vibration, and sound disabled so frequent updates don’t alert the user. See Android notification categories.
2. Register the extension in the Android Manifest
Openapp/src/main/AndroidManifest.xml and paste the following <meta-data> tag inside the existing <application> block. Do not create a new file, and do not add a <service> tag. The <meta-data> entry alone tells OneSignal which class from Step 1 to call when a push arrives.
- Leave
android:nameexactly as shown. - Set
android:valueto the fully qualified name of your class (thepackagedeclaration inNotificationServiceExtension.ktplus the class name).
Steps 1 and 2 are the only Android file changes. The remaining steps cover payload format and how to send Live Notifications from your backend.
3. Define your Live Notification payload
Each Live Notification carries alive_notification object inside the push’s data field. The schema is a convention you control. The shape used in this guide:
Example payload (start of a sports score Live Notification):
4. Handle the lifecycle events
Your service extension dispatches on theevent field. The example code above does this in handleLiveNotification.
Verify you’re ready to test
Before sending curl requests, confirm the following:- The device shows as subscribed in the OneSignal dashboard.
- Push permission is granted on the device.
- You have a Subscription ID or External ID for the target user.
- You have your app’s REST API key from Settings → Keys & IDs.
Send a Live Notification
Sendstart, update, and end events with the Create message API. Every request must:
- Set the same
collapse_idso OneSignal collapses later messages onto the first one. The ID must be unique to that specific Live Notification instance. - Target the same set of users (typically with
include_subscription_idsorinclude_aliases.external_id). - Use
isAndroid: trueto restrict delivery to Android push subscriptions.
Start
Sendevent: "start" to create the Live Notification. Initialize both static (event_attributes) and dynamic (event_updates) data.
Start
Update
Sendevent: "update" with new event_updates data. You can update as many times as you like after start.
Update
End
Sendevent: "end" to dismiss the Live Notification. The service extension calls NotificationManager.cancel(id) to remove it from the user’s device.
End
FAQ
Are Android Live Notifications a managed OneSignal feature?
No. They are a pattern you implement in yourNotificationServiceExtension on top of OneSignal push and Android’s NotificationManager. OneSignal does not track Live Notification state, manage update lifecycles, or expose Live Notifications in the dashboard. The schema and event names in this guide are conventions you can change.
Why do I need both collapse_id and a stable Android notification ID?
They solve different problems. collapse_id deduplicates messages on the OneSignal side and APNs/FCM side so the device only processes the latest one if updates arrive in a burst. The stable Android notification ID is what NotificationManager.notify(id, …) uses to replace the visible notification’s contents instead of posting a new one. You need both.
How often can I send updates?
Frequent updates are fine, but use a low importance channel (IMPORTANCE_LOW) with badges, vibration, and sound disabled. High importance with frequent updates will alert the user every time and is the most common reason support tickets get opened for this pattern.
What happens if the user kills the app or device reboots?
The Android notification persists on the lock screen and notification shade until your app cancels it or the user dismisses it. The service extension only runs when a push arrives, so any in-memory state (like progress) must be encoded inevent_updates, not held in app memory.
Can I do this on iOS too?
iOS has a managed equivalent: Live Activities. It uses ActivityKit and is built into OneSignal as a first-class feature with its own Start and Update APIs. Use Live Activities on iOS rather than this pattern.Related pages
Service extensions
Intercept and customize push notifications before display on Android and iOS.
Create message API
The API used to send the start, update, and end pushes for a Live Notification.
Live Activities (iOS)
The managed iOS equivalent built on ActivityKit.
Android notification categories
Configure channels so frequent Live Notification updates don’t alert the user.