Live Activities on Android!

Helder Pinhal
Helder Pinhal
Jan 20 2023
Posted in Engineering & Technology

Yes, that's possible!

Live Activities on Android!

Our last article about Live Activities focused on building an order tracker for iOS. This time around, we're doing the same for Android. Of course, Android has no such thing as a Live Activity, but we can emulate this!

Where we're coming from

When Apple introduced Live Activities with iOS 16.1, it brought a fresh approach to providing meaningful at-a-glance information to users. While teams are investigating and developing creative ways to leverage this functionality, we're committed to providing an equivalent for Android.

The principle behind Live Activities is reasonably straightforward. You display some UI on the Lock Screen, and the OS provides automatic updates through remote notifications.

On Android, you can build any kind of UI. Whether you go for a Widget on the user's home screen or a Notification on the notification drawer and the lock screen, that's up to you. Consider your options and what's best for your particular use case.

The Notificare toolset

To assist you in developing this mechanism, we provide a way for you to register the ongoing activities and receive remote updates for them. The complete public API is quite simple, and we can narrow it down to the following:

// 1. Register an activity
Notificare.push().registerLiveActivity(
    activityId = "order-status",
    topics = listOf("optional", "topics")
)

// 2. End an ongoing activity
Notificare.push().endLiveActivity(
    activityId = "order-status",
)

// 3. Intent receiver for remote updates
class PushReceiver : NotificarePushIntentReceiver() {

    override fun onLiveActivityUpdate(context: Context, update: NotificareLiveActivityUpdate) {
        // Update the UI with the latest data.
    }

    override fun onTokenChanged(context: Context, token: String) {
        // Re-register any ongoing activities.
    }

}

Building the UI

As we mentioned, the UI part is up to your imagination, but bear in mind that the OS has certain limitations. We consider that, the most meaningful way of displaying the information, is by presenting a custom notification on the lock screen.

In this case, the view height is the constraint with the most impact on what we can build. For more information on this subject, check the Android Developers' documentation.

Live Activity UI showcase

Before we can place a notification on the lock screen, we must register a channel. The documentation is unambiguous, but, simply put, the following snippet illustrates how you can do it.

val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

val channel = NotificationChannel(
    "live-activities",
    context.getString(R.string.notification_channel_live_activities_title),
    NotificationManager.IMPORTANCE_DEFAULT
)

channel.description = context.getString(R.string.notification_channel_live_activities_description)

notificationManager.createNotificationChannel(channel)

The next step is building the notification itself. You can configure several options through the NotificationCompat.Builder to create the perfect notification for your use case. You can even provide custom layouts based on RemoteViews for a truly tailored user experience.

val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

val notification = NotificationCompat.Builder(context, "live-activities")
    .setSmallIcon(R.drawable.ic_stat_notification)
    .setStyle(NotificationCompat.DecoratedCustomViewStyle())
    .setCustomContentView(createStandardLayout())
    .setCustomBigContentView(createExpandedLayout())
    .build()

notificationManager.notify(
    "order-status",
    notificationCounter.incrementAndGet(),
    notification
)

Sending remote updates

The Notificare REST API exposes an endpoint for sending content updates to a specific activity identifier in combination with any topics you provide. Below is an example of such a request:

curl --location --request POST 'https://push.notifica.re/live-activity/message' \
--header 'Authorization: Basic ...' \
--header 'Content-Type: application/json' \
--data-raw '{
    "activity": "order-status",
    "content": {
        "state": "shipped"
    }
}'

Alternatively, you can use our dashboard to send remote updates to a specific device.

Live Activity remote updates composer

Handling the remote updates

As mentioned in the toolset section, you must tap into the NotificarePushIntentReceiver to receive and process remote updates. By overriding the onLiveActivityUpdate method, you receive all the information associated with the update — notification title, message, content state, etc.

class PushReceiver : NotificarePushIntentReceiver() {

    override fun onLiveActivityUpdate(context: Context, update: NotificareLiveActivityUpdate) {
        // Update the UI with the latest data.
    }

}

Furthermore, you must re-register any ongoing activities when the push token changes. Otherwise, those activities get lost, and you won't receive any other updates.

class PushReceiver : NotificarePushIntentReceiver() {

    override fun onTokenChanged(context: Context, token: String) {
        // Re-register any ongoing activities.
    }

}

Conclusion

Although we didn't cover all the details of building and binding the custom layouts for the notification, we have implemented this example in the Notificare Go app, whose source code is available on GitHub.

We look forward to what you can come up with using the Live Activities mechanism!

As always, we hope you liked this article, and if you have anything to add, we are available via our Support Channel.

Keep up-to-date with the latest news