Skip to main content

Sleep Cycle SDK - Android Documentation

Overview

The Sleep Cycle SDK for Android enables developers to integrate advanced sleep analysis capabilities into their applications. The SDK provides real-time sleep tracking using audio and motion sensors, delivering detailed sleep insights and events throughout the night.

System Requirements

Minimum Android API Level:
  • Min SDK: API level 28 (Android 9.0 Pie)
  • Compile SDK: API level 35
Kotlin:
  • Kotlin Version: 1.9+ (JVM target 11)
  • The SDK is written in Kotlin and provides a Kotlin-first API

Installation

Find the latest version on Maven Central.

Groovy DSL

Add the Sleep Cycle SDK dependency to your build.gradle:
dependencies {
    implementation "com.sleepcycle.sdk:sdk-android:<latest-version>"
}

Kotlin DSL

Add the Sleep Cycle SDK dependency to your build.gradle.kts:
dependencies {
    implementation("com.sleepcycle.sdk:sdk-android:<latest-version>")
}

Prerequisites

Permissions

The SDK requires microphone access for audio-based sleep analysis:
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
The SDK automatically includes the WAKE_LOCK permission in its manifest to keep the device awake during analysis:
<uses-permission android:name="android.permission.WAKE_LOCK" />

Keeping the analysis active using a foreground service

To ensure continuous sleep analysis throughout the night, you must implement a foreground service. This prevents Android from terminating the analysis process during extended periods. It is up to the host app to start the foreground service correctly. The service must declare appropriate foreground service types in its manifest to specify what system resources it needs access to. For sleep analysis, you’ll typically need the health or microphone service types, which grant access to health sensors and microphone respectively.

General

It’s typical to call initialize() during application startup, often in your Application subclass’s onCreate() method. This ensures the SDK is ready when your activities need it. The SDK maintains its state across configuration changes. The SDK is thread safe and can be called from any thread.

Initialize the SDK

The SDK requires authentication before use. The initialization process validates your credentials and determines available features.
import com.sleepcycle.sdk.SleepCycleSdk

try {
    val features = SleepCycleSdk.initialize(
        context = applicationContext,
        apiKey = "your-api-key-here"
    )
    Log.d("SDK", "Authorized with features: $features")
} catch (e: Exception) {
    Log.e("SDK", "Authorization failed: ${e.message}")
}

Start a sleep analysis session

Once initialized, you can start a sleep analysis session:
import com.sleepcycle.sdk.SleepAnalysisConfig

SleepCycleSdk.startAnalysis(
    config = SleepAnalysisConfig(
        useAudio = true,
        useAccelerometer = true
    )
)
Parameters:
  • config: Configuration object specifying which sensors to use
  • startMillisUtc: Analysis start time in UTC milliseconds (defaults to current time)
  • dataSource: Optional custom data source. When null, the SDK uses live device sensors (microphone and accelerometer)
  • audioEventListeners: Optional list of AudioEventListener instances that receive callbacks during audio analysis. Use this to capture audio samples and events in real-time

Resume a session

The SDK supports resuming a previously started analysis session. This is useful when your app restarts or the foreground service is terminated by the system.
if (SleepCycleSdk.isResumePossible()) {
    SleepCycleSdk.resumeAnalysis()
}

Stop a session

To stop an active analysis session and retrieve the results:
val result: AnalysisResult? = SleepCycleSdk.stopAnalysis()

result?.let { analysisResult ->
    val statistics = analysisResult.statistics
    val events = analysisResult.eventsByType
    val breathingRates = analysisResult.breathingRates

    Log.d("SDK", "Sleep duration: ${statistics.totalSleepDurationSeconds}")

    events?.get(EventType.SNORING)?.forEach { event ->
        Log.d("SDK", "Snoring detected from ${event.startTime} to ${event.endTime}")
    }

    breathingRates.forEach { breathingRate ->
        Log.d("SDK", "Breathing rate: ${breathingRate.bpm} bpm at ${breathingRate.timestampSecondsUtc}")
    }
}

Real-time events

The SDK provides real-time event updates during analysis through a Flow API:
import com.sleepcycle.sdk.Event
import com.sleepcycle.sdk.EventType

lifecycleScope.launch {
    SleepCycleSdk.eventFlow.collect { events: List<Event> ->
        events.forEach { event ->
            when (event.type) {
                EventType.MOVEMENT -> handleMovement(event)
                EventType.SNORING -> handleSnoring(event)
                EventType.TALKING -> handleTalking(event)
                EventType.COUGHING -> handleCoughing(event)
            }
        }
    }
}

Real-time breathing rate

The SDK provides real-time breathing rate measurements during analysis:
import com.sleepcycle.sdk.BreathingRate

lifecycleScope.launch {
    SleepCycleSdk.breathingRateFlow.collect { breathingRate: BreathingRate ->
        Log.d("SDK", "Breathing rate: ${breathingRate.bpm} bpm (confidence: ${breathingRate.confidence})")
    }
}
The flow emits BreathingRate objects containing the breathing rate measurement. Each measurement includes:
  • timestampSecondsUtc: Double - Time of measurement in seconds since Unix epoch
  • bpm: Float - Breathing rate in breaths per minute
  • confidence: Float - Confidence level of the measurement (0.0 to 1.0)

Real-time sleep staging (Experimental)

This feature is experimental and may change in future releases. The API and behavior are subject to modification without notice.
The SDK can provide real-time sleep stage predictions during analysis. This feature requires the realTimeSleepStaging capability to be enabled for your API key.
import com.sleepcycle.sdk.SleepStage
import com.sleepcycle.sdk.SleepStageInterval

lifecycleScope.launch {
    SleepCycleSdk.sleepStageFlow.collect { stageInterval: SleepStageInterval ->
        when (stageInterval.stage) {
            SleepStage.AWAKE -> Log.d("SDK", "Awake: ${stageInterval.interval}")
            SleepStage.LIGHT -> Log.d("SDK", "Light sleep: ${stageInterval.interval}")
            SleepStage.DEEP -> Log.d("SDK", "Deep sleep: ${stageInterval.interval}")
            SleepStage.REM -> Log.d("SDK", "REM sleep: ${stageInterval.interval}")
        }
    }
}
The flow emits SleepStageInterval objects containing the sleep stage and time interval. Sleep stages are emitted approximately every 30 seconds during analysis, providing near real-time feedback on sleep state transitions. SleepStageInterval properties:
  • stage: SleepStage - The predicted sleep stage
  • interval: TimeInterval - The time interval for this stage
SleepStage values:
  • AWAKE - User is awake
  • LIGHT - Light sleep (N1/N2)
  • DEEP - Deep sleep (N3/slow-wave sleep)
  • REM - REM (rapid eye movement) sleep

Event signatures

For snoring events, the Event.signature property contains a 16-dimensional feature vector that represents unique characteristics of the detected snore. Snore events from the same person are grouped close to each other in the signature space, allowing clustering of events by person.

Audio event listener

The AudioEventListener interface allows you to receive real-time audio analysis updates during a session. Implement this interface to access raw audio samples, event detection, and volume information as analysis progresses.
val audioEventListener = object : AudioEventListener {
    override fun onAudioAnalysisBatchCompleted(
        audioSamples: FloatArray,
        audioSampleRate: Int,
        audioStartTime: Double,
        audioEndTime: Double,
        eventsStarted: List<EventStartedInfo>,
        eventsEnded: List<EventEndedInfo>,
        rms: FloatArray
    ) {
        // Process audio samples and events
    }
}

SleepCycleSdk.startAnalysis(
    config = SleepAnalysisConfig(useAudio = true),
    audioEventListeners = listOf(audioEventListener)
)
The audioSamples parameter contains all processed audio data in sequence, without any gaps or overlap between batches. Each batch continues exactly where the previous batch ended, ensuring complete coverage of all analyzed audio.

Audio clips

The SDK can capture short audio recordings when specific sleep events are detected, such as snoring, sleep talking, or coughing. To use audio clips, create an audio clips producer and pass it to startAnalysis:
import com.sleepcycle.sdk.*

// Configure which events trigger audio clips
val audioClipsConfig = AudioClipsConfig(
    activeTypes = hashMapOf(
        EventType.SNORING to EventTypeConfig(minDuration = 0.5),
        EventType.TALKING to EventTypeConfig(minDuration = 0.5)
    ),
    clipLength = 10.0  // Clip duration in seconds
)

// Implement receiver to handle captured clips
val audioClipsReceiver = object : AudioClipsReceiver {
    override fun onAudioClipReceived(audioClip: AudioClip) {
        // Process or store the audio clip
    }
}

// Create audio clips producer
val audioClipsProducer = SleepCycleSdk.createAudioClipsProducer(
    config = audioClipsConfig,
    receiver = audioClipsReceiver
)

// Pass to startAnalysis
SleepCycleSdk.startAnalysis(
    config = SleepAnalysisConfig(useAudio = true),
    audioEventListeners = listOf(audioClipsProducer)
)
Each AudioClip contains the audio samples as a FloatArray, the event type, start time, and sample rate.

Get the SDK state

Monitor SDK state changes using the StateFlow:
import com.sleepcycle.sdk.SdkState

val sdkStateFlow: StateFlow<SdkState> = SleepCycleSdk.sdkStateFlow
Get the current state:
val currentState: SdkState = SleepCycleSdk.getState()