Class WorkoutSession

java.lang.Object
com.codename1.health.workout.WorkoutSession

public abstract class WorkoutSession extends Object

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.

  • Constructor Details

    • WorkoutSession

      protected WorkoutSession(WorkoutConfiguration configuration)
      Ports and the framework construct sessions.
  • 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()
      The current state.
    • isLive

      public boolean isLive()
      Whether the operating system is running a real workout session -- see the class documentation. false means the clock and the saved record are real but collection is entirely up to you.
    • prepare

      public final AsyncResource<Boolean> prepare()
      Warms up sensors ahead of start(), for apps that show a countdown. Optional; start() works without it.
    • start

      public final AsyncResource<Boolean> start()
      Starts recording.
    • pause

      public final AsyncResource<Boolean> pause()
      Pauses recording. The elapsed clock stops.
    • resume

      public final AsyncResource<Boolean> resume()
      Resumes after a pause.
    • end

      public final AsyncResource<WorkoutSample> end()
      Ends the workout and writes it to the health store, resolving with the persisted record.
    • 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()
      Time spent recording, excluding pauses.
    • getStartedAtMillis

      public final long getStartedAtMillis()
      When the workout started, epoch millis, or 0 before start().
    • getEndedAtMillis

      public final long getEndedAtMillis()
      When it ended, epoch millis, or 0 while still running.
    • 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)
      Feeds samples into the workout. On a recorded session this is the only way anything is collected.
    • addEvent

      public final AsyncResource<Boolean> addEvent(WorkoutEvent event)
      Records an event -- a lap, a marker, a segment boundary.
    • getEvents

      public final List<WorkoutEvent> getEvents()
      Every event recorded so far.
    • addListener

      public final void addListener(WorkoutSessionListener listener)
      Registers a listener for state, statistics and events.
    • removeListener

      public final void removeListener(WorkoutSessionListener listener)
      Removes a listener.
    • getStatisticsSnapshot

      protected final Map<String, HealthQuantity> getStatisticsSnapshot()
      The accumulated statistics, for ports assembling the final record.
    • doPrepare

      protected void doPrepare(AsyncResource<Boolean> out)
      Warms up sensors. Default completes immediately.
    • doStart

      protected abstract void doStart(AsyncResource<Boolean> out)
      Starts platform collection.
    • doPause

      protected abstract void doPause(AsyncResource<Boolean> out)
      Pauses platform collection.
    • doResume

      protected abstract void doResume(AsyncResource<Boolean> out)
      Resumes platform collection.
    • doEnd

      protected abstract void doEnd(AsyncResource<WorkoutSample> out)
      Stops collection and persists the workout.
    • doDiscard

      protected abstract void doDiscard()
      Abandons the workout without persisting.
    • doAddSamples

      protected void doAddSamples(List<HealthSample> samples, AsyncResource<Boolean> out)
      Hands fed samples to the platform. Default accepts them into the shared rollup only.
    • setState

      protected final void setState(WorkoutSessionState newState)
      Moves to a new state and notifies listeners. Ports call this for transitions the platform initiated.
    • fireStatisticsUpdated

      protected final void fireStatisticsUpdated(HealthDataType type)
      Notifies listeners that a statistic changed.
    • fireEvent

      protected final void fireEvent(WorkoutEvent event)
      Notifies listeners of an event.
    • fireFailed

      protected final void fireFailed(HealthException error)
      Reports an unrecoverable failure and moves to WorkoutSessionState.FAILED.