Skip to content
AF
Engagement & Retention

Android Live Updates for an Ongoing Workout Notification

Last verified October 3, 2026 · 7 min read

On an Android phone, an ongoing workout can be shown as a Live Update, a promoted ongoing notification that Google documents appearing at the top of the notification drawer, on the lock screen and as a status bar chip, expanded by default and not collapsible. Google lists the requirements: a standard, BigTextStyle, CallStyle, ProgressStyle or MetricStyle notification that requests promotion with setRequestPromotedOngoing, is ongoing, has a content title, uses no custom RemoteViews, is not colorized or a group summary, and sits on a channel above IMPORTANCE_MIN, from an app that declares POST_PROMOTED_NOTIFICATIONS, which Google's reference says is required in addition to POST_NOTIFICATIONS. MetricStyle, added in API level 37, shows up to three metrics and names fitness tracking as a use case, and Google gives starting a workout as an example of the user-initiated activity Live Updates are meant for. Device makers can add their own criteria and users can turn the feature off, so check canPostPromotedNotifications and hasPromotableCharacteristics rather than assuming promotion.

The iPhone has Live Activities; the Android phone now has Live Updates, and for an ongoing workout they solve the same problem: keeping a session that is happening right now visible without the app open. Unlike ActivityKit, a Live Update is not a separate framework. It is an ordinary ongoing notification that asks the system to promote it, and the system decides whether it qualifies. On the watch, the counterpart is Wear OS ongoing activity.

What Google says a promoted notification gets#

Google's Live Updates guide describes promoted notifications as appearing more prominently on system surfaces: at the top of the notification drawer, on the lock screen, and as a chip in the status bar. Promoted cards are expanded by default and cannot be collapsed. Google also states that users can temporarily dismiss a Live Update or demote it to a standard notification, so the design has to survive being shown as a plain notification.

The eligibility checklist#

Google lists these requirements for a notification to qualify as a Live Update:

  • It uses the standard style, BigTextStyle, CallStyle, ProgressStyle or MetricStyle.
  • The app declares the non-runtime permission android.permission.POST_PROMOTED_NOTIFICATIONS in its manifest.
  • It requests promotion with EXTRA_REQUEST_PROMOTED_ONGOING or setRequestPromotedOngoing.
  • It is ongoing, with FLAG_ONGOING_EVENT set.
  • It has a content title.
  • It has no custom content view, which means no RemoteViews.
  • It is not a group summary set with setGroupSummary.
  • It does not set setColorized to true.
  • Its notification channel is not IMPORTANCE_MIN.

Google adds that device manufacturers can enforce additional criteria, and points to their own documentation. Treat promotion as something you request, not something you get.

The permission line deserves a second look. Google's Manifest.permission reference says POST_PROMOTED_NOTIFICATIONS is required in addition to, not instead of, POST_NOTIFICATIONS. A user who denied the ordinary notification permission therefore gets no Live Update either; push notifications for a fitness app covers what that denial takes with it.

Is a workout an appropriate use?#

Google gives three usage criteria: the activity must be ongoing, user-initiated and time-sensitive. A workout meets all three, and Google uses it as an example: most Live Updates should represent activities the user explicitly triggered, "such as starting a workout."

The same criteria rule out the things fitness teams are tempted to promote. Google says an activity in the past should use a standard notification, which covers the post-workout summary. It lists alerts, upcoming calendar events and quick access to app features as inappropriate, which covers a reminder to train. And it says not to let activities triggered by other parties generate Live Updates, which matters if your product has coaches or training partners.

API levels, as Google's reference labels them#

APIWhat Google's reference saysAdded in
Notification.FLAG_PROMOTED_ONGOINGSet by the system when the notification is promotedAPI level 36
Notification.hasPromotableCharacteristics()Whether the notification has every characteristic that makes it eligible, ignoring user preferencesAPI level 36
NotificationManager.canPostPromotedNotifications()Whether the app's properly formatted notifications can appear promotedAPI level 36
Notification.Builder.setShortCriticalText()Very short text for the status bar chip; suggested maximum 7 charactersAPI level 36
Notification.ProgressStyleExpanded progress bar with segments, points and a tracker iconAPI level 36
Notification.Builder.setRequestPromotedOngoing()Requests promoted ongoing statusversion 36.1
POST_PROMOTED_NOTIFICATIONSRequired to post promoted notifications, in addition to POST_NOTIFICATIONSversion 36.1
Notification.MetricStyleShows up to 3 metrics when expandedAPI level 37
NotificationCompat.Builder.setRequestPromotedOngoing()The Jetpack equivalentandroidx.core 1.17.0

Google's SDK setup pages put Android 16 at compileSdk 36 and Android 17 at 37.

MetricStyle is the workout template#

ProgressStyle is built for a tracker moving toward a destination; Google's examples are a car on its way, food being delivered and a navigation journey. A run with no fixed end does not fit that shape. MetricStyle does: Google's reference describes it as a style that shows up to 3 metrics when expanded, where metrics usually represent quantities that change over time, "such as fitness information collected by a tracker, timers, weather information."

What the reference specifies:

  • A MetricStyle must contain at least one Metric, or the style is rejected when the notification is built.
  • When the notification is promoted, one of its metrics might be shown in the status bar chip, and setCriticalMetric(index) tells the system which one is most important.
  • The style does not display the large icon.
  • A Metric is a value plus a label. Value types include FixedInt and FixedFloat with an optional unit, FixedText, FixedDate, FixedTime, and TimeDifference, which represents a timer, a stopwatch or a countdown.
  • TimeDifference.forStopwatch takes a start time in the SystemClock.elapsedRealtime() time base, or an Instant, plus a format; forPausedStopwatch takes the elapsed Duration for a paused session.

One inconsistency to know about: the class-level sample on Google's MetricStyle page passes a FORMAT_CHRONOMETER_AUTOMATIC constant, but the forStopwatch reference lists only FORMAT_ADAPTIVE and FORMAT_CHRONOMETER as valid values. Use the listed constants.

<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.POST_PROMOTED_NOTIFICATIONS" />
// MetricStyle and Notification.Metric are API level 37. Below that, post a
// standard-style ongoing notification instead.
fun buildWorkoutNotification(
    context: Context,
    startElapsedRealtime: Long,
    distanceKm: Float,
    heartRate: Int?,
): Notification {
    val builder = Notification.Builder(context, WORKOUT_CHANNEL_ID)
        .setSmallIcon(R.drawable.ic_workout)
        .setContentTitle("Outdoor run")
        .setOngoing(true)

    if (Build.VERSION.SDK_INT >= 37) {
        val heartRateValue =
            if (heartRate != null) Notification.Metric.FixedInt(heartRate, "bpm")
            else Notification.Metric.FixedText("--")

        builder
            .setStyle(
                Notification.MetricStyle()
                    .addMetric(
                        Notification.Metric(
                            Notification.Metric.TimeDifference.forStopwatch(
                                startElapsedRealtime,
                                Notification.Metric.TimeDifference.FORMAT_CHRONOMETER,
                            ),
                            "Time",
                        )
                    )
                    .addMetric(
                        Notification.Metric(Notification.Metric.FixedFloat(distanceKm, "km"), "Distance")
                    )
                    .addMetric(Notification.Metric(heartRateValue, "Heart rate"))
                    .setCriticalMetric(0) // elapsed time is the chip candidate
            )
            .setRequestPromotedOngoing(true)
    }
    return builder.build()
}

The stopwatch value keeps counting on its own, so you do not need to repost every second; repost when distance or heart rate changes, at a cadence a person can read. Showing a placeholder when the sensor drops follows Google's own UX advice not to show an empty state.

The status chip#

Google's guide describes the chip as always including an icon and optionally text, with a maximum width of 96dp. Text under 7 characters is shown whole; for longer text the system decides how much fits, and shows the icon alone if less than half would. setShortCriticalText takes the highest precedence for the chip, with a suggested maximum of 7 characters and no guarantee of how much is shown. Alternatively, the guide says a timer appears in the chip when the notification's when time uses a chronometer, through setUsesChronometer. For a workout, elapsed time is the natural chip content either way.

Check before you rely on it#

Google documents three checks. hasPromotableCharacteristics() tells you whether the notification itself is eligible, and its reference is explicit that it does not consider user preferences. canPostPromotedNotifications() tells you whether the app can post promoted notifications at all, for example whether the user turned the feature off. FLAG_PROMOTED_ONGOING is what the system sets on a notification it actually promoted.

To send users to the setting, the NotificationManager and Settings references name Settings.ACTION_APP_NOTIFICATION_PROMOTION_SETTINGS. The Live Updates guide, last updated on 1 October 2026, names a different constant, ACTION_MANAGE_APP_PROMOTED_NOTIFICATIONS, which we did not find in the Settings reference. Build against the reference for your compile SDK.

Dismissal and lifecycle#

Google's guidance is direct: posting unwanted Live Updates can lead users to revoke the app's posting permission, and you should not repost a Live Update the user dismissed. Use setDeleteIntent to detect the dismissal and record it against the session, so the next distance update does not bring the card back.

The rest of the lifecycle is the same as on the watch. Tie the notification to the session object rather than to a screen, end it on every terminal path including an abandoned session, and make sure an app update mid-session does not orphan it. Wear OS ongoing activity walks through those cases, and Google notes that Live Updates are bridged to some connected Wear OS devices, so the phone notification may also show up on the wrist. The notification is presentation only; the numbers in it come from whatever owns the session in your app, and on the watch that is Health Services exercise tracking.

Every requirement, method and API level above is taken from Google's Live Updates guide and the Android and Jetpack reference pages as of this page's review date. This part of the platform is new and still moving, so check each symbol against the reference for your target SDK.

Frequently asked questions

Does an Android workout Live Update need POST_PROMOTED_NOTIFICATIONS as well as POST_NOTIFICATIONS?
Yes. Google's Live Updates guide lists declaring the non-runtime permission android.permission.POST_PROMOTED_NOTIFICATIONS in the manifest as a requirement, and Google's Manifest.permission reference says that permission is required in addition to, not instead of, POST_NOTIFICATIONS. The reference labels it as added in version 36.1. The practical consequence is that a user who denied the ordinary notification permission cannot see your workout Live Update either, so the in-app workout screen has to stand on its own.
How many metrics can an Android MetricStyle workout notification show?
Up to three when expanded, according to Google's MetricStyle reference, which describes metrics as quantities that change over time such as fitness information collected by a tracker, timers or weather. The style must contain at least one metric or it is rejected when the notification is built. When the notification is promoted, one metric might be shown in the status bar chip, and setCriticalMetric tells the system which one is most important. Each metric is a value and a label, and the value can be a fixed number with a unit, text, a date, a time, or a running or paused stopwatch.
Why is my ongoing workout notification not being promoted to a Live Update?
Check it against Google's list: an allowed style, a promotion request through setRequestPromotedOngoing, the ongoing flag, a content title, no custom RemoteViews, not a group summary, not colorized, a channel above IMPORTANCE_MIN, and the POST_PROMOTED_NOTIFICATIONS permission. Then call hasPromotableCharacteristics, which reports eligibility but ignores user preferences, and canPostPromotedNotifications, which reflects whether the user allows promotion for the app. Google also says device manufacturers can enforce additional criteria, and users can demote a Live Update to a standard notification, so a correct notification may still appear unpromoted.
Should a fitness app use a Live Update for a workout summary or a reminder to train?
No. Google's usage criteria say a Live Update must represent an activity actively in progress, with a distinct start and end, and that an activity in the past should use a standard notification, which covers a post-workout summary. Google lists alerts, upcoming calendar events and quick access to app features as inappropriate uses, which covers training reminders, and says not to let activities triggered by other parties generate Live Updates. The workout itself qualifies: Google names starting a workout as an example of the user-initiated activity Live Updates are meant to represent.

All 55 questions in Engagement & Retention →

Keep reading

Elsewhere on the site

Pages that share this one’s concepts and sources, from other sections.

Next steps

Was this page useful?

Independent comparison, last reviewed October 3, 2026. Pricing, rate limits, and feature availability change often — confirm current details in each provider’s official documentation before you commit. Product and company names are trademarks of their respective owners; AIFitnessAPI is not affiliated with, endorsed by, or sponsored by any product listed here.

← All engagement & retention · by AIFitnessAPI