Отслеживание сеансов сна

Это руководство совместимо с Health Connect версии 1.1.0-alpha11 .

Health Connect предоставляет тип данных «Сессия сна» для хранения информации о сне пользователя, например, о ночном или дневном сне. Для представления этих сеансов используется тип данных SleepSessionRecord .

Сеансы позволяют пользователям измерять производительность за определенный период времени, например, непрерывный пульс или данные о местоположении.

Сеансы SleepSessionRecord содержат данные, которые регистрируют фазы сна, такие как AWAKE , SLEEPING и DEEP .

Подтип данных — это данные, которые «принадлежат» сеансу и имеют смысл только при чтении в родительском сеансе. Например, стадия сна.

Проверьте доступность Health Connect

Прежде чем использовать Health Connect, ваше приложение должно проверить наличие Health Connect на устройстве пользователя. Health Connect может быть предустановлен не на всех устройствах или отключен. Проверить наличие Health Connect можно с помощью метода HealthConnectClient.getSdkStatus() .

Как проверить доступность Health Connect

fun checkHealthConnectAvailability(context: Context) {
    val providerPackageName = "com.google.android.apps.healthdata" // Or get from HealthConnectClient.DEFAULT_PROVIDER_PACKAGE_NAME
    val availabilityStatus = HealthConnectClient.getSdkStatus(context, providerPackageName)

    if (availabilityStatus == HealthConnectClient.SDK_UNAVAILABLE) {
      // Health Connect is not available. Guide the user to install/enable it.
      // For example, show a dialog.
      return // early return as there is no viable integration
    }
    if (availabilityStatus == HealthConnectClient.SDK_UNAVAILABLE_PROVIDER_UPDATE_REQUIRED) {
      // Health Connect is available but requires an update.
      // Optionally redirect to package installer to find a provider, for example:
      val uriString = "market://details?id=$providerPackageName&url=healthconnect%3A%2F%2Fonboarding"
      context.startActivity(
        Intent(Intent.ACTION_VIEW).apply {
          setPackage("com.android.vending")
          data = Uri.parse(uriString)
          putExtra("overlay", true)
          putExtra("callerId", context.packageName)
        }
      )
      return
    }
    // Health Connect is available, obtain a HealthConnectClient instance
    val healthConnectClient = HealthConnectClient.getOrCreate(context)
    // Issue operations with healthConnectClient
}

В зависимости от статуса, возвращаемого getSdkStatus() , вы можете предложить пользователю установить или обновить Health Connect из Google Play Store, если это необходимо.

Доступность функций

Для этого типа данных нет флага доступности функций.

Требуемые разрешения

Доступ к сеансу сна защищен следующими разрешениями:

  • android.permission.health.READ_SLEEP
  • android.permission.health.WRITE_SLEEP

Чтобы добавить в свое приложение возможность сеанса сна, начните с запроса разрешений на запись для типа данных SleepSession .

Вот разрешение, которое вам необходимо объявить, чтобы иметь возможность записывать сеанс сна:

<application>
  <uses-permission
android:name="android.permission.health.WRITE_SLEEP" />
...
</application>

Для чтения сеанса сна вам необходимо запросить следующие разрешения:

<application>
  <uses-permission
android:name="android.permission.health.READ_SLEEP" />
...
</application>

Запросить разрешения у пользователя

После создания клиентского экземпляра ваше приложение должно запрашивать разрешения у пользователя. Пользователи должны иметь возможность предоставлять или отклонять разрешения в любое время.

Для этого создайте набор разрешений для необходимых типов данных. Убедитесь, что разрешения в наборе предварительно объявлены в манифесте Android.

// Create a set of permissions for required data types
val PERMISSIONS =
    setOf(
  HealthPermission.getReadPermission(SleepSessionRecord::class),
  HealthPermission.getWritePermission(SleepSessionRecord::class)
)

Используйте getGrantedPermissions , чтобы проверить, предоставлены ли приложению необходимые разрешения. Если нет, запросите их с помощью createRequestPermissionResultContract . Откроется экран разрешений Health Connect.

// Create the permissions launcher
val requestPermissionActivityContract = PermissionController.createRequestPermissionResultContract()

val requestPermissions = registerForActivityResult(requestPermissionActivityContract) { granted ->
  if (granted.containsAll(PERMISSIONS)) {
    // Permissions successfully granted
  } else {
    // Lack of required permissions
  }
}

suspend fun checkPermissionsAndRun(healthConnectClient: HealthConnectClient) {
  val granted = healthConnectClient.permissionController.getGrantedPermissions()
  if (granted.containsAll(PERMISSIONS)) {
    // Permissions already granted; proceed with inserting or reading data
  } else {
    requestPermissions.launch(PERMISSIONS)
  }
}

Поскольку пользователи могут предоставлять или отзывать разрешения в любое время, ваше приложение должно периодически проверять наличие предоставленных разрешений и обрабатывать ситуации, когда разрешение теряется.

Поддерживаемые агрегации

Для SleepSessionRecord доступны следующие агрегированные значения:

Общие рекомендации

Ниже приведены некоторые рекомендации по работе с сеансами сна в Health Connect.

  • Сеансы следует использовать для добавления данных из определенного сеанса сна, например:
suspend fun writeSleepSession(healthConnectClient: HealthConnectClient) {
    healthConnectClient.insertRecords(
        listOf(
            SleepSessionRecord(
                startTime = Instant.parse("2022-05-10T23:00:00.000Z"),
                startZoneOffset = ZoneOffset.of("-08:00"),
                endTime = Instant.parse("2022-05-11T07:00:00.000Z"),
                endZoneOffset = ZoneOffset.of("-08:00"),
                title = "My Sleep"
            ),
        )
    )
}
  • Сеансы не следует использовать для общих измерений, таких как подсчет шагов за день.
  • Данные подтипа не содержат UID, но связанные данные имеют отдельные UID.
  • Данные подтипов должны быть выровнены в сеансе с последовательными временными метками, которые не перекрываются. Однако допускаются пробелы.
  • Сеансы полезны, если пользователь хочет, чтобы данные были связаны с сеансом (и отслеживались как его часть), а не записывались непрерывно.

сеансы сна

Вы можете читать и записывать данные о сне в Health Connect. Данные о сне отображаются в виде сеанса и могут быть разделены на 8 отдельных фаз сна:

  • UNKNOWN : Не указано или неизвестно, спит ли пользователь.
  • AWAKE : Пользователь бодрствует в течение цикла сна, а не в течение дня.
  • SLEEPING : Общее или недетализированное описание сна.
  • OUT_OF_BED : Пользователь встает с постели во время сеанса сна.
  • AWAKE_IN_BED : Пользователь не спит в постели.
  • LIGHT : Пользователь находится в фазе легкого сна.
  • DEEP : Пользователь находится в фазе глубокого сна.
  • REM : Пользователь находится в фазе быстрого сна.

Эти значения отражают тип сна пользователя в определённом диапазоне времени. Запись стадий сна необязательна, но рекомендуется, если она доступна.

Запишите сеансы сна

Тип данных SleepSessionRecord состоит из двух частей:

  1. Общий сеанс, охватывающий всю продолжительность сна.
  2. Отдельные стадии во время сеанса сна, такие как легкий сон или глубокий сон.

Вот как вставить сеанс сна без стадий:

SleepSessionRecord(
      title = "weekend sleep",
      startTime = startTime,
      endTime = endTime,
      startZoneOffset = ZoneOffset.UTC,
      endZoneOffset = ZoneOffset.UTC,
)

Вот как добавить стадии, охватывающие весь период сеанса сна:

val stages = listOf(
    SleepSessionRecord.Stage(
        startTime = START_TIME
        endTime = END_TIME,
        stage = SleepSessionRecord.STAGE_TYPE_SLEEPING,
    )
)

SleepSessionRecord(
        title = "weekend sleep",
        startTime = START_TIME,
        endTime = END_TIME,
        startZoneOffset = START_ZONE_OFFSET,
        endZoneOffset = END_ZONE_OFFSET,
        stages = stages,
)

Прочитайте сеанс сна

Для каждого возвращенного сеанса сна необходимо проверить, присутствуют ли также данные о стадиях сна:

suspend fun readSleepSessions(
    healthConnectClient: HealthConnectClient,
    startTime: Instant,
    endTime: Instant
) {
    val response =
        healthConnectClient.readRecords(
            ReadRecordsRequest(
                SleepSessionRecord::class,
                timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
            )
        )
    for (sleepRecord in response.records) {
        // Retrieve relevant sleep stages from each sleep record
        val sleepStages = sleepRecord.stages
    }
}

Удалить сеанс сна

Вот как удалить сеанс. В этом примере мы использовали сеанс сна:

suspend fun deleteSleepSession(
    healthConnectClient: HealthConnectClient,
    sleepRecord: SleepSessionRecord,
) {
    val timeRangeFilter = TimeRangeFilter.between(sleepRecord.startTime, sleepRecord.endTime)
    healthConnectClient.deleteRecords(SleepSessionRecord::class, timeRangeFilter)
}