public final class SleepSample

  1. Object
  2. HealthSample
  3. SessionSample
  4. SleepSample

A sleep session, optionally broken into SleepStageInterval spans.

Stage detail is not guaranteed

A session recorded by a watch usually carries stages; one inferred by a phone usually does not, and neither did iOS before version 16. Check hasStageDetail() and fall back to showing the total duration – drawing a hypnogram from a single “asleep” span produces an empty chart that looks like a bug.

if (night.hasStageDetail()) {
    for (SleepStageInterval iv : night.getStages()) {
        drawBand(iv.getStage(), iv.getStartMillis(), iv.getEndMillis());
    }
} else {
    showTotal(night.getDurationMillis());
}

Neither phone reads sleep in this release

Sleep is available on the simulator, the desktop and the JavaScript port, and on none of the mobile ones: a sleep query is refused on iOS and Android alike, so no session of this shape ever comes back from a device. Build against it by all means – but do not build a mobile screen around it yet.

The reason it is unfinished on iOS is worth knowing, because it shapes what finishing it will look like. HealthKit has no sleep-session object at all, only a run of overlapping category samples, so the port has to group them into sessions itself – Apple’s own convention is to split on a gap, which is what SampleQuery.setSleepSessionGapMillis(long) is there to tune. That grouping is a heuristic, which is why it belongs in the port rather than baked into the shared code.

Methods

public static SleepSample create(long startMillis, long endMillis)A session with no stage breakdown.
public static SleepSample create(long startMillis, long endMillis, List<SleepStageInterval> stages)A session with stage detail.
public List<SleepStageInterval> getStages()The stage breakdown, in the order the platform reported it.
public void addStage(SleepStageInterval interval)Appends a stage span.
public SleepStageSupport getStageSupport()true when this session carries a real stage breakdown – that is, at least one span classified as something more specific than “asleep”, “in bed” or “unknown”.
public boolean hasStageDetail()
public long getDurationMillis(SleepStage stage)The total time in stage – the time actually covered by its spans, so two overlapping spans of the same stage count the overlap once.
public long getAsleepDurationMillis()The total time spent asleep – every span except SleepStage.AWAKE, SleepStage.AWAKE_IN_BED and SleepStage.OUT_OF_BED.
public Duration getAsleepDuration()Time asleep in this session, as a Duration.
public String toString()Returns a string representation of the object.

Inherited methods

Method details

create

public static SleepSample create(long startMillis, long endMillis)
A session with no stage breakdown.

create

public static SleepSample create(long startMillis, long endMillis, List<SleepStageInterval> stages)
A session with stage detail. The list is copied defensively.

getStages

public List<SleepStageInterval> getStages()
The stage breakdown, in the order the platform reported it. Empty when no breakdown is available.

addStage

public void addStage(SleepStageInterval interval)
Appends a stage span. Used when building a session to write.

getStageSupport

public SleepStageSupport getStageSupport()

true when this session carries a real stage breakdown – that is, at least one span classified as something more specific than “asleep”, “in bed” or “unknown”.

Returns false for an empty stage list and for a list containing only SleepStage.ASLEEP_UNSPECIFIED, SleepStage.AWAKE_IN_BED and SleepStage.UNKNOWN, because none of those tell you anything a hypnogram could show. How much stage detail this session carries.

Three answers rather than the boolean hasStageDetail(), because “has stages” collapses two cases an app has to draw differently: a session that knows only asleep-versus-awake, and one carrying a real hypnogram. Branch on this before building the UI rather than discovering it from an empty chart.

hasStageDetail() is kept and is exactly getStageSupport() == SleepStageSupport.STAGED.

hasStageDetail

public boolean hasStageDetail()

getDurationMillis

public long getDurationMillis(SleepStage stage)
The total time in stage – the time actually covered by its spans, so two overlapping spans of the same stage count the overlap once.

getAsleepDurationMillis

public long getAsleepDurationMillis()

The total time spent asleep – every span except SleepStage.AWAKE, SleepStage.AWAKE_IN_BED and SleepStage.OUT_OF_BED.

Falls back to the whole session duration when no stages are present, which is the best available answer for a source that only reported “asleep from X to Y”.

getAsleepDuration

public Duration getAsleepDuration()

Time asleep in this session, as a Duration.

The millis form stays for the ports and the wire format; this is the type the rest of the framework speaks.

toString

public String toString()
Returns a string representation of the object. In general, the toString method returns a string that “textually represents” this object. The result should be a concise but informative representation that is easy for a person to read. It is recommended that all subclasses override this method. The toString method for class Object returns a string consisting of the name of the class of which the object is an instance, the at-sign character `@’, and the unsigned hexadecimal representation of the hash code of the object. In other words, this method returns a string equal to the value of: getClass().getName() + ‘@’ + Integer.toHexString(hashCode())