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

Данное руководство совместимо с версией Health Connect 1.1.0-alpha11 .

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

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

В сессиях SleepSessionRecord содержатся данные, регистрирующие стадии сна, такие как AWAKE , SLEEPING и DEEP .

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

Проверьте доступность 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, если это необходимо.

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

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

Необходимые разрешения

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

  • 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 : Пользователь находится в фазе быстрого сна (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)
}