Android SDK
面向 Android 应用的高级睡眠分析能力
Sleep Cycle SDK - Android 文档
概览
Sleep Cycle SDK for Android 让开发者能够将先进的睡眠分析能力集成到他们的应用中。SDK 通过音频和运动传感器提供实时睡眠追踪,并在整夜过程中生成详细的睡眠洞察和事件。
系统要求
最低 Android API 级别:
- Min SDK:API level 28(Android 9.0 Pie)
- Compile SDK:API level 35
Kotlin:
- Kotlin 版本:1.9+(JVM target 11)
- SDK 使用 Kotlin 编写,并提供 Kotlin 优先的 API
安装
SDK 以两个构件发布,二者由同一份源码构建,并暴露完全相同的 com.sleepcycle.sdk API。请只依赖其中之一:
| 内嵌版(bundled) | 精简版(slim) | |
|---|---|---|
| 构件 | com.sleepcycle.sdk:sdk-android | com.sleepcycle.sdk:sdk-android-slim |
| 机器学习模型 | 内嵌在 AAR 中 | 首次 initialize() 时下载 |
| 构件体积 | 基准 | 约小 15 MB |
首次 initialize() | 无需下载 | 下载已获授权的功能所需的模型 |
| 网络要求 | 仅授权时需要 | 授权与首次下载时需要 |
两个构件同步发版,API 完全一致,因此切换只需改动一行依赖。若希望减小应用下载体积,并可以接受首次启动时一次性的模型下载,请选择精简版;若要求 SDK 除授权外无需下载任何内容即可使用,请选择内嵌版。
可以在 Maven Central 上找到最新版本:sdk-android 和 sdk-android-slim。
Groovy DSL
将 Sleep Cycle SDK 依赖添加到您的 build.gradle:
dependencies {
// 内嵌版:模型内嵌在 AAR 中
implementation "com.sleepcycle.sdk:sdk-android:<latest-version>"
// 精简版:模型在运行时下载(替换上面一行,不要同时使用)
// implementation "com.sleepcycle.sdk:sdk-android-slim:<latest-version>"
}Kotlin DSL
将 Sleep Cycle SDK 依赖添加到您的 build.gradle.kts:
dependencies {
// 内嵌版:模型内嵌在 AAR 中
implementation("com.sleepcycle.sdk:sdk-android:<latest-version>")
// 精简版:模型在运行时下载(替换上面一行,不要同时使用)
// implementation("com.sleepcycle.sdk:sdk-android-slim:<latest-version>")
}使用精简版构件
使用精简版构件时,initialize() 会下载您的 API 密钥所授权功能需要的加密模型,并在全部模型在本地就绪之前不会返回。只有必需的模型会被下载,因此启用的功能越少,下载量越小。
下载的模型保存在应用的内部文件目录中,并在之后每次启动时复用,因此每次安装只会下载一次(若 SDK 升级更换了模型,则会再次下载)。清除应用数据、卸载应用或调用 clear() 时,这些模型会被删除。
可通过可选的 onDownloadProgress 回调向用户展示进度:
val features = SleepCycleSdk.initialize(
context = applicationContext,
apiKey = "your-api-key-here",
onDownloadProgress = { progress ->
// progress 为 0.0..1.0 之间的比例,从后台线程回调
updateProgressBar(progress)
}
)当无需下载时,该回调会立即以 1.0 调用——内嵌版构件始终如此,已完成下载的精简版安装同样如此。因此同一份代码对两个构件均无需改动。
资源就绪失败会以异常的形式从 initialize() 抛出:
SdkResourceException - 所需模型无法下载,例如首次启动时设备处于离线状态
SdkNotEnoughDiskSpaceException - 剩余空间不足以存放所需模型
两者都可以恢复:待设备联网或释放出空间后再次调用 initialize() 即可。下载会从已有的部分文件断点续传,重试不会从头开始。
前置条件
权限
SDK 需要麦克风权限以进行基于音频的睡眠分析:
<uses-permission android:name="android.permission.RECORD_AUDIO"/>SDK 在其清单文件中自动包含 WAKE_LOCK 权限,以便在分析期间保持设备唤醒:
<uses-permission android:name="android.permission.WAKE_LOCK" />使用前台服务保持分析处于活动状态
要确保整夜持续进行睡眠分析,您必须实现一个前台服务。这样可以防止 Android 在长时间运行期间终止分析进程。
正确启动前台服务由宿主应用负责。该服务必须在其清单中声明合适的前台服务类型,以指定它需要访问的系统资源。对于睡眠分析,您通常需要 health 或 microphone 服务类型,分别授予对健康传感器和麦克风的访问权限。
通用说明
SDK 是线程安全的,可以从任意线程调用。
初始化 SDK
SDK 在使用前需要进行身份验证。初始化过程会校验您的凭证并确定可用的功能。
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}")
}参数:
context Context - Android context,内部使用其 application context
apiKey String - 您的 Sleep Cycle API 密钥
logger Logger - 用于 SDK 日志的 Logger(默认写入 logcat)
logLevel LogLevel - SDK 日志级别(默认为 INFO)
forceTokenRefresh Boolean - 即使存在缓存令牌也强制重新获取令牌(默认为 false)
telemetry TelemetryConfig - 控制 SDK 发送哪些遥测数据(默认关闭分析数据,开启错误报告)
onDownloadProgress ((Float) -> Unit)? - 可选的模型下载进度,取值为 0.0..1.0 之间的比例,从后台线程回调
使用精简版构件时,initialize() 还会下载已获授权的功能所需的模型,并在它们于本地就绪之前不会返回。参见使用精简版构件。
遥测数据
telemetry 参数控制 SDK 向 Sleep Cycle 回报哪些数据:
analytics Boolean - 睡眠会话分析事件。默认关闭
errorReporting Boolean - 描述技术故障的诊断报告。默认开启
val features = SleepCycleSdk.initialize(
context = applicationContext,
apiKey = "your-api-key-here",
telemetry = TelemetryConfig(analytics = true, errorReporting = true)
)两个开关互相独立。当 analytics 关闭时,不会有任何分析事件被排队或发送。当 errorReporting 关闭时,不会发送任何诊断报告,但故障信息仍会传递给您在 initialize() 中传入的 Logger。
分析事件反映 SDK 在您的用户实际使用的设备上的表现,使 Sleep Cycle 得以发现影响特定设备型号的异常并据此调整分析——例如麦克风差异如何影响声压级测量,或如何影响睡眠分期与呼吸频率检测。若您的隐私政策有此要求,将 analytics 保持关闭即可;两种设置下 SDK 的行为完全相同。
单个事件不携带任何设备或用户标识符。它记录所属的会话、发生时间、设备型号、操作系统版本与 SDK 版本,因此无法将某次会话与某个安装或任何其他会话关联起来。
返回的 SleepAnalysisFeatures 表示您的 API 密钥可用的能力:
sleepStaging Boolean - 睡眠分期分析
smartAlarm Boolean - 智能闹钟功能
audioEvents Boolean - 音频事件检测
snoringDetection Boolean - 鼾声检测
realTimeSleepStaging Boolean - 实时睡眠分期
multiChannelAnalysis Boolean - 多声道分析(立体声,两个声道)
extendedAudioEvents Boolean - 标准集之外的扩展音频事件类型
销毁与清除 SDK
destroy() 会释放 SDK 的资源并将其恢复到 UNINITIALIZED 状态:
SleepCycleSdk.destroy()它会停止数据源,但不会结算或结束活动会话,因此被应用关闭中断的会话可以再次通过 resumeAnalysis() 接管。若要结束这些会话,请先调用 stopAnalysis() 或 stopDataSource(),或事后调用 clearActiveSessions()。
clear() 更进一步:它会销毁 SDK 并清除全部持久化状态——缓存的授权令牌、存储的内容密钥,以及精简版构件下载的所有模型:
SleepCycleSdk.clear(applicationContext)下一次 initialize() 会重新授权;使用精简版构件时,还会重新下载所需的模型。内嵌版构件中内嵌的模型不受影响。
获取 SDK 状态
通过 StateFlow 监听 SDK 状态的变化:
import com.sleepcycle.sdk.SdkState
val sdkStateFlow: StateFlow<SdkState> = SleepCycleSdk.sdkStateFlow获取当前状态:
val currentState: SdkState = SleepCycleSdk.getState()启动睡眠分析会话
初始化完成后,即可启动一次睡眠分析会话。该方法返回标识本次会话的 UUID。
import com.sleepcycle.sdk.SleepAnalysisConfig
try {
val sessionId: UUID = SleepCycleSdk.startAnalysis(
config = SleepAnalysisConfig(
useAudio = true,
useAccelerometer = true
)
)
Log.d("SDK", "Analysis started with session ID: $sessionId")
} catch (e: Exception) {
Log.e("SDK", "Failed to start analysis: ${e.message}")
}参数:
config SleepAnalysisConfig - 用于指定使用哪些传感器的配置对象
startMillisUtc Long - 分析的起始时间(UTC 毫秒,默认为当前时间)
dataSource DataSource? - 可选的自定义数据源;为 null 时,SDK 使用设备实时传感器,且仅在会话使用音频时才打开麦克风
audioEventListeners List<AudioEventListener> - 可选监听器列表,在音频分析过程中接收回调
恢复会话
SDK 支持恢复先前启动的分析会话。当应用重启或前台服务被系统终止时,这一功能很有用。
try {
if (SleepCycleSdk.isResumePossible()) {
SleepCycleSdk.resumeAnalysis()
}
} catch (e: Exception) {
Log.e("SDK", "Failed to resume analysis: ${e.message}")
}若某个可恢复的会话不打算恢复,可用 clearActiveSessions() 结束它并丢弃其结果,使 isResumePossible() 重新返回 false:
SleepCycleSdk.clearActiveSessions()若数据源正在运行,该方法会抛出 IllegalStateException。
停止会话
要停止当前的分析会话并获取结果:
try {
val result: AnalysisResult? = SleepCycleSdk.stopAnalysis()
result?.let { analysisResult ->
val events = analysisResult.events
val breathingRates = analysisResult.breathingRates
val sleepStageIntervals = analysisResult.sleepStageIntervals
analysisResult.statistics?.let { statistics ->
Log.d("SDK", "Sleep duration: ${statistics.totalSleepDurationSeconds}")
}
events.forEach { event ->
Log.d("SDK", "${event.type} from ${event.startTime} to ${event.endTime}")
}
breathingRates.forEach { breathingRate ->
Log.d("SDK", "Breathing rate: ${breathingRate.bpm} bpm at ${breathingRate.timestampSecondsUtc}")
}
analysisResult.audioStatistics?.let { audioStats ->
audioStats.healthIntervals.forEach { interval ->
Log.d("SDK", "Audio ${interval.status}: ${interval.interval}")
}
}
}
} catch (e: Exception) {
Log.e("SDK", "Failed to stop analysis: ${e.message}")
}分析结果
AnalysisResult 包含一次睡眠分析会话的完整输出:
sessionId UUID - 唯一会话标识符
startSecondsUtc Double - 会话起始时间(UTC 秒)
endSecondsUtc Double - 会话结束时间(UTC 秒)
timeZoneId String - 会话开始时捕获的 IANA 时区(例如 "Europe/Stockholm")
events List<Event> - 检测到的睡眠事件
breathingRates List<BreathingRate> - 呼吸频率测量值
sleepStageIntervals List<SleepStageInterval> - 睡眠阶段数据
realTimeSleepStageIntervals List<SleepStageInterval> - 会话期间实时发出的睡眠分期
sleepStagePredictions List<SleepStagePrediction> - 会话结束后对每个 epoch 的预测,包含各睡眠阶段的概率
statistics SleepStatistics? - 聚合的睡眠统计(可空)
audioStatistics AudioStatistics? - 音频运行状况统计(可空)
SleepStatistics
当存在时,statistics 包含本次睡眠会话的聚合指标:
totalSleepDurationSeconds Double - 总睡眠时长
sleepOnsetLatencySeconds Double? - 入睡所用时间
sleepEfficiency Double - 睡眠时长与在床时长的比值(0.0 到 1.0)
finalWakeTimeSecondsUtc Double? - 最终醒来时间(UTC 秒)
numberOfAwakenings Int - 整夜的醒来次数
snoreTimeSeconds Double - 鼾声总时长
snoreSessions List<SnoreSession> - 单次鼾声会话
sleepStageDurationsSeconds Map<SleepStage, Double> - 每个睡眠阶段的时长
AudioStatistics
当存在时,audioStatistics 包含整个会话期间音频输入运行状况的相关信息。
睡眠评分
会话完成后,您可以使用 SleepScoring.compute() 计算当晚的睡眠评分。该评分将当晚的结果与最近几晚的简短历史记录结合起来。
import com.sleepcycle.sdk.score.SleepScore
import com.sleepcycle.sdk.score.SleepScoring
import com.sleepcycle.sdk.score.toSleepScoreHistoryEntry
// 从每个已完成的结果构建历史记录条目,并将其持久化以供后续夜晚使用
val historyEntry = analysisResult.toSleepScoreHistoryEntry()
val score: SleepScore = SleepScoring.compute(
result = analysisResult,
history = recentHistoryEntries,
dateOfBirthSecondsUtc = userDateOfBirthSecondsUtc, // 可选,按年龄调整质量子评分
chronoType = userChronoType // 可选,选择时段子评分的窗口
)
Log.d("SDK", "Sleep score: ${score.total} (duration=${score.duration}, quality=${score.quality}, routine=${score.routine})")每个 SleepScore 字段的取值范围为 0.0–1.0,数值越高越好:
total Float - 当晚的总体睡眠评分
duration Float - 用户的睡眠时长
quality Float - 用户的睡眠质量
routine Float - 用户的睡眠作息
SleepScoring.identifyChronoType(history) 根据最近的历史记录推导用户的 ChronoType(EXTREME_MORNING、MORNING、INTERMEDIATE、EVENING、EXTREME_EVENING),数据不足时返回 null。其结果可作为 chronoType 参数传回 compute()。
实时事件
SDK 在分析过程中通过 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)
else -> handleOtherEvent(event)
}
}
}
}当您的 API 密钥启用了 extendedAudioEvents 功能时,会在标准事件之外同时报告额外的 EventType 值:BIRD、CAT、DIGESTIVE、DOG、FART、MUSIC、SNEEZE、THROAT_CLEARING、TRAFFIC、WATER 和 WIND。
每个 Event 包含:
type EventType - 事件类型
startTime Double - 起始时间戳(UTC 秒)
endTime Double - 结束时间戳(UTC 秒)
probability Float - 置信度分数(0.0 到 1.0)
source EventSource - 检测来源
sessionId UUID - 该事件所属的会话
signature FloatArray? - 可选特征向量(用于鼾声事件)
实时呼吸频率
SDK 在分析过程中提供实时呼吸频率测量:
import com.sleepcycle.sdk.BreathingRate
lifecycleScope.launch {
SleepCycleSdk.breathingRateFlow.collect { breathingRate: BreathingRate ->
Log.d("SDK", "Breathing rate: ${breathingRate.bpm} bpm (confidence: ${breathingRate.confidence})")
}
}每个 BreathingRate 包含:
timestampSecondsUtc Double - 测量时间(自 Unix 纪元起的秒数)
bpm Float - 呼吸频率(每分钟呼吸次数)
confidence Float - 测量的置信度(0.0 到 1.0)
sessionId UUID - 该测量所属的会话
实时睡眠分期
SDK 可在分析过程中提供实时睡眠阶段预测。此功能要求您的 API 密钥启用了 realTimeSleepStaging 功能。
import com.sleepcycle.sdk.SleepStage
import com.sleepcycle.sdk.SleepStagePrediction
lifecycleScope.launch {
SleepCycleSdk.sleepStageFlow.collect { prediction: SleepStagePrediction ->
when (prediction.stage) {
SleepStage.AWAKE -> Log.d("SDK", "Awake: ${prediction.interval}")
SleepStage.LIGHT -> Log.d("SDK", "Light sleep: ${prediction.interval}")
SleepStage.DEEP -> Log.d("SDK", "Deep sleep: ${prediction.interval}")
SleepStage.REM -> Log.d("SDK", "REM sleep: ${prediction.interval}")
}
Log.d("SDK", "Deep sleep probability: ${prediction.probabilities.deep}")
}
}该 Flow 在分析过程中大约每 30 秒发出一个 SleepStagePrediction 对象,从而以接近实时的方式反馈睡眠状态的转换。每个预测都包含最可能的睡眠阶段 stage、对应 epoch 的时间区间 interval,以及 probabilities(一个 SleepStageProbabilities,包含 awake、rem、light 和 deep 各睡眠阶段的概率)。这些概率之和为 1,可以通过 probabilities[SleepStage.DEEP] 按睡眠阶段读取。
实时音频运行状况
SDK 在分析期间监测音频输入的运行状况,并在状态变化时发出更新:
import com.sleepcycle.sdk.AudioHealthUpdate
import com.sleepcycle.sdk.AudioHealthStatus
lifecycleScope.launch {
SleepCycleSdk.audioHealthFlow.collect { update: AudioHealthUpdate ->
when (update.status) {
AudioHealthStatus.HEALTHY -> Log.d("SDK", "Audio input healthy")
AudioHealthStatus.FLATLINE -> Log.w("SDK", "Audio flatline detected")
AudioHealthStatus.MISSING_INPUT -> Log.w("SDK", "Audio input missing")
}
}
}AudioHealthStatus 取值:
HEALTHY - 音频输入包含有变化的信号
FLATLINE - 检测到恒定值(麦克风失效或输入静音)
MISSING_INPUT - 较长时间内未收到任何音频输入
智能闹钟
智能闹钟在唤醒时段内监测身体活动,并在用户处于浅睡眠阶段时发出事件,从而让您在最佳时机唤醒用户。这需要为您的 API 密钥启用 smartAlarm 功能,且仅在主声道上支持。
使用 SmartAlarmConfig 配置唤醒时段,并在开始分析时传入:
import com.sleepcycle.sdk.SmartAlarmConfig
SleepCycleSdk.startAnalysis(
config = SleepAnalysisConfig(useAudio = true, useAccelerometer = true),
smartAlarmConfig = SmartAlarmConfig(
wakeupWindowStartSecondsUtc = windowStartSecondsUtc,
wakeupWindowEndSecondsUtc = windowEndSecondsUtc
)
)通过 smartAlarmFlow 观察闹钟生命周期事件:
import com.sleepcycle.sdk.SmartAlarmEvent
lifecycleScope.launch {
SleepCycleSdk.smartAlarmFlow.collect { event: SmartAlarmEvent ->
when (val type = event.type) {
is SmartAlarmEvent.Type.Armed -> Log.d("SDK", "Smart alarm armed")
is SmartAlarmEvent.Type.Triggered -> when (type.reason) {
SmartAlarmEvent.Reason.OPTIMAL_WAKE_UP -> ringAlarm()
SmartAlarmEvent.Reason.USER_INTERACTION -> ringAlarm()
SmartAlarmEvent.Reason.WINDOW_END -> ringAlarm()
}
}
}
}可在会话运行期间使用 updateSmartAlarm() 修改闹钟。它会替换会话启动时设置的闹钟、为未设置闹钟的会话添加闹钟,或在传入 null 时取消闹钟:
// 调整唤醒时段
SleepCycleSdk.updateSmartAlarm(
SmartAlarmConfig(
wakeupWindowStartSecondsUtc = newWindowStartSecondsUtc,
wakeupWindowEndSecondsUtc = newWindowEndSecondsUtc
)
)
// 取消闹钟
SleepCycleSdk.updateSmartAlarm(null)新配置会被持久化,因此进程被杀后恢复的会话会沿用它;已经触发过的闹钟会被新配置重新装载,从而可以再次触发。若唤醒时段已经过去,会在下一次分析节拍时以 WINDOW_END 触发。该调用针对主声道会话,若该声道上没有活动会话,则抛出 IllegalStateException。
smartAlarmConfig 参数在 startMultiChannelAnalysis() 上同样可用,且该方法会拒绝为 AnalysisChannel.PRIMARY 以外的声道传入该参数。
事件签名
对于鼾声事件,Event.signature 属性包含一个 16 维特征向量,表示所检测到鼾声的独特特征。来自同一人的鼾声事件在签名空间中彼此聚集,因此可以按人对事件进行聚类。
音频事件监听器
AudioEventListener 接口允许您在会话过程中接收实时的音频分析更新。实现该接口可在分析进行时访问原始音频样本、事件检测以及音量信息。
val audioEventListener = object : AudioEventListener {
override fun onAudioAnalysisBatchCompleted(
audioSamples: FloatArray,
audioSampleRate: Int,
audioStartTime: Double,
audioEndTime: Double,
audioProbability: Map<EventType, Float>,
eventsStarted: List<EventStartedInfo>,
eventsEnded: List<EventEndedInfo>,
dbSpl: FloatArray,
sessionId: UUID
) {
// Process audio samples and events
}
}
try {
SleepCycleSdk.startAnalysis(
config = SleepAnalysisConfig(useAudio = true),
audioEventListeners = listOf(audioEventListener)
)
} catch (e: Exception) {
Log.e("SDK", "Failed to start analysis: ${e.message}")
}audioSamples 参数顺序包含所有已处理的音频数据,批次之间没有间隙或重叠。每个批次都从前一个批次结束的位置精确接续,从而对所有分析过的音频实现完整覆盖。
audioProbability 参数提供所分析时间窗口内每种 EventType 的每批次概率。dbSpl 参数提供批次中每个时间帧以 dB SPL 表示的 A 计权声音音量。
音频片段
当检测到特定的睡眠事件(例如鼾声、梦话或咳嗽)时,SDK 可以捕获短音频录音。
要使用音频片段,需创建一个音频片段生成器,并将其传入 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
}
}
try {
// Create audio clips producer
val audioClipsProducer = SleepCycleSdk.createAudioClipsProducer(
config = audioClipsConfig,
receiver = audioClipsReceiver
)
// Pass to startAnalysis
SleepCycleSdk.startAnalysis(
config = SleepAnalysisConfig(useAudio = true),
audioEventListeners = listOf(audioClipsProducer)
)
} catch (e: Exception) {
Log.e("SDK", "Failed to start analysis with audio clips: ${e.message}")
}每个 AudioClip 包含:
startTime Double - 起始时间戳(秒)
type EventType - 触发本次捕获的事件类型
samples FloatArray - 原始音频样本
sampleRate Int - 采样率(Hz)
sessionId UUID - 该片段所属的会话
多声道分析
SDK 支持使用立体声音频源同时分析两个声道。多声道分析将数据源生命周期与各个会话生命周期分离,使您可以独立启动和停止每个声道上的会话。
立体声流应来自两个独立的单声道麦克风,每个麦克风占用一个声道,再合并为单个立体声流。
此功能要求您的 API 密钥启用了 multiChannelAnalysis 功能。
声道分离
使用立体声输入时,ChannelSeparationConfig 控制如何将音频事件分配到各个声道。内置预设:
BED_SIDE_MICS— 分离放置的床头麦克风(默认值)CENTERED_MIC_ARRAY— 间距很近的麦克风阵列DETECTION_STRENGTH_ONLY— 不进行空间过滤,仅依据检测置信度
所有参数(麦克风间距、模糊区、置信度阈值、各事件类型设置)都可以单独调节,以适配您的具体硬件配置和使用场景。
数据源生命周期
在启动各个会话之前,使用立体声音频配置启动数据源:
try {
val dataSource = SleepCycleSdk.createLiveDataSource(
audioFormat = DataSource.AudioFormat.STEREO
)
SleepCycleSdk.startDataSource(
dataSource = dataSource,
channelSeparationConfig = ChannelSeparationConfig.BED_SIDE_MICS
)
} catch (e: Exception) {
Log.e("SDK", "Failed to start data source: ${e.message}")
}在每个声道上启动会话
数据源运行后,在每个声道上启动一个会话:
import com.sleepcycle.sdk.AnalysisChannel
try {
val primarySessionId: UUID = SleepCycleSdk.startMultiChannelAnalysis(
channel = AnalysisChannel.PRIMARY,
config = SleepAnalysisConfig(useAudio = true, useAccelerometer = true)
)
val secondarySessionId: UUID = SleepCycleSdk.startMultiChannelAnalysis(
channel = AnalysisChannel.SECONDARY,
config = SleepAnalysisConfig(useAudio = true, useAccelerometer = false)
)
} catch (e: Exception) {
Log.e("SDK", "Failed to start multi-channel analysis: ${e.message}")
}AnalysisChannel 取值:
PRIMARY - 第一个音频声道(或单声道)
SECONDARY - 立体声中的第二个音频声道
独立停止各个会话
每个会话都可以独立停止以获取其结果:
try {
val primaryResult: AnalysisResult? = SleepCycleSdk.stopAnalysis(
sessionId = primarySessionId
)
val secondaryResult: AnalysisResult? = SleepCycleSdk.stopAnalysis(
sessionId = secondarySessionId
)
} catch (e: Exception) {
Log.e("SDK", "Failed to stop analysis: ${e.message}")
}停止数据源
所有会话都已停止后,再停止数据源:
try {
SleepCycleSdk.stopDataSource()
} catch (e: Exception) {
Log.e("SDK", "Failed to stop data source: ${e.message}")
}如果在仍有会话处于活动状态时调用 stopDataSource(),会强制停止这些会话并丢弃其结果。要保留结果,请先停止每个会话。