# Live Activities

Android Live Activity notifications provides a similar feature-set and experience to [iOS Live Activities](https://documentation.pushly.com/integration/implementation-steps/android/sdk-kotlin-java/live-activities) on the Android platform allowing for real-time updated content via push notifications.

The PushSDK helps you streamline Live Activity registration and updates by allowing developers to register and manage the Live Activity handlers 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 Android Send Integration configured with a Firebase Sender ID and Server API Key or Service Account.
* An Android app.
* A device or emulator running API 19+ (Android 4.4) with Google Play Store Services installed.
* PushSDK release supporting Live Activities (See version support chart below).

## Step 1: Android SDK Setup

For applications **not** already using the PushSDK please see our Native App Push setup guide for [Android](#step-1-android-sdk-setup).

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="">Kotlin / Java</a></td><td>1.3.0+</td></tr></tbody></table>

{% tabs %}
{% tab title="app/build.gradle" %}

```gradle
dependencies {
    ...
    implementation 'com.pushly.android:pushsdk:[1.3, 2.0['
}
```

{% endtab %}
{% endtabs %}

## Step 2: Creating a Handler for Live Activity Updates

To handle and display updates you will need to implement the `PNLiveActivityHandler` class. The handler requires a `name` that will uniquely identifier this type of activity and start via push. An optional notification `channelId` can also be specified to group Live Activity notifications into their own channel. When no custom channel ID is specified the PushSDK will use a default channel.

An `onUpdate` method must be implemented and is responsible for handling any Live Activity event as it is received (start, update, or end). Use this method to customize how updates are displayed to users.

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
class MyActivityHandler : PNLiveActivityHandler(
    name = "game_updates",
    channelId = "sports_channel"
) {
    override fun onUpdate(context: Context, contentState: ContentState): PNLiveActivityUpdateResult {
        // Create your notification builder
        val builder = Notification.Builder(context, channelId)
            .setSmallIcon(R.drawable.ic_notification)
            .setContentTitle("Game Update")
            .setContentText("${contentState.getString("home_team")} vs ${contentState.getString("away_team")}")
        
        // Return builder with the result
        return PNLiveActivityUpdateResult.Ok(builder)
    }
}
```

{% endtab %}

{% tab title="Java" %}

```java
class MyActivityHandler extends PNLiveActivityHandler {
    public MyActivityHandler() {
        super("game_updates", "sports_channel");
    }

    @Override
    public @NonNull PNLiveActivityUpdateResult onUpdate(@NonNull Context context, @NonNull ContentState contentState) {
        String homeTeam = contentState.getStringOrDefault("home_team", "Home Team");
        String awayTeam = contentState.getStringOrDefault("away_team", "Away Team");

        // Create your notification builder
        NotificationCompat.Builder builder = new NotificationCompat.Builder(context, this.getChannelId())
                .setSmallIcon(R.drawable.ic_notification)
                .setContentTitle("Game Update")
                .setContentText(String.format("%s, vs %s", homeTeam, awayTeam));

        // Return builder with the result
        return new PNLiveActivityUpdateResult.Ok(builder);
    }
}
```

{% endtab %}
{% endtabs %}

### Registering the Handler

Once you have implemented your handler you will need to register it with the PushSDK. The following code snippet shows how to register the handler:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
class MainApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        
        // ... PushSDK configuration code

        PushSDK.LiveActivities.register(MyActivityHandler())
    }
}
```

{% endtab %}

{% tab title="Java" %}

```java
class MainApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        
        // ... PushSDK configuration code

        PushSDK.LiveActivities.register(new MyActivityHandler());
    }
}
```

{% endtab %}
{% endtabs %}

## Step 3: Starting a Live Activity

### Starting from Within the App

The following code snippet requests to start a Live Activity using a unique `activityId` , a `handler` name that corresponds to a previously register handler class, and the initial `contentState` of the activity. In this scenario we will use the `PNLiveActivityHandler` class registered with the name: `game_updates`.

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

```kotlin
class MainActivity : AppCompatActivity() {
    public fun startLiveActivity() {
        PushSDK.LiveActivities.start(
            activityId = "my_activity_id",
            handler = "game_updates", // Must match registered handler name
            contentState = contentStateOf(
                "home_team" to "Chiefs",
                "home_team_score" to 0,
                "away_team" to "Chargers",
                "away_team_score" to 0
            )
        )
    }
}
```

{% endcode %}
{% endtab %}

{% tab title="Java" %}

```java
class MainActivity extends AppCompatActivity {
    public void startLiveActivity() {
        PushSDK.LiveActivities.start(
            "my_activity_id",
            "game_updates", // Must match registered handler name
            ContentState.builder()
                .put("home_team", "Chiefs")
                .put("home_team_score", 0)
                .put("away_team", "Chargers")
                .put("away_team_score", 0)
                .build()
        );
    }
}
```

{% endtab %}
{% endtabs %}

#### Content State

`ContentState` is used to pass data to Live Activities. You can create your state using convenience method `contentStateOf()`:

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

```kotlin
val state = contentStateOf(
    "key1" to "value1",
    "key2" to 42,
    "key3" to null
)
```

{% endcode %}
{% endtab %}

{% tab title="Java" %}

```java
ContentState state = ContentState.builder()
    .put("key1", "value1")
    .put("key2", 1)
    .put("key3", null)
    .build();
```

{% endtab %}
{% endtabs %}

`ContentState` supports the following value types: String, Int, Long, Float, Double, Boolean, null.

### Starting via Push

Once you have registered the handler 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 handler name name in the `activity.android.data.handler_name` property and passing the associated unique activity identifier in the request path - in this scenario we used `my_activity_id` which we can then use in subsequent update events.

{% tabs %}
{% tab title="Example Start Request" %}

```json
POST Request to:
https://api.pushly.com/domains/{domain_id}/live-activities/my_activity_id
{
    "name": "my-request-event-name",
    "event": "start",
    "activity": {
        "android": {
            "data": {
                "handler_name": "game_updates",
                "content_state": {
                    "home_team": "Chiefs",
                    "home_team_score": 0,
                    "away_team": "Chargers",
                    "away_team_score": 0
                },
                "notification": {
                    "title": "The Game Has Begun",
                    "body": "Stay tuned for more updates!"
                }
            }
        }
    }
}
```

{% endtab %}
{% endtabs %}

## Step 4: Send Your Live Activity an Update

Once the Live Activity has been started, either locally or via push, you can use our [Live Activity API documentation](https://developers.pushly.com/reference/management-update-live-activity) 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": {
        "android": {
            "data": {
                "content_state": {
                    "home_team": "Chiefs",
                    "home_team_score": 7,
                    "away_team": "Chargers",
                    "away_team_score": 0
                }
            }
        }
    }
}
```

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

## Step 5: Removing Live Activities

In a similar fashion to how iOS Live Activities work Android Live Activity notifications will automatically end and self-cleanup after 12 hours from the time they are started. However, there might be situations where you want to cleanup the activity before that time limit has occurred. In those scenarios you can remove a single activity or remove all active activities with the following methods:

### Remove a Specific Activity

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

```kotlin
PushSDK.LiveActivities.remove(activityId = "my_activity_id")
```

{% endcode %}
{% endtab %}

{% tab title="Java" %}

```java
PushSDK.LiveActivities.remove("my_activity_id");
```

{% endtab %}
{% endtabs %}

### Remove All Activities

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

```kotlin
PushSDK.LiveActivities.removeAll()
```

{% endcode %}
{% endtab %}

{% tab title="Java" %}

```java
PushSDK.LiveActivities.removeAll();
```

{% endtab %}
{% endtabs %}

## Best Practices

1. Always register handlers in your application's `onCreate` method for proper initialization.
2. Return a properly configured `Notification.Builder` in the handler's `onUpdate` method.
3. Use consistent activity IDs to properly track and update specific activities.
4. Handle all possible states in your handler's `onUpdate` method.
5. Implement proper error handling in your handler.
6. Use meaningful handler names that reflect their purpose.
7. Clean up activities when they're no longer needed using and `end` event or manually calling one of the remove methods.
