Skip to main content
Follow this guide to add Live Activities to an app built with a cross-platform framework such as React Native, Flutter, Unity, Cordova, Capacitor, or .NET MAUI. Live Activities normally require ActivityKit code written in Swift. The OneSignal SDK’s setupDefault method manages the Live Activity lifecycle for you against a built-in DefaultLiveActivityAttributes type, so the only native code you write is the widget layout.
Live Activities are an iOS feature. They are not available on Android, on Huawei devices, or on the web. For a comparable Android experience, see Android Live Updates.

Requirements

  • Your framework’s OneSignal SDK, on a release that bundles OneSignal iOS SDK 5.2.0 or higher. That version added setupDefault and push-to-start (for example, react-native-onesignal 5.2.0). Follow Mobile SDK setup first.
  • OneSignal iOS SDK 5.2.15 or higher for click tracking and confirmed receipt. See Live Activities analytics.
  • iOS 16.1+ or iPadOS 17+ to start a Live Activity in-app with startDefault.
  • iOS 17.2+ to start a Live Activity remotely with the Start Live Activity API. Apple added push-to-start in iOS 17.2, so devices below it can only start activities in-app.
  • A .p8 APNs key. Apple does not support p12 certificates with Live Activities.
  • Xcode 14 or higher.

Setup

1. Set up the OneSignal SDK

Set up the OneSignal SDK for your framework and initialize it in your app before continuing.

React Native

Bare React Native apps.

Expo

Managed Expo apps with EAS Build.

Flutter

Flutter apps using Dart.

Unity

Unity apps for iOS, Android, Amazon, and Huawei.

.NET MAUI

.NET MAUI apps for iOS and Android.

Cordova

Cordova and Ionic Cordova hybrid apps.

Capacitor

Capacitor and Ionic Capacitor hybrid apps.

2. Call setupDefault on app launch

setupDefault tells the OneSignal SDK to manage the Live Activity lifecycle for its built-in DefaultLiveActivityAttributes type. Call it once per app launch, right after you initialize the OneSignal SDK. The SDK then registers the device’s push-to-start token, which is what lets you start, update, and end the activity with the Start Live Activity and Update Live Activity APIs. To start an activity from inside your app instead of remotely, call startDefault with an activityId, static attributes, and initial content. Your app must be in the foreground.
Live Activities are iOS-only. The Flutter SDK checks the platform internally, so setupDefault does nothing on Android. In React Native, guard the call as shown above.
setupDefault listens for both push-to-start and push-to-update tokens by default. In React Native and Flutter, pass setup options to enable only one of them. For example, if you always start activities from inside the app, you can skip push-to-start registration.

3. Create the Live Activity widget extension

1

Update your Info.plist

In Xcode, open your main target’s Info.plist, add the key Supports Live Activities as Boolean, and set it to YES. The raw key name is NSSupportsLiveActivities.
Xcode Info.plist editor showing Supports Live Activities set to YES

Add Supports Live Activities key to Info.plist and set its value to Boolean YES.

If your use case sends frequent high-priority updates, also add NSSupportsLiveActivitiesFrequentUpdates as a Boolean set to YES (iOS 16.2+). Apple throttles apps that send priority: 10 updates too often, and this key raises that budget. See Update frequency and throttling.
2

Create a Widget Extension

In Xcode, go to File > New > Target… > Widget Extension.
Xcode new target dialog with Widget Extension selected

Add a new Widget Extension target for your app in Xcode.

Select and press Next.Configure the Widget Extension by providing a name (example: OneSignalWidget) and ensure Include Live Activity is selected. Then click Finish.
Widget Extension configuration with Include Live Activity checkbox selected

Widget Extension options for a Live Activity.

Click Don’t Activate if prompted to activate the scheme.
Xcode scheme activation dialog for the Widget Extension

Scheme activation prompt: select Don't Activate.

3

Add the OneSignalLiveActivities subspec to your Podfile (optional)

This step is only required if your app uses a Live Activity widget extension with CocoaPods.Find the name of your widget extension target in your project’s Targets list. The example below uses OneSignalWidgetExtension.
Xcode Targets list showing the widget extension target name

Find the name of your widget extension target.

Open your Podfile and add only the OneSignalXCFramework/OneSignalLiveActivities subspec. Replace OneSignalWidgetExtension with the name of your widget extension target. Do not use the aggregate pod 'OneSignalXCFramework' declaration, which resolves OneSignalComplete and includes the location module.
Podfile
Close Xcode and run pod repo update && pod install to install the OneSignalLiveActivities pod.

4. Build the widget layout

In Xcode, open the WidgetExtensionLiveActivity.swift file that the Widget Extension template generated. Open the Inspector panel on the right side of the screen. Within Target Membership, click the + button and select your main app target. In Flutter this target is named Runner. In other frameworks it matches your app name.
Xcode Target Membership section with the main app target selected

Allow main target membership for the Live Activity file.

Replace the contents of the file with the layout below. Change the displayed values to whatever your activity needs. You do not define an ActivityAttributes struct yourself, because setupDefault supplies DefaultLiveActivityAttributes, which exposes your payload as context.attributes.data and context.state.data.
Swift
Keep the @available(iOS 16.2, *) annotation from the template. A widget gated this way does not render on iOS 16.1, so treat 16.2 as the practical floor for this setup. Set widgetURL to your own deep link, since the example points at apple.com.

Test the Live Activity

Build and run your app on a device or simulator running iOS 17.2 or higher, then send a start request. Two fields carry your widget’s data, and both mirror the structure your Swift layout reads:
  • event_attributes holds static data. You set it in the start request and it stays fixed for the life of the activity. Your widget reads it as context.attributes.data.
  • event_updates holds dynamic data you change on later updates. Your widget reads it as context.state.data. Nest values exactly as your layout expects, so the message dictionary below arrives as context.state.data["message"]["en"].
Before you send, replace these values:
  • YOUR_APP_ID with your OneSignal App ID and YOUR_REST_API_KEY with your API key.
  • activity_id with an identifier of your choice. A new value starts a new Live Activity, and reusing a value updates the activity already using it. See Choose an activity ID.
Leave DefaultLiveActivityAttributes in the URL path as-is. That is the type setupDefault registers, and the path segment is case-sensitive. For every available field, see the Start Live Activity API reference.
curl

Low-level methods

Use these methods only if you want to define your own ActivityAttributes struct in Swift and manage the push-to-start token yourself, instead of letting setupDefault own the lifecycle. You generate the token with ActivityKit in your iOS code, then hand it to OneSignal. For the native side, see the alternative setup notes in the iOS SDK. activityType must be the name of the struct conforming to ActivityAttributes that starts the activity, and it becomes the last segment of the API URL path.

FAQ

Why does my Live Activity never start from a push?

The most common cause is a device below iOS 17.2. Apple added push-to-start in iOS 17.2, so older devices can only start activities in-app with startDefault. If the device qualifies, check that setupDefault runs on every app launch after OneSignal.initialize, that the activity type in your URL path is exactly DefaultLiveActivityAttributes, and that your app uses a .p8 APNs key rather than a p12 certificate.

Do I need to define my own ActivityAttributes struct?

No. setupDefault registers the SDK’s DefaultLiveActivityAttributes type, which is why the widget reads values through context.attributes.data and context.state.data instead of named properties. Define your own struct only if you use the low-level methods.

Why is my widget showing default or empty values?

Your payload nesting does not match what the layout reads. event_attributes maps to context.attributes.data and event_updates maps to context.state.data, so a value the widget reads as context.state.data["message"]["en"] must arrive as event_updates.data.message.en. Values that miss the expected path fall back to the defaults in your Swift code.

Can I use Live Activities on Android?

No. Live Activities are an iOS-only ActivityKit feature, so the calls on this page do nothing on Android. For a comparable Android experience built on push notifications, see Android Live Updates.

Does the widget need its own OneSignal pod?

Only if your app uses CocoaPods. In that case add the OneSignalXCFramework/OneSignalLiveActivities subspec to your widget extension target, as shown in step 3. Do not add the aggregate OneSignalXCFramework pod to the widget target, because it resolves OneSignalComplete and pulls in the location module.

Live Activities

When to use Live Activities, targeting, update frequency, and throttling limits.

Live Activities developer setup

The native iOS (Swift) setup path, including custom ActivityAttributes.

Start Live Activity API

Every field accepted by the push-to-start request.

Live Activities analytics

Delivery, confirmed receipt, click, and unsubscribe metrics for each send.