Setup
Call it after the app launches and before you start sleep tracking, and call Asleep.initAsleepConfig() after you receive onComplete().
Asleep.setup(context, apiKey, asleepSetupListener, productInfo) ← passes the authentication info and the device info
└ onComplete()
└ Asleep.initAsleepConfig(context, apiKey, userId, asleepConfigListener)
└ onSuccess(userId, asleepConfig)
└ createSleepTrackingManager → startSleepTracking
or beginSleepTracking
If you do not pass productInfo, it works exactly the same as before (3.2.0).
To use Product registration, you have to pass productInfo to setup.
Setup
Asleep.setup()
val productInfo = ProductInfo(
model = "MODEL_NAME",
identifierType = Asleep.ProductIdentifierType.SERIAL,
identifierValue = "SERIAL_NUMBER"
)
Asleep.setup(
context = applicationContext,
apiKey = "YOUR_API_KEY",
baseUrl = null,
callbackUrl = null,
service = null,
asleepSetupListener = object : Asleep.AsleepSetupListener {
override fun onComplete() { }
override fun onProgress(progress: Int) { }
override fun onFail(errorCode: Int, detail: String) { }
},
productInfo = productInfo
)| Parameter Name | Type | Description |
|---|---|---|
| context | Context | Enter ApplicationContext |
| apiKey | String | Enter the value issued by Generate API key |
| baseUrl | String? | If null, use the default server, enter the proxy server address |
| callbackUrl | String? | Enter the url of the server to receive sleep session analysis results |
| service | String? | your app name |
| asleepSetupListener | AsleepSetupListener? | listener to receive the setup result |
| productInfo | ProductInfo? | Device (Product) information. If you pass it, the device is registered during setup. See Product Registration below |
Token authentication
Instead of an API Key you can authenticate with app credentials (appId and appSecret). Every API after setup works the same way regardless of which method you use.
Asleep.setup(
context = applicationContext,
appId = "YOUR_APP_ID",
appSecret = "YOUR_APP_SECRET",
asleepSetupListener = asleepSetupListener,
productInfo = productInfo
)| Parameter | Type | Description |
|---|---|---|
| context | Context | Application context |
| appId | String | App ID issued from the dashboard |
| appSecret | String | App Secret issued from the dashboard |
| isTestEnvironment | Boolean? | Set to true only when using the test environment. Default null |
| baseUrl | String? | Uses the default server when null |
| callbackUrl | String? | Server URL to receive the sleep session analysis result |
| service | String? | Application name |
| asleepSetupListener | AsleepSetupListener? | Listener that receives the setup result |
| productInfo | ProductInfo? | Device (Product) information. See Product Registration below |
Differences from the API Key method
| Item | API Key | Token |
|---|---|---|
| Authentication header | x-api-key | Authorization: Bearer |
| Token refresh | None | Refreshed automatically by the SDK (5 minutes before expiry) |
| Authentication failure (401) | Error callback | Reissued automatically and retried |
| Credential storage | - | EncryptedSharedPreferences (AES256) |
onFail(11000)is called immediately whenappIdorappSecretis an empty string.- Both methods share the same re-entrancy guard. A Token setup is ignored while an API Key setup is in progress.
- Token failures are reported as
12000–12003. See the error codes below.
| Code | Name | Description |
|---|---|---|
| 12000 | ERR_TOKEN_ISSUE_FAILED | Failed to issue the token |
| 12001 | ERR_TOKEN_REFRESH_FAILED | Failed to refresh the token |
| 12002 | ERR_TOKEN_INVALID_CREDENTIALS | Invalid appId or appSecret |
| 12003 | ERR_TOKEN_NETWORK_ERROR | Network error during a token request |
Asleep.AsleepSetupListener
interface AsleepSetupListener {
fun onComplete()
fun onProgress(progress: Int)
fun onFail(errorCode: Int, detail: String)
}- onComplete() : It is called when setup is finished. If you passed
productInfo, it is called only after the device registration is finished. - onFail(errorCode, detail) : It is called when setup fails. In this case
onComplete()is not called.detailis a string for checking the cause (logging). Your app logic must branch onerrorCode.
- onProgress(progress) : It is not called during Product registration. You can leave it empty.
Call rules
| Case | Behavior |
|---|---|
Calling setup again while setup is in progress | It is ignored (e.g. W setup is already in progress; this call is ignored, no callback). Call it after you receive onComplete / onFail. Calling it inside the callback is fine |
Calling setup during sleep tracking | It is ignored (no callback). Call it after the tracking has ended |
apiKey is an empty string | onFail(11000) immediately |
baseUrl has an invalid format | onFail(11004) immediately |
Product Registration
Product registration is a feature that registers the device the SDK runs on with the Asleep server. Once registered, the server records which session was measured on which device.
- There is no separate API. The device is registered when you pass
productInfotosetup. - If the registration succeeds, the SDK stores the registration information on the device and automatically includes it in requests such as session creation and data upload from then on. There is no value for the app to handle.
- If you call
setupwithoutproductInfo, no registration request is sent.
ProductInfo
data class ProductInfo(
val model: String,
val identifierType: Asleep.ProductIdentifierType,
val identifierValue: String
)
enum class ProductIdentifierType { SERIAL, MAC_ADDRESS }| Parameter Name | Type | Description |
|---|---|---|
| model | String | Product model name (1~100 characters) |
| identifierType | ProductIdentifierType | The kind of value that identifies the device. SERIAL (serial number) or MAC_ADDRESS (MAC address) |
| identifierValue | String | Serial number or MAC address (1~255 characters) |
Please make sure of the following
- Use a value for
identifierValuethat is unique per device and does not change.- Always pass it in the same format. The SDK does not convert letter case, separators (
:/-) or leading and trailing spaces, and if the string differs even slightly it treats it as a different device and sends a new registration request.- An empty value, a value with only spaces, or a value that exceeds the length fails with
onFail(13400)without a server request.
How it works
If you pass productInfo, the device registration becomes a step of setup, and the remaining steps proceed only after the registration is finished.
Asleep.setup(context, apiKey, asleepSetupListener, productInfo)
│
├ ① Check the stored registration information
│ Already registered with the same API Key and the same productInfo → pass through without a registration request
│
├ ② Check the input values
│ model / identifierValue conditions violated → onFail(13400)
│
├ ③ Send a registration request to the server
│ Network error or server error → retry up to 3 times after 2, 4 and 8 seconds
│
└ ④ Success → (the remaining setup steps) → onComplete()
Failure → onFail(13000 or 13400)
| Case | Behavior |
|---|---|
| First run | It registers with the server and stores the registration information |
From the next run (same API Key, same productInfo) | It passes through without a registration request |
productInfo changed (e.g. the connected device changed) | It registers again with the new productInfo. If it succeeds, the sessions created after that are recorded with the new device |
| API Key changed | It deletes the existing registration information and registers again with the new API Key |
| Reinstalled after deleting the app | The stored registration information is deleted as well, so it registers again on the next setup |
Call setup with the same productInfo every time the app launches. From the second run it passes through without a registration request.
Time taken
Registration is a step that pauses and resumes setup, so the final callback is delayed when the network is in a bad state.
- A device that is already registered: it passes through without a registration request.
- First registration: it usually finishes with a single request.
- When the server does not respond and every retry is spent:
onFail(13000)is called after about 90 seconds with the API Key method, or after about 3 minutes with the Token method, which sends two requests per attempt (HTTP timeout 10 seconds, up to 4 attempts, backoff total 14 seconds). - A 4xx rejection is not retried, so it finishes within one round trip.
We recommend showing a loading screen right after the setup call.
When to start tracking
Which device a session was measured on is determined when the session is created.
- Always start tracking after you receive
onComplete(). - If you receive
onFail(13xxx), setup is not complete. Do not start the tracking. Solve the cause and callsetupagain. setupis ignored during sleep tracking. If the connected device has changed, callsetupwith the newproductInfoafter the tracking has ended.
Stored information
- The registration information is stored in EncryptedSharedPreferences dedicated to the SDK.
- The registration information (credential) is not exposed to the app, and the SDK attaches it to requests automatically.
Error codes
A registration failure is delivered through AsleepSetupListener.onFail(), and it is divided into two codes that the app has to handle differently.
| Code | Name | Meaning | What the app should do |
|---|---|---|---|
| 13000 | ERR_PRODUCT_REGISTER_FAILED | A temporary failure. Network error, server error (5xx), or too many requests (429). This is the result after the SDK has already retried | Guide the user about the network status and call setup again later |
| 13400 | ERR_PRODUCT_REGISTER_REJECTED | Rejected. Invalid input (400), authentication failure (401), no permission to register (403), or a client-side pre-validation failure. Retrying gives the same result | Check productInfo and the API Key |
detailis for checking the cause (logging) and its wording can change without notice.Branch your app logic on the code (
13000/13400).
Example
class SleepSdkController(private val context: Context) {
private val productInfo = ProductInfo(
model = "MODEL_NAME",
identifierType = Asleep.ProductIdentifierType.SERIAL,
identifierValue = deviceSerial
)
private val setupListener = object : Asleep.AsleepSetupListener {
override fun onComplete() {
// It is called only after the device registration is finished.
Asleep.initAsleepConfig(
context = context,
apiKey = "YOUR_API_KEY",
userId = userId,
asleepConfigListener = configListener
)
}
override fun onProgress(progress: Int) { }
override fun onFail(errorCode: Int, detail: String) {
when (errorCode) {
13000 -> {
// Temporary failure - check the network and call setup again after a while
}
13400 -> {
// Rejected - check productInfo / API Key (the result is the same if you try again)
}
}
}
}
private val configListener = object : Asleep.AsleepConfigListener {
override fun onSuccess(userId: String?, asleepConfig: AsleepConfig?) {
// Now you can start the tracking.
}
override fun onFail(errorCode: Int, detail: String) { }
}
fun start() {
Asleep.setup(
context = context.applicationContext,
apiKey = "YOUR_API_KEY",
asleepSetupListener = setupListener,
productInfo = productInfo
)
}
}Updated about 3 hours ago
