Чтение необработанных данных

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

Чтение данных

Health Connect позволяет приложениям считывать данные из хранилища данных, когда приложение находится на переднем плане и в фоновом режиме:

  • Чтение в фоновом режиме : обычно вы можете считывать данные из Health Connect, когда ваше приложение находится в фоновом режиме. В таких случаях вы можете использовать службу переднего плана для выполнения этой операции на случай, если пользователь или система переведут ваше приложение в фоновый режим во время операции чтения.

  • Фоновое чтение : запросив у пользователя дополнительное разрешение, вы сможете читать данные после того, как пользователь или система переведут ваше приложение в фоновый режим. См. полный пример фонового чтения .

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

Чтобы прочитать записи, создайте ReadRecordsRequest и предоставьте его при вызове readRecords .

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

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

Вы также можете прочитать свои данные в агрегированном виде, используя aggregate .

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)
            )
        )
        // 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
    }
}

Пример фонового чтения

Чтобы читать данные в фоновом режиме, объявите следующее разрешение в файле манифеста:

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

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

class ScheduleWorker(private val appContext: Context, workerParams: WorkerParameters):
    CoroutineWorker(appContext, workerParams) {

    override suspend fun doWork(): Result {
        // Read data and process it.
        ...

        // Return success indicating successful data retrieval
        return Result.success()
    }
}

if (healthConnectClient
    .features
    .getFeatureStatus(
    HealthConnectFeatures.FEATURE_READ_HEALTH_DATA_IN_BACKGROUND
    ) == HealthConnectFeatures.FEATURE_STATUS_AVAILABLE) {

    // Check if necessary permission is granted
    val grantedPermissions = healthConnectClient.permissionController.getGrantedPermissions()

    if (PERMISSION_READ_HEALTH_DATA_IN_BACKGROUND !in grantedPermissions) {
        // Perform read in foreground
        ...
    } else {
        // Schedule the periodic work request in background
        val periodicWorkRequest = PeriodicWorkRequestBuilder<ScheduleWorker>(1, TimeUnit.HOURS)
            .build()

        WorkManager.getInstance(context).enqueueUniquePeriodicWork(
            "read_health_connect",
            ExistingPeriodicWorkPolicy.KEEP,
            periodicWorkRequest
        )
    }
} else {
  // Background reading is not available, perform read in foreground
  ...
}

Параметр 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 года .