Dashboard Sign InKR

Get Started

Requirements

🚧

Minimum requirements on AsleepTrack SDK for Android

  • Android 7.0 (API level 24) or higher
  • Java 1.8 or higher
  • Android Gradle plugin 8.0 or higher

API Key

  • The API key is required to use the Asleep Track SDK.
  • For how to issue an API key, see this link [Generate API key]

Getting Ready

Install AsleepTrack SDK and Settings

  1. Create a project using Android Studio.
  2. Open the AndroidManifest.xml file to add permissions.
<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>
    
  1. Open the app-level build.gradle file and add lifecycle-service, okhttp, gson, and 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

Permission Acquisition

  • Acquire the required permissions: RECORD_AUDIO and POST_NOTIFICATIONS (for Android 13 and above).
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

  • Create buttons for Init, Begin, End, and Report to be displayed on the screen.

<?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>
  • Declare the buttons as variables.
    ...
    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 Initialization

  • Replace [YOUR API KEY] in apiKey with the actual issued API Key.
  • If userId is null, the SDK will generate a new userId.
  • In a real app implementation, the generated userId should be stored and retrieved as needed.
  • service: If the app has a specific service name, enter it here.
  • asleepConfigListener: Provides a callback for initialization success or failure.
    • On success, userId and asleepConfig are returned.
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

  • Start sleep tracking.
    1. Pass the asleepConfig generated from initAsleepConfig and the asleepTrackingListener to monitor the sleep tracking status.
    2. When tracking begins, the onStart() callback is triggered.
    3. The onPerform() callback is called every 30 seconds to provide progress updates.
    4. When tracking ends, the onFinish() callback is triggered.
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

  • End sleep tracking.
btnEnd.setOnClickListener {
  Asleep.endSleepTracking()
}

Get Report

  • Retrieve the recorded sleep data.
    1. Create a Reports object by passing the asleepConfig generated from initAsleepConfig.
    2. Provide the sessionId that was created during sleep tracking.
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 Verification

  • If the logcat logs show that userId, sessionId, and report have been successfully created as shown below, the SDK is functioning correctly.


📘

Important Considerations for App Development

  • Using Foreground Service
    For sleep tracking, the app must continuously record, process data, and perform network operations throughout the night.
    To prevent interruptions, it is essential to implement a Foreground Service in your app.
    Refer to the Android Foreground Service Guide for more details.

    Our SDK supports two development approaches:

    1. Begin-End Method
      • The foreground service is built into the SDK, abstracting all sleep tracking operations.
      • Developers do not need to implement a foreground service in the app.
      • Simply call beginSleepTracking() and endSleepTracking() to implement sleep tracking easily.
      • Refer to the Begin-End Sample App.
    2. SleepTrackingManager Method
      • This approach provides more control by allowing developers to implement the foreground service directly.
      • While it is more complex, it is useful for controlling hardware based on sleep stages or implementing custom actions.
      • Refer to the FGS Process Separation Sample App.
      • Choose the method that best fits your app’s requirements.
  • Recommended: In-App Update Feature

    • In-App Update Guide
    • If an Android app update occurs automatically after sleep tracking starts, the app may close unexpectedly, causing an abnormal session termination.
    • To avoid this, use In-App Updates, which allow users to update the app in advance, preventing unintended interruptions.
  • Battery Optimization Exception

    • Doze-Standby Guide
    • To ensure stable sleep tracking, battery optimization exceptions are required.
    • This prevents the device from entering Doze Mode during sleep tracking.
    • The permission is set using REQUEST_IGNORE_BATTERY_OPTIMIZATIONS.