# Live Activities

[Live Activities](https://developer.apple.com/design/human-interface-guidelines/live-activities), introduced by Apple in October 2022, allow app developers to display dynamic, live-updating, content via widgets on device lock screens and in the Dynamic Island (for capable devices).

The PushSDK helps you streamline Live Activity registration and updates by allowing developers to register and manage the short-lived push tokens associated with your Live Activities which can then be updated via our server API.

## Prerequisites

Before you can integrate Live Activities with the SDK the following requirements must be met:

* An iOS Send Integration configured with a .p8 key.
* An iOS app (Live Activities are only available for iOS and iPadOS).
* A device or emulator with iOS 16.1 or newer installed
* PushSDK release supporting Live Activities (See version support chart below)

## Step 1: iOS SDK Setup

For applications **not** already using the PushSDK please see our Native App Push setup guide for [Apple / iOS](https://documentation.pushly.com/integration/implementation-steps/apple-ios).

For applications already using the PushSDK you might need to upgrade to a later version that includes Live Activity support. Use the following tables to determine if you need to upgrade your installation.

<table><thead><tr><th width="190">SDK</th><th>Earliest Version with Live Activities</th></tr></thead><tbody><tr><td><a href="">Swift</a></td><td>1.2.0+</td></tr><tr><td><a href="../../react-native">React Native SDK</a></td><td>1.1.0+</td></tr><tr><td><a href="../../flutter">Flutter SDK</a></td><td>1.1.0+</td></tr></tbody></table>

<table><thead><tr><th width="190">SDK</th><th>Earliest Version with Push-to-Start Live Activities Support</th></tr></thead><tbody><tr><td><a href="">Swift</a></td><td>1.3.9+ (Requires iOS 17.2+)</td></tr></tbody></table>

{% tabs %}
{% tab title="Swift Package Manager" %}
Within the Xcode project navigator panel locate `Package Dependencies`. Locate and right-click on `Pushly` and select `Update Package`.

<figure><img src="https://810756845-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Lry9Z27iWOZyQEGAgY7%2Fuploads%2F9faSouNBrEPdCAgMZh4r%2Fimage.png?alt=media&#x26;token=aca77332-b0b7-49d8-9d8a-1c7606950e3f" alt=""><figcaption></figcaption></figure>

If after an update the package is not >= version 1.2.0 select your Project in the project navigator, select your project, and then navigate to `Package Dependencies`. Select `Pushly` and ensure the `Dependency Rule` is set to `Up to Next Major Version` with 1.0.0, or greater, as the target.

<figure><img src="https://810756845-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Lry9Z27iWOZyQEGAgY7%2Fuploads%2FGsUeegTRGVruLueDjKzv%2Fimage.png?alt=media&#x26;token=78a89577-2661-4c17-812f-442a324ac9cc" alt=""><figcaption></figcaption></figure>
{% endtab %}

{% tab title="CocoaPods" %}

* Ensure you are targeting `'Pushly', '>= 1.0', '< 2.0'` in your Podfile.
* Run `pod update Pushly`
* Confirm the latest version has been downloaded by looking in your Podfile.lock.
  {% endtab %}
  {% endtabs %}

## Step 2: Add Live Activity Support to Info.plist

Applications implementing Live Activities must set the `Supports Live Activities` key to `YES` in their primary target info.plist.

<figure><img src="https://810756845-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Lry9Z27iWOZyQEGAgY7%2Fuploads%2FLxAihjwTK0unScTevEoi%2Fimage.png?alt=media&#x26;token=81a7906f-bbb8-4073-9b01-bfccf870f0b3" alt=""><figcaption></figcaption></figure>

If one of your use cases utilizes frequent updates you should also consider setting `Supports Live Activities Frequent Updates` to `YES` in the info.plist.

## Step 3: Add a Live Activity Widget Extension

Within your app's Xcode project select `File > New > Target`. Select `Widget Extension` inside the iOS templates tab and click `Next`.

<figure><img src="https://810756845-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Lry9Z27iWOZyQEGAgY7%2Fuploads%2FhI067o4x4UVy5PwHqMn6%2Fimage.png?alt=media&#x26;token=9c683a4c-9a4b-4ee9-9ccd-e0181fc1df68" alt=""><figcaption></figcaption></figure>

Enter your desired Live Activity widget name for the `Product Name` and any other configuration details for your widget extension, making sure that `Include Live Activity` is selected, and then click `Finish`. On the subsequent dialog click `Cancel` to continue developing without activating the new widget extension as the current target.

<figure><img src="https://810756845-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Lry9Z27iWOZyQEGAgY7%2Fuploads%2FmXxVVyXfwYnspkWUYVlu%2Fimage.png?alt=media&#x26;token=8e472508-f834-42b9-abe9-6e36087b950f" alt=""><figcaption></figcaption></figure>

## Step 4: Setup a Live Activity

### User Interface

Before starting your new Live Activity we recommend reading through Apple's guide to [Displaying live data with Live Activities](https://developer.apple.com/documentation/activitykit/displaying-live-data-with-live-activities).

### Starting Your Live Activity

Once your Live Activity has been designed and setup you are now ready to start and register it via the PushSDK.

To aid in tracking and updating multiple Live Activity instances across millions of devices via a single API call we use an activity ID. Activity IDs are string values provided by you, the developer.

In some scenarios, such as sporting events, you may want to send a single update to all devices registered to a single event. In these cases you should use a unique ID that identifies the event rather than an ID per individual user.

In other scenarios, such as meal orders, Live Activities are user specific. In these cases you should use a unique ID that identifies the individual user.

## Step 5: Starting a Live Activity

### Starting from Within the App

The following code snippet requests to start a Live Activity using the `MyLiveActivityAttributes` struct with an `eventId` attribute that will uniquely identify this instance of the activity and then registers the activity with the PushSDK to observe and collect any token updates.

{% tabs %}
{% tab title="Swift" %}
{% code fullWidth="false" %}

```swift
import UIKit
import ActivityKit
import Pushly

class ViewController: UIViewController {
    public func startLiveActivity() {
        if #available(iOS 16.1, *) {
            let attributes = MyLiveActivityAttributes(eventId: "my_activity_id")
            let contentState = MyLiveActivityAttributes.ContentState(
                home_team: "Chiefs",
                home_team_score: 0,
                away_team: "Chargers",
                away_team_score: 0)
            let activityContent = ActivityContent(
                state: contentState,
                staleDate: nil)
        
            do {
                let activity = try Activity<MyLiveActivityAttributes>.request(
                    attributes: attributes,
                    contentState: activityContent,
                    pushType: .token)
            
                // Register the activity with Pushly using the eventId attribute
                PushSDK.LiveActivities.register(
                    activity,
                    withId: activity.attributes.eventId)
            } catch (let error) {
                print(error.localizedDescription)
            }
        }
    }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

### Registering an Activity Type for Starting via Push

The following code snippet will start observing an Activity type and register and push-to-start tokens as well as ensure any started or already running activities are registered for push token collection as well. We will once again be using the `MyLiveActivityAttributes` class with an `eventId` attribute that will uniquely identify this instance of the activity.

{% tabs %}
{% tab title="Swift" %}
{% code fullWidth="false" %}

```swift
import UIKit
import ActivityKit
import Pushly

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        ...

        if #available(iOS 16.1, *) {
            // Register the activity type with Pushly
            PushSDK.LiveActivities.register(Activity<MyLiveActivityAttributes>.self) { activity in
                // Register the specific activity with Pushly
                PushSDK.LiveActivities.register(activity, withId: activity.attributes.eventId)
            }
        }
    }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

### Sending the Start Event

Once you have registered the activity type with the PushSDK you can use our [Live Activity API documentation](https://developers.pushly.com/reference/management-update-live-activity) to send a start event by specifying the corresponding attributes struct name in the `activity.ios.data.attributes_type` property and passing the associated unique activity identifier in both the `activity.ios.data.attributes` object and the request path - in this scenario we used the `eventId` attribute set to `my_activity_id` which we can then use in subsequent update events.

{% tabs %}
{% tab title="Example Start Event" %}
{% code fullWidth="false" %}

```json
POST Request to:
https://api.pushly.com/domains/{domain_id}/live-activities/my_activity_id
{
    "name": "my-request-event-name",
    "event": "start",
    "activity": {
        "ios": {
            "data": {
                "relevance_score": 100,
                "priority": 10,
                "attributes_type": "MyLiveActivityAttributes",
                "attributes": {
                    "eventId": "my_activity_id"
                },
                "content_state": {
                    "home_team": "Chiefs",
                    "home_team_score": 0,
                    "away_team": "Chargers",
                    "away_team_score": 0
                },
                "notification": {
                    "title": "A Live Event Has Started",
                    "body": "Stay tuned for more updates!"
                }
            }
        }
    }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

### PNActivityAttributes Protocol

The PushSDK also provides a simple protocol, `PNActivityAttributes`, that requires an attribute of `pnActivityId` which will be used to uniquely identify the activity. When using this protocol the method signatures are simplified as the ID is auto collected for token registrations in activities started both locally and via push.

{% tabs %}
{% tab title="Swift" %}
{% code fullWidth="false" %}

```swift
import UIKit
import ActivityKit
import Pushly

struct MyLiveActivityAttributes: PNActivityAttributes {
    public struct ContentState: Codable, Hashable {
        var home_team: String
        var home_team_score: Int
        var away_team: String
        var away_team_score: Int
    }

    var pnActivityId: String
}

class ViewController: UIViewController {
    public func startLiveActivity() {
        if #available(iOS 16.1, *) {
            ...

            // Register the activity with Pushly
            PushSDK.LiveActivities.register(activity)
        }
    }
}

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        ...

        if #available(iOS 16.1, *) {
            // Register the activity type with Pushly
            PushSDK.LiveActivities.register(Activity<MyLiveActivityAttributes>.self)
        }
    }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

## Step 5: Send Your Live Activity an Update

Once the short-lived push tokens have been registered with an activity ID you can use our [Live Activity API documentation](https://documentation.pushly-dev.com/#live-activities) to send updates to all registered Live Activities via a single request.

{% tabs %}
{% tab title="Example Update Event" %}
{% code fullWidth="false" %}

```json
POST Request to:
https://api.pushly.com/domains/{domain_id}/live-activities/my_activity_id
{
    "name": "my-request-event-name",
    "event": "update",
    "activity": {
        "ios": {
            "data": {
                "relevance_score": 100,
                "priority": 10,
                "content_state": {
                    "home_team": "Chiefs",
                    "home_team_score": 7,
                    "away_team": "Chargers",
                    "away_team_score": 0
                }
            }
        }
    }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

For more information on [Starting and updating Live Activities with ActivityKit push notifications](https://developer.apple.com/documentation/activitykit/displaying-live-data-with-live-activities) see Apple's developer documentation.
