Odczyt nieprzetworzonych danych

Poniższy przykład pokazuje, jak odczytywać dane pierwotne w ramach typowego procesu.

Odczytywanie danych

Health Connect umożliwia aplikacjom odczytywanie danych z pamięci, gdy są one na pierwszym planie i w tle:

  • Odczytywanie danych na pierwszym planie: zwykle możesz odczytywać dane z Health Connect, gdy aplikacja jest na pierwszym planie. W takich przypadkach możesz użyć usługi na pierwszym planie, aby wykonać tę operację, jeśli użytkownik lub system umieści aplikację w tle podczas operacji odczytu.

  • Odczytywanie w tle: prosząc użytkownika o dodatkowe uprawnienia, możesz odczytywać dane po tym, jak użytkownik lub system umieści Twoją aplikację w tle. Zobacz pełny przykład odczytu w tle.

Typ danych Kroki w Health Connect rejestruje liczbę kroków wykonanych przez użytkownika między odczytami. Liczba kroków to powszechny pomiar na platformach związanych ze zdrowiem, aktywnością fizyczną i dobrym samopoczuciem. Health Connect umożliwia odczytywanie i zapisywanie danych o liczbie kroków.

Aby odczytać rekordy, utwórz ReadRecordsRequest i podaj go podczas wywoływania funkcji readRecords.

Przykład poniżej pokazuje, jak odczytać dane o liczbie kroków użytkownika w określonym czasie. Rozszerzony przykład z SensorManager znajdziesz w przewodniku po danych dotyczących liczby kroków.

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

Możesz też odczytywać dane w formie zagregowanej za pomocą 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
    }
}

Odczytuj dane o krokach na urządzeniu mobilnym

W przypadku Androida 14 (API na poziomie 34) i rozszerzenia SDK w wersji 20 lub nowszej Health Connect udostępnia zliczanie kroków na urządzeniu. Jeśli jakiejkolwiek aplikacji przyznano uprawnienie READ_STEPS, Health Connect zacznie rejestrować kroki z urządzenia z Androidem, a użytkownicy będą widzieć dane o krokach automatycznie dodawane do wpisów Kroki w Health Connect.

Aby sprawdzić, czy na urządzeniu jest dostępna funkcja zliczania kroków, musisz sprawdzić, czy urządzenie działa na Androidzie 14 (API na poziomie 34) i ma co najmniej wersję rozszerzenia SDK 20. Możesz użyć tego kodu:

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

Kroki zarejestrowane przez Health Connect mają ustawioną wartość DataOrigin na nazwę pakietu android. Jeśli Twoja aplikacja odczytuje tylko zagregowane liczby kroków za pomocą aggregate i nie filtruje ich według DataOrigin, kroki zarejestrowane na urządzeniu są automatycznie uwzględniane w sumie.

Jeśli aplikacja musi odczytywać dane o krokach na urządzeniu lub wyświetlać dane o krokach podzielone według aplikacji lub urządzenia źródłowego, możesz wysyłać zapytania o rekordy, w których pole DataOrigin ma wartość android. Jeśli Twoja aplikacja wyświetla atrybucję danych o krokach, dane z pakietu Android powinny być przypisywane do bieżącego urządzenia. Możesz to zrobić, używając etykiety, np. „Twój telefon”, pobierając nazwę urządzenia za pomocą Settings.Global.getString(resolver, Settings.Global.DEVICE_NAME) lub sprawdzając pole Device w metadanych rekordu.

Ten przykład pokazuje, jak odczytać zagregowane dane o liczbie kroków na urządzeniu mobilnym, filtrując je według android źródła danych:

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

Liczenie kroków na urządzeniu

Szczegółowe informacje o funkcji liczenia kroków na urządzeniu:

  • Korzystanie z czujników: Health Connect korzysta z czujnika TYPE_STEP_COUNTER firmy SensorManager. Ten czujnik jest zoptymalizowany pod kątem niskiego zużycia energii, dzięki czemu idealnie nadaje się do ciągłego śledzenia kroków w tle.
  • Granularność danych: aby oszczędzać baterię, dane o krokach są zwykle przesyłane w pakietach i zapisywane w bazie danych Health Connect nie częściej niż raz na minutę.
  • Atrybucja: jak wspomnieliśmy wcześniej, wszystkie kroki zarejestrowane przez tę funkcję na urządzeniu są przypisywane do nazwy pakietu androidDataOrigin.
  • Aktywacja: mechanizm zliczania kroków na urządzeniu jest aktywny tylko wtedy, gdy co najmniej 1 aplikacja na urządzeniu ma przyznane uprawnienie READ_STEPS w Health Connect.

Przykład odczytywania w tle

Aby odczytywać dane w tle, zadeklaruj w pliku manifestu to uprawnienie:

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

Przykład poniżej pokazuje, jak odczytać dane o liczbie kroków w tle dla użytkownika w określonym czasie za pomocą funkcji 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
  ...
}

Parametr ReadRecordsRequest ma domyślną wartość pageSize 1000. Jeśli liczba rekordów w jednym readResponse przekracza pageSize żądania, musisz przejść przez wszystkie strony odpowiedzi, aby pobrać wszystkie rekordy, używając pageToken. Uważaj jednak, aby nie przekroczyć limitu żądań.

Przykład odczytu pageToken

Do odczytywania rekordów zalecamy używanie pageToken, aby pobierać wszystkie dostępne dane z wybranego okresu.

W tym przykładzie pokazujemy, jak odczytać wszystkie rekordy, dopóki nie zostaną wykorzystane wszystkie tokeny strony:

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
}

Informacje o sprawdzonych metodach odczytywania dużych zbiorów danych znajdziesz w artykule Planowanie, aby uniknąć ograniczenia liczby żądań.

Odczytywanie wcześniej zapisanych danych

Jeśli aplikacja zapisywała wcześniej rekordy w Health Connect, może odczytywać dane historyczne. Dotyczy to sytuacji, w których aplikacja musi ponownie zsynchronizować się z Health Connect po ponownym zainstalowaniu przez użytkownika.

Obowiązują pewne ograniczenia dotyczące odczytu:

  • Android 14 lub nowszy

    • Brak historycznego limitu dotyczącego odczytywania przez aplikację własnych danych.
    • 30-dniowy limit odczytywania przez aplikację innych danych.
  • Android 13 lub starszy

    • 30-dniowy limit odczytywania danych przez aplikację.

Ograniczenia można usunąć, prosząc o uprawnienia do odczytu.

Aby odczytać dane historyczne, musisz wskazać nazwę pakietu jako obiekt DataOrigin w parametrze dataOriginFilter funkcji ReadRecordsRequest.

Poniższy przykład pokazuje, jak wskazać nazwę pakietu podczas odczytywania rekordów tętna:

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
}

Odczytywanie danych starszych niż 30 dni

Domyślnie wszystkie aplikacje mogą odczytywać dane z Health Connect z okresu do 30 dni przed przyznaniem im uprawnień.

Jeśli chcesz rozszerzyć uprawnienia do odczytu poza domyślne ograniczenia, poproś o PERMISSION_READ_HEALTH_DATA_HISTORY. W przeciwnym razie próba odczytania rekordów starszych niż 30 dni spowoduje błąd.

Historia uprawnień usuniętej aplikacji

Jeśli użytkownik usunie Twoją aplikację, wszystkie uprawnienia, w tym uprawnienia do historii, zostaną cofnięte. Jeśli użytkownik ponownie zainstaluje aplikację i ponownie przyzna jej uprawnienia, będą obowiązywać te same domyślne ograniczenia, a aplikacja będzie mogła odczytywać dane z Health Connect z okresu do 30 dni przed tą nową datą.

Załóżmy na przykład, że użytkownik usunie Twoją aplikację 10 maja 2023 r., a następnie zainstaluje ją ponownie 15 maja 2023 r. i przyzna jej uprawnienia do odczytu. Najwcześniejsza data, od której Twoja aplikacja może domyślnie odczytywać dane, to 15 kwietnia 2023 r.

Obsługa wyjątków

W przypadku wystąpienia problemu Health Connect zgłasza standardowe wyjątki dotyczące operacji CRUD. Aplikacja powinna przechwytywać i obsługiwać każdy z tych wyjątków w odpowiedni sposób.

Każda metoda w HealthConnectClient zawiera listę wyjątków, które mogą zostać zgłoszone. Ogólnie rzecz biorąc, aplikacja powinna obsługiwać te wyjątki:

Tabela 1. Wyjątki dotyczące Health Connect i zalecane sprawdzone metody
Wyjątek Opis Zalecana sprawdzona metoda
IllegalStateException Wystąpił jeden z tych scenariuszy:

  • Usługa Health Connect jest niedostępna.
  • Żądanie nie jest prawidłową konstrukcją. Na przykład żądanie zbiorcze w okresowych przedziałach, w którym obiekt Instant jest używany w przypadku timeRangeFilter.

Przed wysłaniem żądania najpierw rozwiąż ewentualne problemy z danymi wejściowymi. Najlepiej przypisywać wartości do zmiennych lub używać ich jako parametrów w funkcji niestandardowej zamiast używać ich bezpośrednio w żądaniach, aby móc stosować strategie obsługi błędów.
IOException Podczas odczytywania i zapisywania danych na dysku wystąpiły problemy. Aby uniknąć tego problemu, wykonaj te czynności:

  • Twórz kopie zapasowe wszystkich danych wprowadzanych przez użytkowników.
  • umieć radzić sobie z problemami, które mogą wystąpić podczas operacji zapisu zbiorczego. Na przykład upewnij się, że proces przechodzi przez problem, i wykonaj pozostałe operacje.
  • Stosuj ponowne próby i strategie wycofywania, aby rozwiązywać problemy z żądaniami.

RemoteException Wystąpiły błędy w usłudze bazowej, z którą łączy się pakiet SDK, lub podczas komunikacji z nią.

 Na przykład aplikacja próbuje usunąć rekord o danym uid. Wyjątek jest jednak zgłaszany po tym, jak aplikacja podczas sprawdzania w usłudze bazowej stwierdzi, że rekord nie istnieje.
Aby uniknąć tego problemu, wykonaj te czynności:

  • Regularnie synchronizuj dane między magazynem danych aplikacji a Health Connect.
  • Stosuj ponowne próby i strategie wycofywania, aby rozwiązywać problemy z żądaniami.

SecurityException Problemy występują, gdy żądania wymagają uprawnień, które nie zostały przyznane. Aby tego uniknąć, upewnij się, że zadeklarowano wykorzystanie typów danych Health Connect w opublikowanej aplikacji. Musisz też zadeklarować uprawnienia Health Connect w pliku manifestuw aktywności.