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()