Begin and End Sleep Tracking
For sleep tracking, the app must continuously perform recording, data processing, and network operations throughout the night. However, the Android OS may enter Doze Mode, which can disable microphone and network resources or suspend running processes, imposing various restrictions. As a result, the sleep tracking process may be interrupted.
To address this issue, developers typically use a Foreground Service to separate tasks into a persistent process. However, this approach can be complex and challenging to implement.
To simplify this process, we have abstracted all these complexities within the SDK. Now, developers can easily start and stop sleep tracking by simply calling beginSleepTracking() and endSleepTracking(). This reduces the development burden and enables a faster and more stable implementation of sleep tracking functionality.
Additional Guidance for Hardware ControlIf hardware control must be guaranteed based on Sleep Stage values during sleep, the built-in SDK functionality may have limitations.
In such cases, you should either:
- Implement control using a Webhook Server.
- Design a custom Foreground Service to ensure uninterrupted operation throughout the night.
Begin SleepTracking
Asleep.beginSleepTracking()
-
This function starts the sleep tracking process, and the following tasks are performed automatically:
- Foreground Service Execution: The Foreground Service starts automatically, ensuring background tasks remain stable.
- Notification Display:
- According to Android system policies, a notification will be displayed in the status bar while the foreground service is running.
- This notification informs the user that sleep tracking is in progress and can support user interaction if needed.
- Start Sleep Tracking:
- The SleepTrackingManager immediately begins the sleep tracking process.
beginSleepTracking(
asleepConfig: AsleepConfig,
notificationClass: Class<*>? = null,
notificationTitle: String? = null,
notificationText: String? = null,
notificationIcon: Int? = null,
asleepTrackingListener: AsleepTrackingListener
)
| Parameter | Type | Description |
|---|---|---|
| asleepConfig | AsleepConfig | Value received from initAsleepConfig. |
| notificationClass | Class<*>? | Activity to open when tapping the foreground service notification. |
| notificationTitle | String? | Title of the foreground service notification. |
| notificationText | String? | Body text of the foreground service notification. |
| notificationIcon | Int? | Icon resource for the foreground service notification. |
| asleepTrackingListener | Asleep.AsleepTrackingListener | Listener to receive callbacks during sleep tracking |
AsleepNotificationConfig (v3.3.0)
AsleepNotificationConfig (v3.3.0)The four notification parameters (notificationClass · notificationTitle · notificationText · notificationIcon) can be passed bundled into a single object. The behavior is the same as before, only the form in which they are passed is different.
beginSleepTracking(
asleepConfig: AsleepConfig,
notificationConfig: AsleepNotificationConfig?,
asleepTrackingListener: AsleepTrackingListener
)val notificationConfig = AsleepNotificationConfig.Builder()
.setActivityClass(MainActivity::class.java)
.setTitle("Sleep Tracking")
.setText("Good night!")
.setSmallIcon(R.drawable.ic_sleep)
.build()
Asleep.beginSleepTracking(
asleepConfig = asleepConfig,
notificationConfig = notificationConfig,
asleepTrackingListener = asleepTrackingListener
)| Builder method | Matching existing parameter | Default value |
|---|---|---|
setActivityClass(cls) | notificationClass | None (tapping the notification does not navigate) |
setTitle(title) | notificationTitle | "Sleep Tracking" |
setText(text) | notificationText | "Good night!" |
setSmallIcon(resId) | notificationIcon | The system default icon |
- If you pass
nulltonotificationConfig, every value is applied as its default. - Passing the four existing parameters as before keeps working. Use whichever is more convenient.
- It can also be used together with
CompletableAsleepTrackingListener.
Asleep.beginSleepTracking(
asleepConfig = asleepConfig,
notificationConfig = notificationConfig,
completableAsleepTrackingListener = completableListener,
recordingPath = recordingPath,
recordingType = RecordingType.ALL
)
AsleepNotificationConfigisParcelable, so it is passed to the foreground service as it is.There is nothing else to handle.
Asleep.AsleepTrackingListener
- An interface that provides callbacks for the start, end, and status of sleep tracking.
interface AsleepTrackingListener {
fun onStart(sessionId: String)
fun onPerform(sequence: Int)
fun onFinish(sessionId: String?)
fun onFail(errorCode: Int, detail: String)
}| Function | Parameter | Type | Description |
|---|---|---|---|
| onStart | sessionId | String | Called when sleep tracking starts, providing the session ID. |
| onPerform | sequence | Int | Called every 30 seconds during analysis, providing a sequence value starting from 0. |
| onFinish | sessionId | String | Called when sleep tracking ends, providing the session ID of the completed session. |
| onFail | errorCode | Int | Called if an error occurs during the sleep tracking process, returning an errorCode. |
| detail | String | Additional description related to the errorCode. |
Termination Based on Error Codes
If the following errors are returned in the errorCode parameter of onFail(), sleep tracking is considered unable to continue and will automatically terminate, triggering the onFinish() callback.
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
For other errors, sleep tracking will not be terminated, even if temporary issues prevent proper measurement:
ERR_AUDIO_SILENCED, ERR_AUDIO_UNSILENCED, ERR_UPLOAD_FAILED
Analysis complete notification · saving recording files (v3.3.0)
If you pass a CompletableAsleepTrackingListener, onComplete is called when the server analysis is finished after tracking is stopped. The optional parameters (recordingPath, recordingType) for saving the recording files of snoring · unstable-breathing sections can be used together with it.
val notificationConfig = AsleepNotificationConfig.Builder()
.setActivityClass(MainActivity::class.java)
.setTitle("Sleep Tracking")
.setText("Good night!")
.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
)| Parameter | Type | Description |
|---|---|---|
completableAsleepTrackingListener | CompletableAsleepTrackingListener | Listener to receive tracking events and the analysis complete notification |
recordingPath | String? | Path to save the recording files. If omitted or null, no recording file is created. Default null |
recordingType | RecordingType | Type of recording to keep. Applied only when recordingPath is set. Default ALL |
recordingPath/recordingTypeare available only on the Completable listener overload. If you pass them together with the existingAsleepTrackingListener, they are rejected withonFail(11009).
Asleep.CompletableAsleepTrackingListener
Asleep.CompletableAsleepTrackingListenerinterface 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) — Called when the server analysis is finished after tracking is stopped and the result can be retrieved.
- The other callbacks,
onStart,onPerform,onFinishandonFail, are the same as in the existingAsleepTrackingListener.
Callback flow
[AsleepTrackingListener (existing)]
onStart → onPerform(0) → onPerform(1) → … → onFinish
[CompletableAsleepTrackingListener]
onStart → onPerform(0) → … → onFinish → onComplete or onFail(28000)The check for analysis completion runs every 3 seconds after the session is stopped, up to 10 times (about 30 seconds).
ERR_COMPLETE_TIMEOUT(28000) is not a tracking failure. The session has already been closed normally (onFinish), and it only means that the analysis did not finish within 30 seconds. Retrieve the result withReports.getReport(sessionId)a little later.
The location and number of the recording files, RecordingType and how to use Asleep.createRecordingFileManager() are the same as in the "Saving recording files" section of the SleepTrackingManager page.
Asleep.getCurrentSleepData()
- Retrieves real-time sleep data measured so far.
Asleep.getCurrentSleepData(asleepSleepDataListener = object: Asleep.AsleepSleepDataListener {
override fun onSleepDataReceived(session: Session) {
}
override fun onFail(errorCode: Int, detail: String) {
}
})Asleep.AsleepSleepDataListener
- On success, retrieves the session values through the
onSleepDataReceived()function. - On failure, returns an
errorCodethrough theonFail()function.
interface AsleepSleepDataListener {
fun onSleepDataReceived(session: Session)
fun onFail(errorCode: Int, detail: String)
}Asleep.isSleepTrackingAlive()
- This function checks whether sleep tracking is currently in progress.
- If the Foreground Service is running, it returns
true. - When the app starts, calling this function will determine if sleep tracking is active.
- If
trueis returned, the app should display a UI indicator to inform the user that sleep tracking is in progress.
- If
Asleep.isSleepTrackingAlive(context: Context)Asleep.connectSleepTracking()
- If
isSleepTrackingAlive()returnstrue, it means sleep tracking is running normally. - In this case, re-register the
AsleepTrackingListenerto receive events and data related to the sleep tracking status. - This ensures synchronization between the sleep tracking process and the UI state.
Asleep.connectSleepTracking(asleepTrackingListener: AsleepBeginEndTrackingListener)End SleepTracking
Asleep.endSleepTracking()
This function stops the sleep tracking session started with beginSleepTracking().
- Calling this function immediately halts sleep tracking.
- The Foreground Service is also terminated, ensuring that all sleep tracking-related processes are safely and completely stopped.
Asleep.endSleepTracking()Specifying the analysis range (v3.3.0)
When you stop tracking, you can specify the range (start · end time) that the server will analyze yourself. For example, use it when you want to analyze only the "time the user fell asleep ~ time the user woke up" that the user entered.
// Analyze the whole tracking (existing)
Asleep.endSleepTracking()
// Analyze only the specified range
Asleep.endSleepTracking(analysisStartTime, analysisEndTime)| Parameter | Type | Description |
|---|---|---|
analysisStartTime | Date | Analysis start time |
analysisEndTime | Date | Analysis end time. It must be later than analysisStartTime |
- The two values are always passed together. To stop without a range, call
Asleep.endSleepTracking(). - If the start time is later than or the same as the end time,
onFail(11009)is called without a server request and then the session is closed without a range. - If the server rejects the range (400), the SDK requests the close again without the range. If it succeeds, the normal flow proceeds and the app is not notified separately.
- If a range is specified,
Session.startTime/endTimebecome the times of the analysis range, and the stage arrays are returned only for that range. Check the information about the analyzed range withReport.analysison the Reports page.
Refer to the Sample App for Sleep Tracking using the Begin-End method.
Updated 3 days ago
