Get Started

🚧

수면 측정 시 안내 사항을 따라주시기 바랍니다.

AsleepTrack의 수면 측정/분석 기능을 정확하게 테스트하려면, 
테스트 환경 가이드를 반드시 따라주시기 바랍니다. 이 가이드를 준수하지 않은 환경에서 얻은 수면 분석 결과는 
실제 수면 패턴과 정확하게 일치하지 않을 수 있음을 유의해주세요.

  • 수면 측정은 최소 20분 이상의 오디오가 업로드 되어야 분석이 시작되며, ê·¸ 이후로는 플랜(계약 ì¡°ê±´)에 따라 5분 또는 20분 간격으로 분석합니다.
    🔗 Test Environment Guideline 확인하기
  • AsleepTrack의 수면 측정/분석 기능을 확인해 ë³¼ 수 있는 대한 샘플 코드를 제공합니다.
    🔗 Sample App 확인하기
  • Android SDK를 이용한 수면 모니터링 앱을 사용할 때 다른 녹음/녹화 앱과 같이 실행 중이면 수면 측정이 정상적으로 작동하지 않습니다.
    • OS version 9 이하 에서는 오직 한 개의 앱에서만 Audio 녹음 기능을 제공하며, 먼저 실행된 앱에서만 독점이 가능하고 다른 앱에서는 Audio 녹음 실행시 에러가 발생합니다.
    • OS version 10 이상에서는 두 개 이상의 Audio 녹음앱 실행시 가장 나중에 실행된 Audio 관련된 앱에서 정상적으로 녹음이 되고 이전에 실행된 앱들은 Silence 처리되어 수면 모니터링 분석시 정상적인 결과를 얻을 수가 없습니다.
      Android Developer Site

📘

인앱 업데이트

앱 사용자 설정에 따라 앱 자동 업데이트가 이뤄질 수 있습니다. 수면측정 시작 후 앱 업데이트가 자동으로 이뤄지게 되면 의도치 않은 앱 종료로 수면 측정중 비정상 종료가 발생하게 됩니다.
이러한 상황을 미연에 방지하고자 미리 업데이트를 받을 수 있는 인앱 업데이트라는 기능을 사용하게 되면 의도치 않은 상황을 줄일 수 있습니다.

🔗 인앱 업데이트 가이드


1. Requirements

1.1 Minimum requirements on AsleepTrack SDK for Android

🚧

  • Android 8.0 (API level 26) 혹은 더 높은 버전
  • Java 1.8 혹은 더 높은 버전
  • Android Gradle plugin 8.0 혹은 더 높은 버전

1.2 API Key

  • AsleepTrack SDK를 사용하기 위해서는 API key가 필요합니다.
  • API key를 발급하는 방법에 대해서는 이 링크 Generate API key를 참고하세요.

2. Getting Ready

2.1 Install AsleepTrack SDK and Settings

  1. Android Studio를 이용하여 프로젝트를 생성합니다.
  2. 생성된 프로젝트 폴더의 [root]/app/libs 폴더에 AsleepSDK.aar 파일을 추가합니다.
  3. AndroidManifest.xml 파일을 열어 퍼미션을 추가합니다.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <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"/>
		...
    

📘

FOREGROUND_SERVICE 권한은 앱 개발시 필요합니다.

개발할 앱이 밤 중에 끊김없이 수면을 측정하게 하려면 FOREGROUND_SERVICE로 SDK를 사용하여야 합니다.

https://developer.android.com/guide/components/foreground-services

앱에서 Asleep SDK를 적용할 때, Google 라이브러리(gms, chrome)의 업데이트로 인해 수면 측정 중 의도치 않게 앱이 강제로 종료되는 현상을 방지하기 위해 foreground service의 process를 분리하는 작업이 필요합니다.

이에 대한 FGS 프로세스가 분리된 샘플 앱의 코드를 참고하시기 바랍니다.

📘

REQUEST_IGNORE_BATTERY_OPTIMIZATIONS 권한은 안정적인 수면측정을 위해 필요합니다.

도즈 모드에 빠지는 것을 방지하기 위해 해당 권한이 필요합니다.

https://developer.android.com/training/monitoring-device-state/doze-standby

  1. 앱 수준의 build.gradle 파일을 열어 okhttp, gson 및 libs 폴더의 *.aar을 추가합니다.
plugins {
  ...
}

android {
	...
}

dependencies {
		...
    implementation 'com.squareup.okhttp3:okhttp:4.11.0'
    implementation 'com.google.code.gson:gson:2.10'
    implementation fileTree(dir: 'libs', include: ['*.aar', '*.jar'], exclude: [])
}
  1. 마이크 녹음 기능과 FGS의 notification을 위한 권한 소스코드를 작성합니다.
ActivityCompat.requestPermissions(requireActivity(), 
                                  arrayOf(android.Manifest.permission.RECORD_AUDIO, 
                                          android.Manifest.permission.POST_NOTIFICATIONS), 
                                  0)

3. Sleep Tracking with AsleepTrack SDK

3.1 Step 1: Initialize the AsleepTrack SDK

  • 1.2에서 발급받은 apiKey를 입력합니다.
  • userId가 null이면 새로운 userId가 생성됩니다.
  • baseUrl에는 프록시 서버의 url 입력하세요. null이면 default base url이 사용됩니다.
  • callbackUrl은 분석 결과를 직접 받는 서버의 url을 입력하세요. null이면 콜백이 없습니다.
  • service는 개발할 앱의 닉네임이 있다면 입력하세요.
import ai.asleep.asleepsdk.Asleep
import ai.asleep.asleepsdk.data.AsleepConfig
import ai.asleep.asleepsdk.AsleepErrorCode

...

Asleep.initAsleepConfig(  
    context = applicationContext,  
    apiKey = "[input your apiKey]",  
    userId = null,  
    baseUrl = null,  
    callbackUrl = null,  
    service = "[input your AppName]",  
    object : Asleep.AsleepConfigListener {  
        override fun onSuccess(userId: String?, asleepConfig: AsleepConfig?) {  
						...
            /* save userId and asleepConfig */
  
        }
    override fun onFail(errorCode: Int, detail: String) {
        ...
    }
})

3.2 Step 2: Create SleepTrackingManager

  • initAsleepConfig에서 받아온 AsleepConfig를 파라메터로 입력합니다.
import ai.asleep.asleepsdk.tracking.SleepTrackingManager

...

var sleepTrackingManager = Asleep.createSleepTrackingManager(asleepConfig, object : SleepTrackingManager.TrackingListener {                           
    override fun onCreate() {
    }

    override fun onUpload(sequence: Int) {
    }
    
    override fun onClose(sessionId: String) {
        ...
        /* save sessionId */
    }
    
    override fun onFail(errorCode: Int, detail: String) {
    }
})

3.3 Step 3: Start Tracking

  1. 측정 시작하기
  • 시작을 하면 SleepTrackingManager 생성 시 등록한 리스너의 onUpload 함수에서 30초마다 시퀀스 값이 콜백됩니다.
sleepTrackingManager?.startSleepTracking()
  1. 측정 중 분석하기
  • session에 대한 정보는 session data type 참조하세요.
sleepTrackingManager?.requestAnalysis(object : SleepTrackingManager.AnalysisListener {  
    override fun onSuccess(session: Session) {  
        Log.d("", "${session.toString()}")  
    }
}

3.4 Step 4: Stop Tracking

  • 정지를 하면 SleepTrackingManager 생성 시 등록한 리스너의 onClose함수에서 sessionId가 콜백됩니다.
sleepTrackingManager?.stopSleepTracking()

3.5 Step 5: Create Reports

  • initAsleepConfig에서 받아온 AsleepConfig를 파라메터로 입력합니다.
val reports = Asleep.createReports(asleepConfig)

3.6 Step 6: Get Report

  1. sessionId 하나의 결과 받아오기
  • sleepTracking을 정지했을 때 받아온 sessionId를 파라메터로 입력합니다.
reports?.getReport(sessionId, object : Reports.ReportListener {
    override fun onSuccess(report: Report?) {
    }

    override fun onFail(errorCode: Int, detail: String) {
    }
})
  1. 날짜로 결과 받아오기
val today = LocalDate.now()
reports?.getReports(today.minusDays(7).toString(), today.toString(), "DESC", 0, 20, object : Reports.ReportsListener {
    override fun onSuccess(reports: List<SleepSession>?) {
    }

    override fun onFail(errorCode: Int, detail: String) {
    }
})

3.7 Step 7: Remove Session

  1. 측정 기록 삭제하기
  • sessionId를 입력하여 측정 기록을 삭제합니다.
reports?.deleteReport(sessionId, object : Reports.DeleteReportListener {
    override fun onSuccess(sessionId: String?) {
    }

    override fun onFail(errorCode: Int, detail: String) {
    }
})
  1. 나의 정보 전부 삭제하기
  • userId와 측정된 기록을 전부 삭제합니다. 삭제된 userId는 더 이상 사용할 수 없습니다.
Asleep.deleteUser(object : Asleep.DeleteUserIdListener {
    override fun onSuccess(userId: String?) {
    }

    override fun onFail(errorCode: Int, detail: String) {
    }
})

3.8 Step 8: Continue Session

  • v2.3.0 이상부터 사용 가능

안드로이드 OS에서는 Google Play 서비스 패키지가 업데이트될 때가 있는데, 이때 동작 중인 앱의 foreground service가 시스템에 의해 강제로 종료 후 재시작 됩니다. 이때 sleepTrackingManager의 동작을 이어할 수 있는 기능을 제공합니다.

우선, foreground service가 시스템에 의해 재시작되면 LifecycleService()의 onStartCommand 함수가 호출이 됩니다.

이때, Asleep.hasUnfinishedSession 함수를 이용하여 종료되지 않은 세션이 존재한다면, AsleepSDK내부에 저장된 AsleepConfig를 가져와 sleepTrackingManager를 다시 생성하고 startSleepTracking을 호출하여 tracking을 이어할 수 있습니다.

private var asleepConfig: AsleepConfig? = null
private var sleepTrackingManager: SleepTrackingManager? = null
...
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { 
  super.onStartCommand(intent, flags, startId)

	if(Asleep.hasUnfinishedSession(applicationContext)) {
    asleepConfig = Asleep.getSavedAsleepConfig(applicationContext, BuildConfig.ASLEEP_API_KEY)
    sleepTrackingManager = Asleep.createSleepTrackingManager(asleepConfig, object : SleepTrackingManager.TrackingListener {
			override fun onCreate() {
        ...
      }
      override fun onUpload(sequence: Int) {
      	...
      }
      override fun onClose(sessionId: String) {
      	...
      }
      override fun onFail(errorCode: Int, detail: String) {
      	...
      }
    }
    ...
    sleepTrackingManager?.startSleepTracking()
  }
  ...
}