Android SDK 시작하기
Requirements
Minimum requirements on SleepTrack SDK for Android
- Android 7.0 (API level 24) 혹은 더 높은 버전
- Java 1.8 혹은 더 높은 버전
- Android Gradle plugin 8.0 혹은 더 높은 버전
API Key
- SleepTrack SDK를 사용하기 위해서는 API key가 필요합니다.
- API key를 발급하는 방법에 대해서는 이 링크 API Key 생성하기를 참고하세요.
Getting Ready
Install SleepTrack SDK and Settings
- Android Studio를 이용하여 기본 프로젝트를 생성합니다.
- AndroidManifest.xml 파일을 열어 퍼미션을 추가합니다.
<manifest ...>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE"/>
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<application ...>
...
</application>
</manifest>
- 앱 수준의 build.gradle 파일을 열어 lifecycle-service, okhttp, gson 및 asleepsdk를 추가합니다.
dependencies {
...
implementation("androidx.lifecycle:lifecycle-service:2.8.7")
implementation("com.squareup.okhttp3:okhttp:4.11.0")
implementation("com.google.code.gson:gson:2.10")
implementation("ai.asleep:asleepsdk:3.1.5")
}dependencies {
...
implementation 'androidx.lifecycle:lifecycle-service:2.8.7'
implementation 'com.squareup.okhttp3:okhttp:4.11.0'
implementation 'com.google.code.gson:gson:2.10'
implementation 'ai.asleep:asleepsdk:3.1.0'
}Sleep Tracking with SleepTrack SDK
권한 획득
- 필수 권한인 RECORD_AUDIO와 POST_NOTIFICATIONS(Android 13 이상)을 획득합니다.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
...
ActivityCompat.requestPermissions(
this@MainActivity,
arrayOf(android.Manifest.permission.RECORD_AUDIO,
android.Manifest.permission.POST_NOTIFICATIONS),
0)
...
}
UI 구성
- 화면에 보여질 init, begin, end, report의 버튼을 만듭니다.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/btn_init"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="200dp"
android:text="init"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_begin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="32dp"
android:text="begin"
app:layout_constraintEnd_toStartOf="@+id/btn_end"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btn_init" />
<Button
android:id="@+id/btn_end"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:text="end"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/btn_begin"
app:layout_constraintTop_toBottomOf="@+id/btn_init" />
<Button
android:id="@+id/btn_report"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:text="report"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btn_init" />
</androidx.constraintlayout.widget.ConstraintLayout>- 버튼을 변수로 선언합니다.
...
private lateinit var btnInit: Button
private lateinit var btnBegin: Button
private lateinit var btnEnd: Button
private lateinit var btnReport: Button
...
btnInit = findViewById(R.id.btn_init)
btnBegin = findViewById(R.id.btn_begin)
btnEnd = findViewById(R.id.btn_end)
btnReport = findViewById(R.id.btn_report)
SleepTrack SDK 초기화
- apiKey의 [YOUR API KEY]에는 실제 발급받은 apiKey를 입력합니다.
- userId가 null인 경우, SDK에서 새로운 userId를 생성합니다.
실제 앱 구현 시, 생성된 userId는 저장 후 필요 시 가져와서 입력하는 방식으로 사용해야 합니다. - service는 개발할 앱의 서비스명이 있다면 입력하세요.
- asleepConfigListener는 초기화에 성공, 실패 여부를 콜백합니다.
- 성공시 userId와 asleepConfig가 반환됩니다.
val TAG = "[AsleepSDK]"
private var createdUserId: String? = null
private var createdAsleepConfig: AsleepConfig? = null
private var createdSessionId: String? = null
...
btnInit.setOnClickListener {
Asleep.initAsleepConfig(
context = this,
apiKey = "[YOUR API KEY]",
userId = null,
service = "Test App",
asleepConfigListener = object: Asleep.AsleepConfigListener {
override fun onFail(errorCode: Int, detail: String) {
Log.d(TAG, "initAsleepConfig onFail $errorCode $detail")
}
override fun onSuccess(userId: String?, asleepConfig: AsleepConfig?) {
Log.d(TAG, "initAsleepConfig onSuccess $userId")
createdUserId = userId
createdAsleepConfig = asleepConfig
}
})
}Begin SleepTracking
- 수면 측정을 시작합니다.
- initAsleepConfig에서 생성된 asleepConfig와 수면 측정 상태를 확인할 수 있는 asleepTrackingListener를 입력합니다.
- 측정이 시작되면 onStart() 콜백이 호출됩니다.
- 매 30초마다 onPerform() 콜백이 호출되어 진행 상태를 제공합니다.
- 측정이 종료되면 onFinish() 콜백이 호출됩니다.
btnBegin.setOnClickListener {
createdAsleepConfig?.let { asleepConfig ->
Asleep.beginSleepTracking(
asleepConfig = asleepConfig,
asleepTrackingListener = object : Asleep.AsleepTrackingListener {
override fun onFail(errorCode: Int, detail: String) {
Log.d(TAG, "beginSleepTracking onFail $errorCode $detail")
}
override fun onFinish(sessionId: String?) {
Log.d(TAG, "beginSleepTracking onFinish $sessionId")
}
override fun onPerform(sequence: Int) {
Log.d(TAG, "beginSleepTracking onPerform $sequence")
}
override fun onStart(sessionId: String) {
Log.d(TAG, "beginSleepTracking onStart $sessionId")
createdSessionId = sessionId
}
})
}
}End SleepTracking
- 수면 측정을 종료합니다.
btnEnd.setOnClickListener {
Asleep.endSleepTracking()
}Get Report
- 측정된 수면 데이터를 받아옵니다.
- initAsleepConfig에서 생성된 asleepConfig를 파라메터로 입력하여 Reports 객체를 만듭니다.
- 수면 측정 시 생성된 sessionId를 입력합니다.
btnReport.setOnClickListener {
createdSessionId?.let { sessionId ->
val reports = Asleep.createReports(createdAsleepConfig)
reports?.getReport(
sessionId = sessionId,
reportListener = object : Reports.ReportListener {
override fun onFail(errorCode: Int, detail: String) {
Log.d(TAG, "getReport onFail $errorCode $detail")
}
override fun onSuccess(report: Report?) {
Log.d(TAG, "getReport onSuccess $report")
}
})
}
}Logcat 확인
- logcat 로그에 아래와 같이 userId, sessionId, report가 성공적으로 생성되었다면, SDK가 정상적으로 동작하고 있는 것입니다.

앱 개발시 주의점
- 포그라운드 서비스 사용
수면 측정을 위해, 앱은 밤 동안 지속적인 레코딩, 데이터 처리, 네트워크 작업 등을 수행해야 합니다. 이러한 작업이 중단되지 않도록 하기 위해, **포그라운드 서비스(Foreground Service)**를 활용하여 앱을 개발하는 것이 필수적입니다.
더 자세한 내용은 Android 포그라운드 서비스 가이드를 참조하세요.
저희 SDK는 두 가지 개발 방식을 지원합니다
- Begin-End 방식
포그라운드 서비스를 SDK 내부에 포함하여, 수면 측정과 관련된 모든 작업을 추상화했습니다.
개발자는 포그라운드 서비스를 앱에서 구현할 필요가 없고 beginSleepTracking() 및 endSleepTracking() 함수만 호출하여 간편하게 수면 측정 기능을 구현할 수 있습니다. Begin-End 방식 샘플 앱을 참고하세요.- SleepTrackingManager 방식
포그라운드 서비스를 직접 구현하여 더 많은 제어를 제공하는 방식입니다.
이 방식은 다소 복잡할 수 있으나, 슬립 스테이지(Sleep Stage)에 따라 하드웨어를 제어하거나 특정 커스텀 작업이 필요한 경우 적합합니다. FGS 프로세스 분리 샘플 앱을 참고하세요.
개발하려는 앱의 요구 사항에 따라 적합한 방식을 선택하세요.- 인앱 업데이트 기능 권장 인앱 업데이트 가이드
- 안드로이드 사용자 설정에 따라 수면측정 시작 후 앱 업데이트가 자동으로 이뤄지게 되면 의도치 않은 앱 종료로 수면 측정중 비정상 종료가 발생하게 됩니다. 이러한 상황을 방지하고자 미리 업데이트를 받을 수 있는 인앱 업데이트라는 기능을 사용하게 되면 의도치 않은 상황을 줄일 수 있습니다.
- 배터리 최적화 예외 권한 안내 doze-standby
- 수면 측정의 안정성을 보장하기 위해 배터리 최적화 예외 권한이 필요합니다.
이 권한은 수면 측정 중 Doze 모드로 전환되는 것을 방지하기 위해 사용되며, REQUEST_IGNORE_BATTERY_OPTIMIZATIONS 권한을 통해 설정됩니다.
Updated 9 months ago
Did this page help you?
