Android SDK μμνκΈ°
Requirements
Minimum requirements on AsleepTrack SDK for Android
- Android 7.0 (API level 24) νΉμ λ λμ λ²μ
- Java 1.8 νΉμ λ λμ λ²μ
- Android Gradle plugin 8.0 νΉμ λ λμ λ²μ
API Key
- AsleepTrack SDKλ₯Ό μ¬μ©νκΈ° μν΄μλ API keyκ° νμν©λλ€.
- API keyλ₯Ό λ°κΈνλ λ°©λ²μ λν΄μλ μ΄ λ§ν¬ API Key μμ±νκΈ°λ₯Ό μ°Έκ³ νμΈμ.
Getting Ready
Install AsleepTrack 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.0")
}
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 AsleepTrack 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)
AsleepTrack 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 about 1 month ago
Whatβs Next