В следующем примере показано, как считывать необработанные данные в рамках стандартного рабочего процесса.
Прочитать данные
Health Connect позволяет приложениям считывать данные из хранилища данных как в фоновом, так и в активном режиме:
Чтение в фоновом режиме : Обычно вы можете считывать данные из Health Connect, когда ваше приложение находится в фоновом режиме. В таких случаях вы можете рассмотреть возможность использования службы переднего плана для выполнения этой операции, если пользователь или система переводят ваше приложение в фоновый режим во время операции чтения.
Чтение в фоновом режиме : запросив у пользователя дополнительное разрешение, вы можете считывать данные после того, как пользователь или система переведут ваше приложение в фоновый режим. См. полный пример чтения в фоновом режиме .
В Health Connect тип данных «Шаги» отображает количество шагов, сделанных пользователем между измерениями. Подсчет шагов — распространенный показатель на платформах для здоровья, фитнеса и хорошего самочувствия. Health Connect позволяет считывать и записывать данные о количестве шагов.
Для чтения записей создайте объект ReadRecordsRequest и передайте его при вызове readRecords .
В следующем примере показано, как считывать данные о количестве шагов пользователя за определенный период времени. Расширенный пример с использованием SensorManager см. в руководстве по данным о количестве шагов .
val response = healthConnectClient.readRecords( ReadRecordsRequest( HeartRateRecord::class, timeRangeFilter = TimeRangeFilter.between(startTime, endTime) ) ) response.records.forEach { record -> /* Process records */ }
Вы также можете считывать данные в агрегированном виде, используя aggregate .
suspend fun readStepsAggregate(startTime: Instant, endTime: Instant): Long { val response = healthConnectClient.aggregate( AggregateRequest( metrics = setOf(StepsRecord.COUNT_TOTAL), timeRangeFilter = TimeRangeFilter.between(startTime, endTime) ) ) return response[StepsRecord.COUNT_TOTAL] ?: 0L }
Прочитайте шаги для мобильных устройств.
При использовании 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
Если ваше приложение считывает агрегированные данные о количестве шагов с помощью aggregate и не фильтрует по DataOrigin , то шаги, сделанные на устройстве, автоматически включаются в общую сумму, и никаких изменений для обновления в июне 2026 года не требуется.
Изменение атрибуции для шагов, выполняемых на устройстве.
Начиная с обновления от июня 2026 года, шаги, отслеживаемые приложением Health Connect, приписываются синтетическому имени пакета (SPN) , например, com.android.healthconnect.phone.jd5bdd37e1a8d3667a05d0abebfc4a89e .
Ранее встроенные данные о количестве шагов были привязаны к имени пакета android . В исторических данных о количестве шагов, записанных до июня 2026 года, сохраняется имя пакета android .
SPN (Single Podsecurity Networks) привязаны к конкретному устройству и используются в рамках каждого приложения для защиты конфиденциальности пользователей:
- Стабильность: Значение SPN для текущего устройства стабильно для вашего приложения.
- Ограничение по области действия приложения: разные приложения на одном устройстве видят разные SPN для данных о шагах, хранящихся на устройстве.
Запрос шагов, выполняемых на устройстве.
Поскольку SPN имеют ограниченную область видимости и зависят от устройства, не следует жестко задавать значения SPN. Вместо этого используйте API getCurrentDeviceDataSource() для получения SPN для текущего устройства.
В то время как для подсчета шагов на устройстве требуется расширение SDK версии 20 или выше, API getCurrentDeviceDataSource() доступен в Android 14 (уровень API 34) с расширением SDK версии 11 или выше.
API-функция getCurrentDeviceDataSource() пока недоступна в библиотеке Health Connect Jetpack. В следующих примерах используется API фреймворка Android:
import android.content.Context
import android.health.connect.HealthConnectManager
val healthConnectManager = context.getSystemService(HealthConnectManager::class.java)
val deviceDataSource = healthConnectManager?.getCurrentDeviceDataSource()
val currentDeviceSpn = deviceDataSource?.deviceDataOrigin?.packageName
Если вашему приложению необходимо считывать данные о шагах, выполняемых на устройстве, или если оно отображает данные о шагах с разбивкой по исходному приложению или устройству, вам необходимо запросить записи, где DataOrigin равен android или соответствует SPN устройства. Если ваше приложение отображает атрибуцию для данных о шагах, используйте metadata.device для идентификации исходного устройства для отдельных записей. Для шагов, выполняемых на устройстве и идентифицированных по SPN в агрегированных данных, вы можете использовать метаданные устройства, такие как model или manufacturer из DeviceDataSource для атрибуции, или использовать общую метку, например, «Ваш телефон», для шагов, выполняемых на устройстве.
В следующем примере показано, как считывать агрегированные данные о количестве шагов на устройстве, фильтруя их по типу android и по SPN текущего устройства:
import android.content.Context
import android.health.connect.HealthConnectManager
import android.os.Build
import android.os.ext.SdkExtensions
import androidx.health.connect.client.HealthConnectClient
import androidx.health.connect.client.records.StepsRecord
import androidx.health.connect.client.records.metadata.DataOrigin
import androidx.health.connect.client.request.AggregateRequest
import androidx.health.connect.client.time.TimeRangeFilter
import java.time.Instant
suspend fun readDeviceStepsByTimeRange(
healthConnectClient: HealthConnectClient,
context: Context,
startTime: Instant,
endTime: Instant
) {
// 1. Check if SDK Extension 11+ is available for getCurrentDeviceDataSource()
val isDataSourceApiAvailable = Build.VERSION.SDK_INT >= Build.VERSION_CODES.U &&
SdkExtensions.getExtensionVersion(Build.VERSION_CODES.U) >= 11
try {
val healthConnectManager = context.getSystemService(HealthConnectManager::class.java)
// 2. Safely fetch the package name only if API is available and data exists
val currentDeviceSpn = if (isDataSourceApiAvailable) {
healthConnectManager?.getCurrentDeviceDataSource()?.deviceDataOrigin?.packageName
} else {
null
}
val dataOriginFilters = mutableSetOf(DataOrigin("android"))
// 3. Explicit null-safety check using .let
currentDeviceSpn?.let {
dataOriginFilters.add(DataOrigin(it))
}
val response = healthConnectClient.aggregate(
AggregateRequest(
metrics = setOf(StepsRecord.COUNT_TOTAL),
timeRangeFilter = TimeRangeFilter.between(startTime, endTime),
dataOriginFilter = dataOriginFilters
)
)
val stepCount = response[StepsRecord.COUNT_TOTAL]
} catch (e: Exception) {
// Now this catch block only handles actual runtime exceptions,
// rather than Errors from missing methods.
}
}
Подсчет шагов на устройстве
- Использование датчика : Health Connect использует датчик
TYPE_STEP_COUNTERизSensorManager. Этот датчик оптимизирован для низкого энергопотребления, что делает его идеальным для непрерывного фонового отслеживания шагов. - Детализация данных : Для экономии заряда батареи данные о количестве шагов обычно объединяются в пакеты и записываются в базу данных Health Connect не чаще одного раза в минуту.
- Атрибуция : Шаги, записанные этой функцией до июня 2026 года, приписываются имени пакета
androidвDataOrigin. После этой даты они приписываются SPN, специфичному для устройства. См. Изменение атрибуции для шагов на устройстве . - Активация : Механизм подсчета шагов на устройстве активируется только в том случае, если хотя бы одному приложению на устройстве предоставлено разрешение
READ_STEPSв рамках Health Connect.
Пример фонового чтения
Для чтения данных в фоновом режиме укажите следующие права доступа в файле манифеста:
<application>
<uses-permission android:name="android.permission.health.READ_HEALTH_DATA_IN_BACKGROUND" />
...
</application>
В следующем примере показано, как с помощью WorkManager в фоновом режиме считывать данные о количестве шагов пользователя за определенный период времени:
class ScheduleWorker(appContext: Context, workerParams: WorkerParameters) : CoroutineWorker(appContext, workerParams) { override suspend fun doWork(): Result { val healthConnectClient = HealthConnectClient.getOrCreate(applicationContext) // Perform background read logic here return Result.success() } }
@OptIn(ExperimentalFeatureAvailabilityApi::class) fun enqueueBackgroundReadWorker(context: Context, healthConnectClient: HealthConnectClient) { if (healthConnectClient .features .getFeatureStatus( HealthConnectFeatures.FEATURE_READ_HEALTH_DATA_IN_BACKGROUND ) == HealthConnectFeatures.FEATURE_STATUS_AVAILABLE ) { val periodicWorkRequest = PeriodicWorkRequestBuilder<ScheduleWorker>(1, TimeUnit.HOURS) .build() WorkManager.getInstance(context).enqueueUniquePeriodicWork( "read_health_connect", ExistingPeriodicWorkPolicy.KEEP, periodicWorkRequest ) } }
Параметр ReadRecordsRequest имеет значение pageSize по умолчанию, равное 1000. Если количество записей в одном readResponse превышает pageSize запроса, вам необходимо пройтись по всем страницам ответа, чтобы получить все записи, используя pageToken . Однако будьте осторожны, чтобы избежать проблем, связанных с ограничением скорости запросов.
пример чтения pageToken
Рекомендуется использовать pageToken для чтения записей, чтобы получить все доступные данные за запрошенный период времени.
В следующем примере показано, как прочитать все записи до тех пор, пока не будут исчерпаны все токены страниц:
val type = HeartRateRecord::class val endTime = Instant.now() val startTime = endTime.minus(Duration.ofDays(7)) try { var pageToken: String? = null do { val readResponse = healthConnectClient.readRecords( ReadRecordsRequest( recordType = type, timeRangeFilter = TimeRangeFilter.between( startTime, endTime ), pageToken = pageToken ) ) val records = readResponse.records // Do something with records pageToken = readResponse.pageToken } while (pageToken != null) } catch (quotaError: IllegalStateException) { // Backoff }
Ознакомьтесь с ранее опубликованными данными.
Если приложение ранее записывало данные в Health Connect, оно может считывать исторические данные. Это применимо в ситуациях, когда приложению необходимо повторно синхронизироваться с Health Connect после переустановки пользователем.
Действуют некоторые ограничения на чтение:
Для Android 14 и выше
- Нет исторических ограничений на чтение собственных данных приложением.
- Ограничение на чтение данных другими приложениями составляет 30 дней.
Для Android 13 и ниже
- Приложение может считывать данные только в течение 30 дней.
Ограничения можно снять, запросив разрешение на чтение .
Для чтения исторических данных необходимо указать имя пакета в виде объекта DataOrigin в параметре dataOriginFilter вашего ReadRecordsRequest .
В следующем примере показано, как указать имя пакета при чтении записей частоты сердечных сокращений:
try { val response = healthConnectClient.readRecords( ReadRecordsRequest( recordType = HeartRateRecord::class, timeRangeFilter = TimeRangeFilter.between(startTime, endTime), dataOriginFilter = setOf(DataOrigin("com.my.package.name")) ) ) for (record in response.records) { // Process each record } } catch (e: Exception) { // Run error handling here }
Прочитать данные старше 30 дней
По умолчанию все приложения могут считывать данные из Health Connect за период до 30 дней до момента предоставления соответствующего разрешения.
Если вам необходимо расширить права на чтение сверх каких-либо ограничений по умолчанию , запросите разрешение PERMISSION_READ_HEALTH_DATA_HISTORY . В противном случае, без этого разрешения, попытка чтения записей старше 30 дней приведет к ошибке.
История разрешений для удалённого приложения
Если пользователь удалит ваше приложение, все разрешения, включая разрешение на просмотр истории, будут отозваны. Если пользователь переустановит ваше приложение и снова предоставит разрешение, будут действовать те же ограничения по умолчанию , и ваше приложение сможет считывать данные из Health Connect за период до 30 дней до этой новой даты.
Например, предположим, пользователь удаляет ваше приложение 10 мая 2023 года, а затем переустанавливает его 15 мая 2023 года, предоставляя права на чтение. Самая ранняя дата, с которой ваше приложение теперь может читать данные по умолчанию, — 15 апреля 2023 года .
Обработка исключений
В случае возникновения проблем Health Connect генерирует стандартные исключения для операций CRUD. Ваше приложение должно перехватывать и обрабатывать каждое из этих исключений соответствующим образом.
В каждом методе класса HealthConnectClient перечислены исключения, которые могут быть сгенерированы. В целом, ваше приложение должно обрабатывать следующие исключения:
| Исключение | Описание | Рекомендуемые лучшие практики |
|---|---|---|
IllegalStateException | Произошло одно из следующих событий:
| Перед отправкой запроса сначала обработайте возможные проблемы с входными данными. Желательно присваивать значения переменным или использовать их в качестве параметров в пользовательской функции, а не использовать их напрямую в запросах, чтобы иметь возможность применять стратегии обработки ошибок. |
IOException | При чтении и записи данных с диска возникают проблемы. | Чтобы избежать этой проблемы, предлагаем следующие варианты:
|
RemoteException | Ошибки возникли внутри или при взаимодействии с базовой службой, к которой подключается SDK. Например, ваше приложение пытается удалить запись с заданным uid . Однако исключение возникает после того, как приложение, проверив данные в базовом сервисе, обнаруживает, что запись не существует. | Чтобы избежать этой проблемы, предлагаем следующие варианты:
|
SecurityException | Проблемы возникают, когда запросы требуют разрешений, которые не предоставлены. | Чтобы этого избежать, убедитесь, что вы указали использование типов данных Health Connect для опубликованного приложения. Кроме того, необходимо указать разрешения Health Connect в файле манифеста и в вашем Activity . |