public abstract class WorkoutSession
- Object
- WorkoutSession
A workout being recorded.
Obtained from
WorkoutManager.startSession(WorkoutConfiguration). The state machine,
the elapsed clock and the rollup of fed samples live here in shared
code; ports implement only the do* methods.
Live and recorded sessions
isLive() tells you whether the operating system is running a real
workout session – keeping the app alive and collecting sensor data
itself. It is false everywhere in this release: the only
implementation here is a recorded session, and
WorkoutManager.isLiveSessionSupported() says so on every platform.
HKWorkoutSession on watchOS and iOS 26, and the Wear OS exercise
client, are what would change that answer; nothing here drives them
yet. Do not assume the OS keeps your app alive or collects data for
you – backgrounding can end the process and take the session with it.
On an Android phone it could not be live in any case, because Health
Connect has no such concept: Google’s documented approach there is to
record the session yourself and write it when it ends, which is exactly
what a recorded session does. So a recorded session is not a degraded
shim – it is the platform-correct design – but it does mean nothing is collected
unless you feed it, through addSamples(List) or by attaching a
Bluetooth sensor with
SensorSessionOptions.setWorkoutSession(WorkoutSession).
Check WorkoutManager.isSensorCollectionSupported() before building UI
that assumes a heart rate will appear on its own.
A killed workout is over
Sessions are deliberately not restored after the process dies. end()
was never called, so nothing is written. An app that needs
crash-resilient workouts should write partial records as it goes –
which is what the recorded path does anyway.
Constructors
protected WorkoutSession(WorkoutConfiguration configuration) | Ports and the framework construct sessions. |
Methods
Inherited methods
Constructor details
WorkoutSession
protected WorkoutSession(WorkoutConfiguration configuration)Method details
getConfiguration
public final WorkoutConfiguration getConfiguration()The configuration this session was started with.
A copy, so that reconfiguring what this returns cannot change a
workout already under way – the same reason the session took a
snapshot of what it was given. Without it the constructor’s
snapshot only moved the problem: getConfiguration().setTitle(..)
reached the very instance doEnd reads when it persists.
getState
public final WorkoutSessionState getState()isLive
public boolean isLive()false means the clock and the saved
record are real but collection is entirely up to you.prepare
public final AsyncResource<Boolean> prepare()start(), for apps that show a
countdown. Optional; start() works without it.start
public final AsyncResource<Boolean> start()pause
public final AsyncResource<Boolean> pause()resume
public final AsyncResource<Boolean> resume()end
public final AsyncResource<WorkoutSample> end()discard
public final void discard()Abandons the workout without writing anything.
A no-op once the workout has ended, and once end() has been
called it is too late: the store write is already in flight, and
claiming to have abandoned the session while that write lands –
then having its callback move the state back to ENDED – would
break the one promise in this method’s name. Discard before ending,
or delete the samples afterwards through the identifiers the write
reports.
getElapsedMillis
public final long getElapsedMillis()getStartedAtMillis
public final long getStartedAtMillis()start().getEndedAtMillis
public final long getEndedAtMillis()getStatistic
public final HealthQuantity getStatistic(HealthDataType type, AggregateMetric metric)A live statistic, or null when the platform does not compute
it and nothing has been fed in.
Never fabricates a zero. On a recorded session with no sensor attached every statistic is null, and showing “0 bpm” instead would be a claim the app cannot support.
addSamples
public final AsyncResource<Boolean> addSamples(List<HealthSample> samples)addEvent
public final AsyncResource<Boolean> addEvent(WorkoutEvent event)getEvents
public final List<WorkoutEvent> getEvents()addListener
public final void addListener(WorkoutSessionListener listener)removeListener
public final void removeListener(WorkoutSessionListener listener)getStatisticsSnapshot
protected final Map<String, HealthQuantity> getStatisticsSnapshot()doPrepare
protected void doPrepare(AsyncResource<Boolean> out)doStart
protected abstract void doStart(AsyncResource<Boolean> out)doPause
protected abstract void doPause(AsyncResource<Boolean> out)doResume
protected abstract void doResume(AsyncResource<Boolean> out)doEnd
protected abstract void doEnd(AsyncResource<WorkoutSample> out)doDiscard
protected abstract void doDiscard()doAddSamples
protected void doAddSamples(List<HealthSample> samples, AsyncResource<Boolean> out)setState
protected final void setState(WorkoutSessionState newState)fireStatisticsUpdated
protected final void fireStatisticsUpdated(HealthDataType type)fireEvent
protected final void fireEvent(WorkoutEvent event)fireFailed
protected final void fireFailed(HealthException error)WorkoutSessionState.FAILED.