Отслеживайте шаги

Health Connect предоставляет тип данных «шаги» для записи количества шагов с помощью StepsRecord . Шаги — это основополагающий показатель в отслеживании здоровья и физической активности.

Прочитайте шаги для мобильных устройств.

При использовании Android 14 (уровень API 34) и SDK Extension версии 20 или выше, Health Connect обеспечивает подсчет шагов непосредственно на устройстве. Если какому-либо приложению предоставлено разрешение READ_STEPS , Health Connect начинает фиксировать шаги на устройстве под управлением Android, и пользователи автоматически видят данные о шагах, добавляемые в записи Health Connect Steps .

Чтобы проверить наличие функции подсчета шагов на устройстве, необходимо убедиться, что устройство работает под управлением Android 14 (уровень API 34) и имеет как минимум версию расширения SDK 20. Для этого можно использовать следующий код:

val isStepTrackingAvailable =
    Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE &&
        SdkExtensions.getExtensionVersion(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) >= 20

При использовании приложения Health Connect для отслеживания шагов на мобильных устройствах в качестве DataOrigin используется имя пакета android . Если ваше приложение просто считывает агрегированные данные о количестве шагов с помощью aggregate и не фильтрует по DataOrigin , шаги, сделанные на устройстве, автоматически включаются в общую сумму.

Если вашему приложению необходимо считывать данные о шагах, выполняемых на устройстве, или если оно отображает данные о шагах с разбивкой по исходному приложению или устройству, вы можете запросить записи, где DataOrigin равен android . Если ваше приложение отображает атрибуцию для данных о шагах, вам следует атрибутивировать данные из пакета android текущему устройству. Вы можете сделать это, используя метку, например, «Ваш телефон», получив имя устройства с помощью Settings.Global.getString(resolver, Settings.Global.DEVICE_NAME) или проверив поле Device в метаданных записи.

В следующем примере показано, как считывать агрегированные данные о количестве шагов, сделанных на мобильном устройстве, с фильтрацией по источнику данных android :

suspend fun readStepsByTimeRange(
    healthConnectClient: HealthConnectClient,
    startTime: Instant,
    endTime: Instant
) {
    try {
        val response = healthConnectClient.aggregate(
            AggregateRequest(
                metrics = setOf(StepsRecord.COUNT_TOTAL),
                timeRangeFilter = TimeRangeFilter.between(startTime, endTime),
                dataOriginFilter = setOf(DataOrigin("android"))
            )
        )
        // The result may be null if no data is available in the time range
        val stepCount = response[StepsRecord.COUNT_TOTAL]
    } catch (e: Exception) {
        // Run error handling here
    }
}

Подсчет шагов на устройстве

Подробнее об функции подсчета шагов на устройстве:

  • Использование датчика : Health Connect использует датчик TYPE_STEP_COUNTER из SensorManager . Этот датчик оптимизирован для низкого энергопотребления, что делает его идеальным для непрерывного фонового отслеживания шагов.
  • Детализация данных : Для экономии заряда батареи данные о количестве шагов обычно объединяются в пакеты и записываются в базу данных Health Connect не чаще одного раза в минуту.
  • Атрибуция : Как упоминалось ранее, все шаги, записанные этой функцией на устройстве, приписываются имени пакета android в DataOrigin .
  • Активация : Механизм подсчета шагов на устройстве активируется только в том случае, если хотя бы одному приложению на устройстве предоставлено разрешение READ_STEPS в рамках 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, если это необходимо.

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

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

  • android.permission.health.READ_STEPS
  • android.permission.health.WRITE_STEPS

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

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

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

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

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

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

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

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

// Create a set of permissions for required data types
val PERMISSIONS =
    setOf(
  HealthPermission.getReadPermission(StepsRecord::class),
  HealthPermission.getWritePermission(StepsRecord::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)
  }
}

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

Информация, содержащаяся в записи о шагах.

Каждый StepsRecord содержит следующую информацию:

  • count : Количество шагов, сделанных за интервал времени, в формате Long .
  • startTime : Время начала интервала измерения.
  • endTime : Время окончания интервала измерения.
  • startZoneOffset : Смещение зоны для времени начала.
  • endZoneOffset : Смещение зоны для времени окончания.

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

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

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

Пример использования

В следующих разделах показано, как читать и записывать данные StepsRecord .

Запись данных о шагах

Ваше приложение может записывать данные о количестве шагов, добавляя экземпляры StepsRecord . В следующем примере показано, как записать 1000 шагов, сделанных пользователем:

suspend fun writeStepsData(
    healthConnectClient: HealthConnectClient,
    startTime: Instant,
    endTime: Instant,
    startZoneOffset: ZoneOffset,
    endZoneOffset: ZoneOffset
) {
    try {
        val stepsRecord = StepsRecord(
            startTime = startTime,
            startZoneOffset = startZoneOffset,
            endTime = endTime,
            endZoneOffset = endZoneOffset,
            count = 1000
        )
        healthConnectClient.insertRecords(listOf(stepsRecord))
    } catch (e: Exception) {
        // Run error handling
    }
}

Прочитать сводные данные

Наиболее распространенный способ чтения данных о шагах — это суммирование общего количества шагов за определенный период времени. В следующем примере показано, как прочитать общее количество шагов пользователя за определенный период времени:

suspend fun readStepsAggregate(
    healthConnectClient: HealthConnectClient,
    startTime: Instant,
    endTime: Instant
) {
    try {
        val response = healthConnectClient.aggregate(
            AggregateRequest(
                metrics = setOf(StepsRecord.COUNT_TOTAL),
                timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
            )
        )
        // The result may be null if no data is available in the time range
        val stepCount = response[StepsRecord.COUNT_TOTAL]
    } catch (e: Exception) {
        // Run error handling here
    }
}

Прочитать исходные данные

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

suspend fun readStepsRaw(
    healthConnectClient: HealthConnectClient,
    startTime: Instant,
    endTime: Instant
) {
    try {
        val response = healthConnectClient.readRecords(
            ReadRecordsRequest(
                recordType = StepsRecord::class,
                timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
            )
        )
        for (record in response.records) {
            // Process each record
        }
    } catch (e: Exception) {
        // Run error handling here
    }
}