Begin, End Sleep Tracking

수면 측정을 위해, 앱은 밤 동안 지속적으로 레코딩, 데이터 처리, 네트워크 작업 등을 수행해야 합니다. 그러나 안드로이드 OS는 밤 사이 도즈 모드(Doze Mode)에 진입하여, 마이크 및 네트워크 리소스를 비활성화하거나 실행 중인 프로세스를 중단하는 등 다양한 제약을 가할 수 있습니다. 이로 인해 수면 측정 프로세스가 중단되는 문제가 발생할 수 있습니다.
이러한 문제를 해결하기 위해, 일반적으로 개발자는 포그라운드 서비스(Foreground Service)를 사용해 작업이 분리된 프로세스로 구현해야 합니다. 하지만, 이 방식은 개발 난이도가 높고 구현 과정이 복잡할 수 있습니다.
이를 간소화하기 위해, 우리는 이러한 복잡한 작업을 SDK 내부에서 모두 처리하여 추상화하였습니다. 이제 개발자는 단순히 beginSleepTracking() 및 endSleepTracking() 메서드를 호출하기만 하면 수면 측정을 손쉽게 시작하고 종료할 수 있습니다. 이를 통해 개발자의 부담을 최소화하고 수면 측정 기능을 보다 빠르고 안정적으로 구현할 수 있도록 지원합니다.

📘

하드웨어 제어를 위한 추가 안내

단, 수면 중 슬립 스테이지(Sleep Stage) 값에 따라 하드웨어 제어가 반드시 보장되어야 하는 경우, SDK의 기본 제공 기능만으로는 제어에 한계가 있을 수 있습니다. 이러한 경우, 웹훅 서버(Webhook Server)를 활용한 제어를 구현하거나, 별도로 포그라운드 서비스(Foreground Service)를 직접 설계하여 수면 중단 없이 지속적으로 작업을 수행할 수 있도록 해야 합니다.

Begin SleepTracking

Asleep.beginSleepTracking()

  • 이 함수는 수면 측정을 시작하는 역할을 하고 다음과 같은 작업이 자동으로 수행됩니다.
    1. 포그라운드 서비스 실행: 포그라운드 서비스가 자동으로 시작되며, 백그라운드 작업이 안정적으로 유지됩니다.
    2. 알림(Notification) 표시: Android 시스템 정책에 따라 포그라운드 서비스가 실행되는 동안, 사용자에게 수면 측정이 진행 중임을 알리는 알림(Notification)이 상태바에 표시됩니다. 이 알림은 수면 측정의 진행 상태를 명확히 전달하며, 필요 시 사용자 상호작용을 지원할 수 있습니다.
    3. 수면 측정 시작: SleepTrackingManager를 통해 수면 측정 프로세스가 즉시 시작됩니다.
beginSleepTracking(
		asleepConfig: AsleepConfig,
  	notificationClass: Class<*>? = null,
  	notificationTitle: String? = null,
  	notificationText: String? = null,
  	notificationIcon: Int? = null,
  	asleepTrackingListener: AsleepTrackingListener
)
ParameterTypeDescription
asleepConfigAsleepConfiginitAsleepConfig를 통해 전달받은 값
notificationClassClass<*>?포그라운드 서비스 알림을 탭하였을 때 이동할 Activity
notificationTitleString?포그라운드 서비스 알림의 제목
notificationTextString?포그라운드 서비스 알림의 본문
notificationIconInt?포그라운드 서비스 알림의 아이콘 리소스 값
asleepTrackingListenerAsleep.AsleepTrackingListener수면 추적시 발생하는 콜백을 받을 리스너

AsleepNotificationConfig (v3.3.0)

알림 관련 파라미터 4개(notificationClass · notificationTitle · notificationText · notificationIcon)를 하나의 객체로 묶어 넘길 수 있습니다. 동작은 기존 방식과 같고, 넘기는 형태만 다릅니다.

beginSleepTracking(
    asleepConfig: AsleepConfig,
    notificationConfig: AsleepNotificationConfig?,
    asleepTrackingListener: AsleepTrackingListener
)
val notificationConfig = AsleepNotificationConfig.Builder()
    .setActivityClass(MainActivity::class.java)
    .setTitle("수면 측정 중")
    .setText("좋은 밤 되세요")
    .setSmallIcon(R.drawable.ic_sleep)
    .build()

Asleep.beginSleepTracking(
    asleepConfig = asleepConfig,
    notificationConfig = notificationConfig,
    asleepTrackingListener = asleepTrackingListener
)
Builder 메서드대응하는 기존 파라미터기본값
setActivityClass(cls)notificationClass없음 (알림을 탭해도 이동하지 않음)
setTitle(title)notificationTitle"Sleep Tracking"
setText(text)notificationText"Good night!"
setSmallIcon(resId)notificationIcon시스템 기본 아이콘
  • notificationConfignull 을 넘기면 모든 값이 기본값으로 적용됩니다.
  • 기존 파라미터 4개를 그대로 넘기는 방식도 계속 동작합니다. 둘 중 편한 쪽을 쓰면 됩니다.
  • CompletableAsleepTrackingListener 와도 함께 쓸 수 있습니다.
Asleep.beginSleepTracking(
    asleepConfig = asleepConfig,
    notificationConfig = notificationConfig,
    completableAsleepTrackingListener = completableListener,
    recordingPath = recordingPath,
    recordingType = RecordingType.ALL
)
📘

AsleepNotificationConfigParcelable 이라 포그라운드 서비스로 그대로 전달됩니다.

별도로 다룰 것은 없습니다.

Asleep.AsleepTrackingListener

  • 수면 측정의 시작과 종료 및 상태에 대한 콜백을 제공하는 인터페이스 입니다.
interface AsleepTrackingListener {
  	fun onStart(sessionId: String)
  	fun onPerform(sequence: Int)
  	fun onFinish(sessionId: String?)
  	fun onFail(errorCode: Int, detail: String)
}
FunctionParameterTypeDescription
onStartsessionIdString측정이 시작되었을때 호출되고 측정하고 있는 세션에 대한 id가 전달됩니다.
onPerformsequenceInt30초마다 한번씩 분석을 진행하며 진행 상태에 대한 시퀀스값이 0부터 전달됩니다.
onFinishsessionIdString측정이 종료 되었을때 호출되고 측정이 종료된 세션에 대한 id가 전달됩니다.
onFailerrorCodeInt측정 시작에서 종료까지의 과정중 에러가 발생하면 errorCode가 전달됩니다.
detailStringerrorCode에 대한 부가설명

에러코드에 따른 종료 여부

다음과 같은 에러가 onFail()의 errorCode로 콜백되면 더이상 수면 측정을 할 수 없다고 판단하여 수면 측정이 자동으로 종료되어 onFinish()가 콜백 됩니다.

ERR_AUDIO, ERR_CREATE_FAILED, ERR_CREATE_UNAUTHORIZED, ERR_CREATE_CONFLICT, ERR_CREATE_VALIDATION, ERR_CREATE_SERVER_ERROR, ERR_UPLOAD_TRACKING_TERMINATED, ERR_CLOSE_FAILED, ERR_CLOSE_BAD_REQUEST, ERR_CLOSE_UNAUTHORIZED, ERR_CLOSE_FORBIDDEN, ERR_CLOSE_NOT_FOUND, ERR_CLOSE_SERVER_ERROR

위의 에러가 아닌 다른 에러는 일시적으로 정상적인 측정이 될 수 없을지라도 측정이 종료 되지는 않습니다.

ERR_AUDIO_SILENCED, ERR_AUDIO_UNSILENCED, ERR_UPLOAD_FAILED


분석 완료 알림 · 녹음 파일 저장 (v3.3.0)

CompletableAsleepTrackingListener 를 넘기면 측정 종료 후 서버 분석이 끝났을 때 onComplete 가 호출됩니다. 코골이 · 호흡 불안정 구간의 녹음 파일을 저장하는 선택 파라미터(recordingPath, recordingType)도 함께 사용할 수 있습니다.

val notificationConfig = AsleepNotificationConfig.Builder()
    .setActivityClass(MainActivity::class.java)
    .setTitle("수면 추적 중")
    .setText("좋은 밤 되세요")
    .build()

val recordingPath = context.getExternalFilesDir(null)?.absolutePath + "/recordings"

Asleep.beginSleepTracking(
    asleepConfig = asleepConfig,
    notificationConfig = notificationConfig,
    completableAsleepTrackingListener = object : Asleep.CompletableAsleepTrackingListener {
        override fun onStart(sessionId: String) { }
        override fun onPerform(sequence: Int) { }
        override fun onFinish(sessionId: String?) { }
        override fun onComplete(session: Session?) { }
        override fun onFail(errorCode: Int, detail: String) { }
    },
    recordingPath = recordingPath,
    recordingType = RecordingType.ALL
)
ParameterTypeDescription
completableAsleepTrackingListenerCompletableAsleepTrackingListener측정 이벤트와 분석 완료 알림을 받을 리스너
recordingPathString?녹음 파일을 저장할 경로. 생략하거나 null 이면 녹음 파일을 만들지 않습니다. 기본값 null
recordingTypeRecordingType남길 녹음 종류. recordingPath 가 있을 때만 적용됩니다. 기본값 ALL
🚧

recordingPath / recordingTypeCompletable 리스너 오버로드에만 있습니다. 기존 AsleepTrackingListener 와 함께 넘기면 onFail(11009) 로 거부됩니다.

Asleep.CompletableAsleepTrackingListener

interface CompletableAsleepTrackingListener {
    fun onStart(sessionId: String)
    fun onPerform(sequence: Int)
    fun onFinish(sessionId: String?)
    fun onComplete(session: Session?)
    fun onFail(errorCode: Int, detail: String)
}
  • onComplete(session) — 측정 종료 후 서버 분석이 끝나 결과를 조회할 수 있을 때 호출됩니다.
  • 그 외 onStart, onPerform, onFinish, onFail 은 기존 AsleepTrackingListener 와 같습니다.

콜백 흐름

[AsleepTrackingListener (기존)]
onStart → onPerform(0) → onPerform(1) → … → onFinish

[CompletableAsleepTrackingListener]
onStart → onPerform(0) → … → onFinish → onComplete 또는 onFail(28000)

분석 완료 확인은 종료 후 3초 간격으로 최대 10회(약 30초) 진행됩니다.

📘

ERR_COMPLETE_TIMEOUT(28000)은 측정 실패가 아닙니다. 세션은 이미 정상 종료(onFinish)되었고, 분석이 30초 안에 끝나지 않았다는 뜻입니다. 잠시 후 Reports.getReport(sessionId) 로 결과를 조회하세요.

녹음 파일의 저장 위치와 개수, RecordingType, Asleep.createRecordingFileManager() 사용법은 SleepTrackingManager 페이지의 "녹음 파일 저장" 섹션과 같습니다.



Asleep.getCurrentSleepData()

  • 현재까지 측정된 실시간 수면 데이터를 받아옵니다.
Asleep.getCurrentSleepData(asleepSleepDataListener = object: Asleep.AsleepSleepDataListener {
  	override fun onSleepDataReceived(session: Session) {
  	}
  	override fun onFail(errorCode: Int, detail: String) {
  	}
})

Asleep.AsleepSleepDataListener

  • 성공시, onSleepDataReceived 함수를 통해 Session의 값을 받아옵니다.
  • 실패시, onFail 함수를 통해 errorCode를 받아옵니다.
interface AsleepSleepDataListener {
  	fun onSleepDataReceived(session: Session)
		fun onFail(errorCode: Int, detail: String)
}

Asleep.isSleepTrackingAlive()

  • 이 함수는 현재 수면 측정이 진행 중인지를 확인하는 역할을 합니다. 포그라운드 서비스(Foreground Service)가 실행 중인 경우, true를 반환합니다.
  • 앱이 실행될 때 이 함수를 호출하여 true가 반환되면, 현재 수면 측정이 진행 중임을 의미합니다. 이 경우, 사용자는 측정 상태를 직관적으로 알 수 있도록 수면 측정 중임을 나타내는 UI를 화면에 표시해야 합니다.
  • 포그라운드 서비스가 강제 종료된 후 앱을 재시작하였을 때 이 함수를 호출하는 것으로 SDK 내부의 측정 상태를 초기 상태로 변경할 수 있으므로 앱 시작 시 필히 이 함수를 이용하여 현재 측정 중인지를 확인하여야 합니다.
Asleep.isSleepTrackingAlive(context: Context)

Asleep.connectSleepTracking()

  • isSleepTrackingAlive()이 true를 반환할 경우, 수면 측정이 정상적으로 진행 중임을 의미합니다. 이때, AsleepTrackingListener를 다시 등록하여 수면 측정 상태에 대한 이벤트 및 데이터를 수신할 수 있도록 구현해야 합니다. 이를 통해 수면 측정 프로세스와 UI 간의 상태 동기화를 유지할 수 있습니다.
Asleep.connectSleepTracking(asleepTrackingListener: AsleepBeginEndTrackingListener)

End SleepTracking

Asleep.endSleepTracking()

이 함수는 beginSleepTracking()으로 시작된 수면 측정을 종료하는 역할을 합니다. 이 함수를 호출하면 수면 측정이 중단됨과 동시에 포그라운드 서비스(Foreground Service)도 종료되어, 수면 추적과 관련된 모든 프로세스가 안전하고 완전하게 종료됩니다.

Asleep.endSleepTracking()

분석 구간 지정 (v3.3.0)

측정을 종료할 때 서버가 분석할 구간(시작 · 종료 시각) 을 직접 지정할 수 있습니다. 예를 들어 사용자가 입력한 "잠든 시각 ~ 일어난 시각"만 분석할 때 사용합니다.

// 측정 전체 분석 (기존)
Asleep.endSleepTracking()

// 지정한 구간만 분석
Asleep.endSleepTracking(analysisStartTime, analysisEndTime)
ParameterTypeDescription
analysisStartTimeDate분석 시작 시각
analysisEndTimeDate분석 종료 시각. analysisStartTime 보다 늦어야 합니다
  • 두 값은 항상 함께 넘깁니다. 구간 없이 종료하려면 Asleep.endSleepTracking() 을 호출하세요.
  • 시작 시각이 종료 시각보다 늦거나 같으면 서버 요청 없이 onFail(11009) 를 호출한 뒤 구간 없이 세션을 종료합니다.
  • 서버가 구간을 거부(400)하면 SDK 가 구간 없이 다시 종료를 요청합니다. 성공하면 정상 흐름으로 진행되며 앱에는 별도로 알리지 않습니다.
  • 구간을 지정하면 Session.startTime / endTime분석 구간의 시각이 되고, stage 배열도 그 구간만큼만 내려옵니다. 분석한 구간 정보는 Reports 페이지의 Report.analysis 로 확인하세요.

📘

Begin, End 방식의 Sleep Tracking에 대한 Sample App 을 참고하세요.


Did this page help you?