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

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

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

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

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

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

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

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

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

suspend fun readStepsByTimeRange(
    healthConnectClient: HealthConnectClient,
    startTime: Instant,
    endTime: Instant
) {
    try {
        val response = healthConnectClient.readRecords(
            ReadRecordsRequest(
                StepsRecord::class,
                timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
            )
        )
        for (stepRecord in response.records) {
            // Process each step record
        }
    } 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 = StepsRecord::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 года .