Integration

This guide explains how to work with Live Activities using our SDK, from retrieving active activities to managing push tokens.

Get Active Live Activities

To retrieve a list of currently active Live Activities associated with the device:

LAIndigitall.getListEnabledLiveActivitiesWith { liveActivities in
    print("List of enabled live activities: \(liveActivities)")
} withError: { error in
    print("Error fetching live activities: \(error)")
}

[LAIndigitall getListEnabledLiveActivitiesWith:^(NSArray *liveActivities) {
    NSLog(@"List of enabled live activities: %@", liveActivities);
} withError:^(NSError *error) {
    NSLog(@"Error fetching live activities: %@", error.localizedDescription);
}];


Register Device Information

Send the list of Live Activities the device is subscribed to so the backend can associate them with the device for push updates:

LAIndigitall.subscribeToLiveActivities(
    withLiveActivities: arrayOfLiveActivitiesModel,
    withOnSuccess: { liveActivity in
        print("Successfully registered live activities with device")
    },
    withError: { error in
        print("Failed to register live activities: \(error)")
    }
)


[LAIndigitall subscribeToLiveActivitiesWithLiveActivities:arrayOfLiveActivitiesModel
                                              withOnSuccess:^(id liveActivity) {
    NSLog(@"Successfully registered live activities with device");
} withError:^(NSError *error) {
    NSLog(@"Failed to register live activities: %@", error.localizedDescription);
}];


Request and Register Push Token (PushToStart)

To receive push notifications for Live Activities, you need to listen for token updates and register them.
This example uses a custom TimerWidgetAttributes type:

Task {
    for await data in Activity<TimerWidgetAttributes>.pushToStartTokenUpdates {
        let token = data.map { String(format: "%02x", $0) }.joined()
        print("PushToStart Token: \(token)")

        // Send the token to your backend
        LAIndigitall.setPushToStartTokenUpdatesWithToken(
            token,
            withIosAttributesType: "TimerWidgetAttributes"
        ) {
            print("Token sent successfully")
        } withError: { error in
            print("Error sending PushToStart token: \(error)")
        }
    }
}

[LAIndigitall subscribeToLiveActivitiesWithLiveActivities:arrayOfLiveActivitiesModel
                                              withOnSuccess:^(id liveActivity) {
    NSLog(@"Successfully registered live activities with device");
} withError:^(NSError *error) {
    NSLog(@"Failed to register live activities: %@", error.localizedDescription);
}];

📘

This token should be sent to your backend notification server so it can target the correct Live Activity.


Monitor Token Updates (Advanced – Rarely Needed)

In most cases, tokens won't change during the activity's lifecycle. However, you can monitor token updates with:

Task {
    for await activityData in Activity<TimerWidgetAttributes>.activityUpdates {
        for await tokenData in activityData.pushTokenUpdates {
            let token = tokenData.map { String(format: "%02x", $0) }.joined()
            print("Updated token: \(token)")

            LAIndigitall.setPushTokenUpdatesWithToken(
                token,
                withLiveActivityExternalId: "YOUR_LIVE_ACTIVITY_EXTERNAL_ID"
            ) {
                print("Token update sent successfully")
            } withError: { error in
                print("Error updating token: \(error)")
            }
        }
    }
}

@objc public class LiveActivityHelper: NSObject {
    @objc public static func listenForPushTokenUpdates() {
        Task {
            for await activityData in Activity<TimerWidgetAttributes>.activityUpdates {
                for await tokenData in activityData.pushTokenUpdates {
                    let token = tokenData.map { String(format: "%02x", $0) }.joined()
                    print("Updated token: \(token)")

                    LAIndigitall.setPushTokenUpdatesWithToken(
                        token,
                        withLiveActivityExternalId: "YOUR_LIVE_ACTIVITY_EXTERNAL_ID"
                    ) {
                        print("Token update sent successfully")
                    } withError: { error in
                        print("Error updating token: \(error)")
                    }
                }
            }
        }
    }
}

📘

Typically, this isn’t necessary if you’re sending push notifications via a known channelId, since tokens are expected to remain stable.


Live Activities (Legacy Push Integration)

Starting with iOS 16.1, Apple introduced the recommended approach to implement Live Activities using ActivityKit (as explained in the previous section). This provides a native API for creating, updating, and ending Live Activities directly from your app or via push notifications.

However, prior to ActivityKit, it was possible to update Live Activities through a custom push model that carried a specific payload with the information to be refreshed. This method can still be relevant for legacy implementations or backward compatibility.

Legacy Push-Based Updates

In this model, each push notification includes a special key called contentState in its payload. This JSON object contains the data needed to manually update the Live Activity.

action = {
  destroy = 1;
  type = <ACTION_TYPE>;
};
appKey = "<YOUR_APPKEY>";
title = "<PUSH_TITLE>";
body = "<PUSH_BODY>";
campaignId = <ID_CAMPAIGN>;
----------
contentState = {
  driverName = "Anne Johnson";
  estimatedDeliveryTime = 1659416400;
};
---------
id = <ID>;
image = "<PUSH_IMAGE>";
journeyStateId = <JOURNEY_ID>;
layout = basic;
sendingId = <SENDING_ID>;
timezone = "Europe/Madrid";

As you can see, the push object contains a contentState key with the JSON used to update the Live Activity.
Additionally, the same information appears inside the userInfo of the remote notification object, but under the key content-state:

alert = "<your push text>";
badge = 0;
"content-available" = 1;
"content-state" = {
  driverName = "Anne Johnson";
  estimatedDeliveryTime = 1659416200;
  update = 1;
};
"mutable-content" = 1;
sound = default;

Notes

  • This approach is considered legacy and should only be used when supporting environments that do not leverage ActivityKit.
  • For new projects targeting iOS 16.1 and above, you should follow the ActivityKit-based integration described in the previous section.
  • Custom payload updates require coordination between your backend and the client app to ensure the content-state matches the expected Live Activity schema.