> ## Documentation Index
> Fetch the complete documentation index at: https://sdk.sleepcycle.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 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

## 安装

可以在 [Maven Central 上找到最新版本](https://central.sonatype.com/artifact/com.sleepcycle.sdk/sdk-android)。

### Groovy DSL

将 Sleep Cycle SDK 依赖添加到您的 `build.gradle`：

```gradle theme={null}
dependencies {
    implementation "com.sleepcycle.sdk:sdk-android:<latest-version>"
}
```

### Kotlin DSL

将 Sleep Cycle SDK 依赖添加到您的 `build.gradle.kts`：

```kotlin theme={null}
dependencies {
    implementation("com.sleepcycle.sdk:sdk-android:<latest-version>")
}
```

## 前置条件

### 权限

SDK 需要麦克风权限以进行基于音频的睡眠分析：

```xml theme={null}
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
```

SDK 在其清单文件中自动包含 WAKE\_LOCK 权限，以便在分析期间保持设备唤醒：

```xml theme={null}
<uses-permission android:name="android.permission.WAKE_LOCK" />
```

### 使用前台服务保持分析处于活动状态

要确保整夜持续进行睡眠分析，您必须实现一个前台服务。这样可以防止 Android 在长时间运行期间终止分析进程。

正确启动前台服务由宿主应用负责。该服务必须在其清单中声明合适的前台服务类型，以指定它需要访问的系统资源。对于睡眠分析，您通常需要 `health` 或 `microphone` 服务类型，分别授予对健康传感器和麦克风的访问权限。

## 通用说明

SDK 是线程安全的，可以从任意线程调用。

## 初始化 SDK

SDK 在使用前需要进行身份验证。初始化过程会校验您的凭证并确定可用的功能。

```kotlin theme={null}
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}")
}
```

返回的 `SleepAnalysisFeatures` 表示您的 API 密钥可用的能力：

<div style={{ background: 'rgba(128,128,128,0.04)', border: '1px solid rgba(128,128,128,0.15)', borderRadius: '0.5rem', padding: '0.75rem 1rem', fontSize: '0.8rem', lineHeight: '2.2' }}>
  <code>sleepStaging</code> <span style={{ opacity: 0.5 }}>Boolean</span> - 睡眠分期分析<br />
  <code>smartAlarm</code> <span style={{ opacity: 0.5 }}>Boolean</span> - 智能闹钟功能<br />
  <code>audioEvents</code> <span style={{ opacity: 0.5 }}>Boolean</span> - 音频事件检测<br />
  <code>snoringDetection</code> <span style={{ opacity: 0.5 }}>Boolean</span> - 鼾声检测<br />
  <code>realTimeSleepStaging</code> <span style={{ opacity: 0.5 }}>Boolean</span> - 实时睡眠分期<br />
  <code>multiChannelAnalysis</code> <span style={{ opacity: 0.5 }}>Boolean</span> - 多声道分析（立体声，两个声道）<br />
  <code>extendedAudioEvents</code> <span style={{ opacity: 0.5 }}>Boolean</span> - 标准集之外的扩展音频事件类型
</div>

## 获取 SDK 状态

通过 StateFlow 监听 SDK 状态的变化：

```kotlin theme={null}
import com.sleepcycle.sdk.SdkState

val sdkStateFlow: StateFlow<SdkState> = SleepCycleSdk.sdkStateFlow
```

获取当前状态：

```kotlin theme={null}
val currentState: SdkState = SleepCycleSdk.getState()
```

## 启动睡眠分析会话

初始化完成后，即可启动一次睡眠分析会话。该方法返回标识本次会话的 `UUID`。

```kotlin theme={null}
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}")
}
```

参数：

<div style={{ background: 'rgba(128,128,128,0.04)', border: '1px solid rgba(128,128,128,0.15)', borderRadius: '0.5rem', padding: '0.75rem 1rem', fontSize: '0.8rem', lineHeight: '2.2' }}>
  <code>config</code> <span style={{ opacity: 0.5 }}>SleepAnalysisConfig</span> - 用于指定使用哪些传感器的配置对象<br />
  <code>startMillisUtc</code> <span style={{ opacity: 0.5 }}>Long</span> - 分析的起始时间（UTC 毫秒，默认为当前时间）<br />
  <code>dataSource</code> <span style={{ opacity: 0.5 }}>DataSource?</span> - 可选的自定义数据源；为 null 时，SDK 使用设备实时传感器<br />
  <code>audioEventListeners</code> <span style={{ opacity: 0.5 }}>List\<AudioEventListener></span> - 可选监听器列表，在音频分析过程中接收回调
</div>

## 恢复会话

SDK 支持恢复先前启动的分析会话。当应用重启或前台服务被系统终止时，这一功能很有用。

```kotlin theme={null}
try {
    if (SleepCycleSdk.isResumePossible()) {
        SleepCycleSdk.resumeAnalysis()
    }
} catch (e: Exception) {
    Log.e("SDK", "Failed to resume analysis: ${e.message}")
}
```

## 停止会话

要停止当前的分析会话并获取结果：

```kotlin theme={null}
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` 包含一次睡眠分析会话的完整输出：

<div style={{ background: 'rgba(128,128,128,0.04)', border: '1px solid rgba(128,128,128,0.15)', borderRadius: '0.5rem', padding: '0.75rem 1rem', fontSize: '0.8rem', lineHeight: '2.2' }}>
  <code>sessionId</code> <span style={{ opacity: 0.5 }}>UUID</span> - 唯一会话标识符<br />
  <code>startSecondsUtc</code> <span style={{ opacity: 0.5 }}>Double</span> - 会话起始时间（UTC 秒）<br />
  <code>endSecondsUtc</code> <span style={{ opacity: 0.5 }}>Double</span> - 会话结束时间（UTC 秒）<br />
  <code>timeZoneId</code> <span style={{ opacity: 0.5 }}>String</span> - 会话开始时捕获的 IANA 时区（例如 "Europe/Stockholm"）<br />
  <code>events</code> <span style={{ opacity: 0.5 }}>List\<Event></span> - 检测到的睡眠事件<br />
  <code>breathingRates</code> <span style={{ opacity: 0.5 }}>List\<BreathingRate></span> - 呼吸频率测量值<br />
  <code>sleepStageIntervals</code> <span style={{ opacity: 0.5 }}>List\<SleepStageInterval></span> - 睡眠阶段数据<br />
  <code>realTimeSleepStageIntervals</code> <span style={{ opacity: 0.5 }}>List\<SleepStageInterval></span> - 会话期间实时发出的睡眠分期<br />
  <code>statistics</code> <span style={{ opacity: 0.5 }}>SleepStatistics?</span> - 聚合的睡眠统计（可空）<br />
  <code>audioStatistics</code> <span style={{ opacity: 0.5 }}>AudioStatistics?</span> - 音频运行状况统计（可空）
</div>

### SleepStatistics

当存在时，`statistics` 包含本次睡眠会话的聚合指标：

<div style={{ background: 'rgba(128,128,128,0.04)', border: '1px solid rgba(128,128,128,0.15)', borderRadius: '0.5rem', padding: '0.75rem 1rem', fontSize: '0.8rem', lineHeight: '2.2' }}>
  <code>totalSleepDurationSeconds</code> <span style={{ opacity: 0.5 }}>Double</span> - 总睡眠时长<br />
  <code>sleepOnsetLatencySeconds</code> <span style={{ opacity: 0.5 }}>Double?</span> - 入睡所用时间<br />
  <code>sleepEfficiency</code> <span style={{ opacity: 0.5 }}>Double</span> - 睡眠时长与在床时长的比值（0.0 到 1.0）<br />
  <code>finalWakeTimeSecondsUtc</code> <span style={{ opacity: 0.5 }}>Double?</span> - 最终醒来时间（UTC 秒）<br />
  <code>numberOfAwakenings</code> <span style={{ opacity: 0.5 }}>Int</span> - 整夜的醒来次数<br />
  <code>snoreTimeSeconds</code> <span style={{ opacity: 0.5 }}>Double</span> - 鼾声总时长<br />
  <code>snoreSessions</code> <span style={{ opacity: 0.5 }}>List\<SnoreSession></span> - 单次鼾声会话<br />
  <code>sleepStageDurationsSeconds</code> <span style={{ opacity: 0.5 }}>Map\<SleepStage, Double></span> - 每个睡眠阶段的时长
</div>

### AudioStatistics

当存在时，`audioStatistics` 包含整个会话期间音频输入运行状况的相关信息。

## 睡眠评分

会话完成后，您可以使用 `SleepScoring.compute()` 计算当晚的睡眠评分。该评分将当晚的结果与最近几晚的简短历史记录结合起来。

```kotlin theme={null}
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，数值越高越好：

<div style={{ background: 'rgba(128,128,128,0.04)', border: '1px solid rgba(128,128,128,0.15)', borderRadius: '0.5rem', padding: '0.75rem 1rem', fontSize: '0.8rem', lineHeight: '2.2' }}>
  <code>total</code> <span style={{ opacity: 0.5 }}>Float</span> - 当晚的总体睡眠评分<br />
  <code>duration</code> <span style={{ opacity: 0.5 }}>Float</span> - 用户的睡眠时长<br />
  <code>quality</code> <span style={{ opacity: 0.5 }}>Float</span> - 用户的睡眠质量<br />
  <code>routine</code> <span style={{ opacity: 0.5 }}>Float</span> - 用户的睡眠作息
</div>

`SleepScoring.identifyChronoType(history)` 根据最近的历史记录推导用户的 `ChronoType`（`EXTREME_MORNING`、`MORNING`、`INTERMEDIATE`、`EVENING`、`EXTREME_EVENING`），数据不足时返回 `null`。其结果可作为 `chronoType` 参数传回 `compute()`。

## 实时事件

SDK 在分析过程中通过 Flow API 提供实时事件更新：

```kotlin theme={null}
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` 包含：

<div style={{ background: 'rgba(128,128,128,0.04)', border: '1px solid rgba(128,128,128,0.15)', borderRadius: '0.5rem', padding: '0.75rem 1rem', fontSize: '0.8rem', lineHeight: '2.2' }}>
  <code>type</code> <span style={{ opacity: 0.5 }}>EventType</span> - 事件类型<br />
  <code>startTime</code> <span style={{ opacity: 0.5 }}>Double</span> - 起始时间戳（UTC 秒）<br />
  <code>endTime</code> <span style={{ opacity: 0.5 }}>Double</span> - 结束时间戳（UTC 秒）<br />
  <code>probability</code> <span style={{ opacity: 0.5 }}>Float</span> - 置信度分数（0.0 到 1.0）<br />
  <code>source</code> <span style={{ opacity: 0.5 }}>EventSource</span> - 检测来源<br />
  <code>sessionId</code> <span style={{ opacity: 0.5 }}>UUID</span> - 该事件所属的会话<br />
  <code>signature</code> <span style={{ opacity: 0.5 }}>FloatArray?</span> - 可选特征向量（用于鼾声事件）
</div>

## 实时呼吸频率

SDK 在分析过程中提供实时呼吸频率测量：

```kotlin theme={null}
import com.sleepcycle.sdk.BreathingRate

lifecycleScope.launch {
    SleepCycleSdk.breathingRateFlow.collect { breathingRate: BreathingRate ->
        Log.d("SDK", "Breathing rate: ${breathingRate.bpm} bpm (confidence: ${breathingRate.confidence})")
    }
}
```

每个 `BreathingRate` 包含：

<div style={{ background: 'rgba(128,128,128,0.04)', border: '1px solid rgba(128,128,128,0.15)', borderRadius: '0.5rem', padding: '0.75rem 1rem', fontSize: '0.8rem', lineHeight: '2.2' }}>
  <code>timestampSecondsUtc</code> <span style={{ opacity: 0.5 }}>Double</span> - 测量时间（自 Unix 纪元起的秒数）<br />
  <code>bpm</code> <span style={{ opacity: 0.5 }}>Float</span> - 呼吸频率（每分钟呼吸次数）<br />
  <code>confidence</code> <span style={{ opacity: 0.5 }}>Float</span> - 测量的置信度（0.0 到 1.0）<br />
  <code>sessionId</code> <span style={{ opacity: 0.5 }}>UUID</span> - 该测量所属的会话
</div>

### 实时睡眠分期（实验性）

<Warning>
  此功能为实验性功能，未来版本中可能会发生变更。API 和行为可能在未通知的情况下被修改。
</Warning>

SDK 可在分析过程中提供实时睡眠阶段预测。此功能要求您的 API 密钥启用了 `realTimeSleepStaging` 功能。

```kotlin theme={null}
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}")
        }
    }
}
```

该 Flow 在分析过程中大约每 30 秒发出一个 `SleepStageInterval` 对象，从而以接近实时的方式反馈睡眠状态的转换。

### 实时音频运行状况

SDK 在分析期间监测音频输入的运行状况，并在状态变化时发出更新：

```kotlin theme={null}
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` 取值：

<div style={{ background: 'rgba(128,128,128,0.04)', border: '1px solid rgba(128,128,128,0.15)', borderRadius: '0.5rem', padding: '0.75rem 1rem', fontSize: '0.8rem', lineHeight: '2.2' }}>
  <code>HEALTHY</code> - 音频输入包含有变化的信号<br />
  <code>FLATLINE</code> - 检测到恒定值（麦克风失效或输入静音）<br />
  <code>MISSING\_INPUT</code> - 较长时间内未收到任何音频输入
</div>

## 智能闹钟

智能闹钟在唤醒时段内监测身体活动，并在用户处于浅睡眠阶段时发出事件，从而让您在最佳时机唤醒用户。这需要为您的 API 密钥启用 `smartAlarm` 功能，且仅在主声道上支持。

使用 `SmartAlarmConfig` 配置唤醒时段，并在开始分析时传入：

```kotlin theme={null}
import com.sleepcycle.sdk.SmartAlarmConfig

SleepCycleSdk.startAnalysis(
    config = SleepAnalysisConfig(useAudio = true, useAccelerometer = true),
    smartAlarmConfig = SmartAlarmConfig(
        wakeupWindowStartSecondsUtc = windowStartSecondsUtc,
        wakeupWindowEndSecondsUtc = windowEndSecondsUtc
    )
)
```

通过 `smartAlarmFlow` 观察闹钟生命周期事件：

```kotlin theme={null}
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()
            }
        }
    }
}
```

`smartAlarmConfig` 参数在 `startMultiChannelAnalysis()` 上同样可用。

## 事件签名

对于鼾声事件，`Event.signature` 属性包含一个 16 维特征向量，表示所检测到鼾声的独特特征。来自同一人的鼾声事件在签名空间中彼此聚集，因此可以按人对事件进行聚类。

## 音频事件监听器

`AudioEventListener` 接口允许您在会话过程中接收实时的音频分析更新。实现该接口可在分析进行时访问原始音频样本、事件检测以及音量信息。

```kotlin theme={null}
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`：

```kotlin theme={null}
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` 包含：

<div style={{ background: 'rgba(128,128,128,0.04)', border: '1px solid rgba(128,128,128,0.15)', borderRadius: '0.5rem', padding: '0.75rem 1rem', fontSize: '0.8rem', lineHeight: '2.2' }}>
  <code>startTime</code> <span style={{ opacity: 0.5 }}>Double</span> - 起始时间戳（秒）<br />
  <code>type</code> <span style={{ opacity: 0.5 }}>EventType</span> - 触发本次捕获的事件类型<br />
  <code>samples</code> <span style={{ opacity: 0.5 }}>FloatArray</span> - 原始音频样本<br />
  <code>sampleRate</code> <span style={{ opacity: 0.5 }}>Int</span> - 采样率（Hz）<br />
  <code>sessionId</code> <span style={{ opacity: 0.5 }}>UUID</span> - 该片段所属的会话
</div>

## 多声道分析

SDK 支持使用立体声音频源同时分析两个声道。多声道分析将数据源生命周期与各个会话生命周期分离，使您可以独立启动和停止每个声道上的会话。

立体声流应来自两个独立的单声道麦克风，每个麦克风占用一个声道，再合并为单个立体声流。

此功能要求您的 API 密钥启用了 `multiChannelAnalysis` 功能。

### 声道分离

使用立体声输入时，`ChannelSeparationConfig` 控制如何将音频事件分配到各个声道。内置预设：

* `BED_SIDE_MICS` — 分离放置的床头麦克风（默认值）
* `CENTERED_MIC_ARRAY` — 间距很近的麦克风阵列
* `DETECTION_STRENGTH_ONLY` — 不进行空间过滤，仅依据检测置信度

所有参数（麦克风间距、模糊区、置信度阈值、各事件类型设置）都可以单独调节，以适配您的具体硬件配置和使用场景。

### 数据源生命周期

在启动各个会话之前，使用立体声音频配置启动数据源：

```kotlin theme={null}
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}")
}
```

### 在每个声道上启动会话

数据源运行后，在每个声道上启动一个会话：

```kotlin theme={null}
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` 取值：

<div style={{ background: 'rgba(128,128,128,0.04)', border: '1px solid rgba(128,128,128,0.15)', borderRadius: '0.5rem', padding: '0.75rem 1rem', fontSize: '0.8rem', lineHeight: '2.2' }}>
  <code>PRIMARY</code> - 第一个音频声道（或单声道）<br />
  <code>SECONDARY</code> - 立体声中的第二个音频声道
</div>

### 独立停止各个会话

每个会话都可以独立停止以获取其结果：

```kotlin theme={null}
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}")
}
```

### 停止数据源

所有会话都已停止后，再停止数据源：

```kotlin theme={null}
try {
    SleepCycleSdk.stopDataSource()
} catch (e: Exception) {
    Log.e("SDK", "Failed to stop data source: ${e.message}")
}
```

如果在仍有会话处于活动状态时调用 `stopDataSource()`，会强制停止这些会话并丢弃其结果。要保留结果，请先停止每个会话。
