Live Updates for the Android SDK
Integrate Live Updates into your Android app to display real-time updates in notifications, widgets, or within your app. AXP

For information about Live Updates, including overview, use cases, and how to send Live Updates via the Push API, see Android Live Updates.
Installation
Include the Live Updates module in your app’s dependencies:
App build.gradle
dependencies {
val airshipVersion = "androidSdkVersion"
implementation("com.urbanairship.android:urbanairship-live-update:$airshipVersion")
}
dependencies {
def airshipVersion = "androidSdkVersion"
implementation "com.urbanairship.android:urbanairship-live-update:$airshipVersion"
}
Creating a handler
The Airship SDK supports two types of Live Update handlers:
NotificationLiveUpdateHandler— Displays a notification with a custom layout, with content updated by the Live Update.CustomLiveUpdateHandler— Receives Live Update events and provides flexibility to display content using a custom implementation. This can be used to power home screen widgets, views embedded in the app, and more.
Each handler type has two different interfaces that may be implemented, to support suspending or callback-based code:
SuspendLiveUpdateNotificationHandlerCallbackLiveUpdateNotificationHandlerSuspendLiveUpdateCustomHandlerCallbackLiveUpdateCustomHandler
The following SampleLiveUpdateHandler reads content from the Live Update payload and displays scores for a sports game in a custom notification layout, using RemoteViews:
Creating a handler
class SampleLiveUpdateHandler : SuspendLiveUpdateNotificationHandler() {
override suspend fun onUpdate(
context: Context,
event: LiveUpdateEvent,
update: LiveUpdate
): LiveUpdateResult<NotificationCompat.Builder> {
// Read content_state fields from the Live Update payload
val teamOneScore = update.content.opt("team_one_score").getInt(0).toString()
val teamTwoScore = update.content.opt("team_two_score").getInt(0).toString()
val statusUpdate = update.content.opt("status_update").optString()
// Expanded notification layout
val bigLayout = RemoteViews(context.packageName, R.layout.sports_big).apply {
setTextViewText(R.id.teamOneScore, teamOneScore)
setTextViewText(R.id.teamTwoScore, teamTwoScore)
setTextViewText(R.id.statusUpdate, statusUpdate)
}
// Collapsed notification layout
val smallLayout = RemoteViews(context.packageName, R.layout.sports_small).apply {
setTextViewText(R.id.teamOneScore, teamOneScore)
setTextViewText(R.id.teamTwoScore, teamTwoScore)
}
// Create the notification builder
val builder = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
.setSmallIcon(R.drawable.ic_notification)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setCategory(NotificationCompat.CATEGORY_EVENT)
.setStyle(NotificationCompat.DecoratedCustomViewStyle())
.setCustomContentView(smallLayout)
.setCustomBigContentView(bigLayout)
// Return 'ok' with the notification builder.
// The Airship SDK will handle posting the notification.
// Returning LiveUpdateResult.cancel() will end the Live Update and dismiss the notification.
return LiveUpdateResult.ok(builder)
}
companion object {
private const val NOTIFICATION_CHANNEL_ID = "sports"
}
}public class SampleLiveUpdateHandler extends CallbackLiveUpdateNotificationHandler() {
@Override
public void onUpdate(
Context context,
LiveUpdateEvent event,
LiveUpdate update,
LiveUpdateResultCallback<NotificationCompat.Builder> callback
) {
// Read content_state fields from the Live Update payload
int teamOneScore = update.getContent().optInt("team_one_score", 0);
int teamTwoScore = update.getContent().optInt("team_two_score", 0);
String statusUpdate = update.getContent().optString("status_update");
// Expanded notification layout
RemoteViews bigLayout = new RemoteViews(context.getPackageName(), R.layout.sports_big);
bigLayout.setTextViewText(R.id.teamOneScore, String.valueOf(teamOneScore));
bigLayout.setTextViewText(R.id.teamTwoScore, String.valueOf(teamTwoScore));
bigLayout.setTextViewText(R.id.statusUpdate, statusUpdate);
// Collapsed notification layout
RemoteViews smallLayout = new RemoteViews(context.getPackageName(), R.layout.sports_small);
smallLayout.setTextViewText(R.id.teamOneScore, String.valueOf(teamOneScore));
smallLayout.setTextViewText(R.id.teamTwoScore, String.valueOf(teamTwoScore));
// Create the notification builder
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
.setSmallIcon(R.drawable.ic_notification)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setCategory(NotificationCompat.CATEGORY_EVENT)
.setStyle(new NotificationCompat.DecoratedCustomViewStyle())
.setCustomContentView(smallLayout)
.setCustomBigContentView(bigLayout);
// Return 'ok' with the notification builder.
// The Airship SDK will handle posting the notification.
// Returning LiveUpdateResult.cancel() will end the Live Update and dismiss the notification.
callback.onResult(LiveUpdateResult.ok(builder));
}
private static final String NOTIFICATION_CHANNEL_ID = "sports";
}Registering a handler
Handlers must be registered with LiveUpdateManager in order to receive Live Update events. This should be done once after takeOff.
In your Autopilot class, or in Application.onCreate, register the types.
Registering a handler
class SampleAutopilot : Autopilot() {
override fun onAirshipReady(context: Context) {
Airship.liveUpdateManager.register(
type = "notification",
handler = SampleLiveUpdateHandler()
)
}
}public class SampleAutopilot extends Autopilot() {
@Override
public void onAirshipReady(Context context) {
LiveUpdateManager.shared().register("notification", new SampleLiveUpdateHandler());
}
}The type used above, "notification", is used to map Live Update events to the corresponding handler in your app.
The value can be any string that is unique across all handlers registered by an app. This also allows a single handler to manage multiple Live Updates that each have a unique name.
Starting Live Updates
Live Updates can be started from within the app.
Starting a Live Update
Airship.liveUpdateManager.start(
name = "sports-game-123",
type = "notification",
content = jsonMapOf(
"team_one_score" to 0,
"team_two_score" to 0,
"status_update" to "Game started!"
)
)Map<String, Object> content = new HashMap<>();
content.put("team_one_score", 0);
content.put("team_two_score", 0);
content.put("status_update", "Game started!");
LiveUpdateManager.shared().start(
"sports-game-123",
"notification",
content
);Updating Live Updates
Live Updates can be updated from within the app.
Updating a Live Update
Airship.liveUpdateManager.update(
name = "sports-game-123",
content = jsonMapOf(
"team_one_score" to 3,
"team_two_score" to 0,
"status_update" to "Game started!"
)
)Map<String, Object> content = new HashMap<>();
content.put("team_one_score", 3);
content.put("team_two_score", 0);
content.put("status_update", "Game started!");
LiveUpdateManager.shared().update(
"sports-game-123",
content
);Ending Live Updates
You can end a Live Update from within the app.
Ending a Live Update
Airship.liveUpdateManager.stop(
name = "sports-game-123",
content = jsonMapOf(
"team_one_score" to 9,
"team_two_score" to 6,
"status_update" to "Game over!"
)
)Map<String, Object> content = new HashMap<>();
content.put("team_one_score", 9);
content.put("team_two_score", 6);
content.put("status_update", "Game over!");
LiveUpdateManager.shared().stop(
"sports-game-123",
content
);Clearing all active Live Updates
During development, it can be useful to reset Live Update tracking on app launch. This allows any Live Updates to be started fresh, even if they were already started during a previous launch. To end all currently active Live Updates, call the clearAll() method on LiveUpdateManager.
Clearing all Live Updates
Airship.liveUpdateManager.clearAll()LiveUpdateManager.shared().clearAll();Categories