Zapisywanie danych

Ten przewodnik jest zgodny z Health Connect w wersji 1.1.0-alpha12 lub nowszej.

Ten przewodnik opisuje proces zapisywania i aktualizowania danych w Health Connect.

Obsługa wartości zerowych

Niektóre typy danych, takie jak kroki, dystans czy kalorie, mogą mieć wartość 0. Zapisuj wartości zerowe tylko wtedy, gdy odzwierciedlają one rzeczywisty brak aktywności, gdy użytkownik nosił urządzenie. Nie zapisuj wartości zerowych, jeśli urządzenie nie było noszone, brakuje danych lub bateria się rozładowała. W takich przypadkach pomiń rekord, aby uniknąć wprowadzających w błąd danych.

Konfigurowanie struktury danych

Zanim zaczniemy zapisywać dane, musimy najpierw skonfigurować rekordy. W przypadku ponad 50 typów danych każdy ma własną strukturę. Więcej informacji o dostępnych typach danych znajdziesz w dokumentacji Jetpacka.

Podstawowe rekordy

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.

Poniższy przykład pokazuje, jak ustawić dane o liczbie kroków:

val zoneOffset = ZoneOffset.systemDefault().rules.getOffset(startTime)
val stepsRecord = StepsRecord(
    count = 120,
    startTime = startTime,
    endTime = endTime,
    startZoneOffset = zoneOffset,
    endZoneOffset = zoneOffset,
    metadata = Metadata.autoRecorded(
        device = Device(type = Device.TYPE_WATCH)
    )
)
healthConnectClient.insertRecords(listOf(stepsRecord))

Rekordy z jednostkami miary

Health Connect może przechowywać wartości wraz z jednostkami miary, aby zapewnić dokładność. Jednym z przykładów jest typ danych Odżywianie, który jest bardzo obszerny i kompleksowy. Obejmuje ona wiele opcjonalnych pól dotyczących składników odżywczych, od węglowodanów ogółem po witaminy. Każdy punkt danych reprezentuje składniki odżywcze, które mogły zostać spożyte w ramach posiłku lub produktu spożywczego.

W tym typie danych wszystkie składniki odżywcze są reprezentowane w jednostkach masy, a energy – w jednostkach energii.

Poniższy przykład pokazuje, jak ustawić dane o odżywianiu dla użytkownika, który zjadł banana:

val endTime = Instant.now()
val startTime = endTime.minus(Duration.ofMinutes(1))

val banana = NutritionRecord(
    name = "banana",
    energy = 105.0.kilocalories,
    dietaryFiber = 3.1.grams,
    potassium = 0.422.grams,
    totalCarbohydrate = 27.0.grams,
    totalFat = 0.4.grams,
    saturatedFat = 0.1.grams,
    sodium = 0.001.grams,
    sugar = 14.0.grams,
    vitaminB6 = 0.0005.grams,
    vitaminC = 0.0103.grams,
    startTime = startTime,
    endTime = endTime,
    startZoneOffset = ZoneOffset.UTC,
    endZoneOffset = ZoneOffset.UTC,
    metadata = Metadata.activelyRecorded(
        device = Device(type = Device.TYPE_PHONE)
    )
)

Rekordy z danymi serii

Health Connect może przechowywać listę danych serii. Jednym z przykładów jest typ danych Tętno, który rejestruje serię próbek bicia serca wykrytych między odczytami.

W tym typie danych parametr samples jest reprezentowany przez listę próbek tętna. Każda próbka zawiera wartość beatsPerMinute i time.

Poniższy przykład pokazuje, jak ustawić dane serii tętna:

val endTime = Instant.now()
val startTime = endTime.minus(Duration.ofMinutes(5))

val heartRateRecord = HeartRateRecord(
    startTime = startTime,
    startZoneOffset = ZoneOffset.UTC,
    endTime = endTime,
    endZoneOffset = ZoneOffset.UTC,
    // records 10 arbitrary data, to replace with actual data
    samples = List(10) { index ->
        HeartRateRecord.Sample(
            time = startTime + Duration.ofSeconds(index.toLong()),
            beatsPerMinute = 100 + index.toLong(),
        )
    },
    metadata = Metadata.activelyRecorded(
        device = Device(type = Device.TYPE_WATCH)
    ))

Wyślij prośbę o uprawnienia do użytkownika

Po utworzeniu instancji klienta aplikacja musi poprosić użytkownika o uprawnienia. Użytkownicy muszą mieć możliwość przyznawania i odbierania uprawnień w dowolnym momencie. Aby to zrobić, utwórz zestaw uprawnień dla wymaganych typów danych. Upewnij się, że uprawnienia w zestawie są najpierw zadeklarowane w pliku manifestu Androida.

val permissions =
    setOf(
        HealthPermission.getReadPermission(HeartRateRecord::class),
        HealthPermission.getWritePermission(HeartRateRecord::class),
        HealthPermission.getReadPermission(StepsRecord::class),
        HealthPermission.getWritePermission(StepsRecord::class)
    )
Użyj getGrantedPermissions, aby sprawdzić, czy Twoja aplikacja ma już wymagane uprawnienia. Jeśli nie, użyj createRequestPermissionResultContract, aby poprosić o te uprawnienia. Wyświetli się ekran uprawnień Health Connect.
val permissions = setOf(
        HealthPermission.getReadPermission(StepsRecord::class),
        HealthPermission.getWritePermission(StepsRecord::class),
        HealthPermission.getReadPermission(HeartRateRecord::class),
        HealthPermission.getWritePermission(HeartRateRecord::class)
    )

val requestPermissionsLauncher = rememberLauncherForActivityResult(
    contract = PermissionController.createRequestPermissionResultContract()
) { grantedPermissions ->
    if (grantedPermissions.containsAll(permissions)) {
        coroutineScope.launch { snackbarHostState.showSnackbar("Permissions granted!") }
    } else {
        coroutineScope.launch { snackbarHostState.showSnackbar("Permissions denied.") }
    }
}
Użytkownicy mogą w każdej chwili przyznać lub cofnąć uprawnienia, dlatego aplikacja musi sprawdzać uprawnienia przed każdym ich użyciem i obsługiwać scenariusze, w których uprawnienia zostaną utracone.

Zapisywanie danych

Jednym z typowych przepływów pracy w Health Connect jest zapisywanie danych. Aby dodać rekordy, użyj insertRecords.

Poniższy przykład pokazuje, jak zapisywać dane, wstawiając liczbę kroków:

val zoneOffset = ZoneOffset.systemDefault().rules.getOffset(startTime)
val stepsRecord = StepsRecord(
    count = 120,
    startTime = startTime,
    endTime = endTime,
    startZoneOffset = zoneOffset,
    endZoneOffset = zoneOffset,
    metadata = Metadata.autoRecorded(
        device = Device(type = Device.TYPE_WATCH)
    )
)
healthConnectClient.insertRecords(listOf(stepsRecord))

Zaktualizuj dane

Jeśli chcesz zmienić co najmniej 1 rekord, zwłaszcza gdy musisz zsynchronizować magazyn danych aplikacji z danymi z Health Connect, możesz zaktualizować dane. Istnieją 2 sposoby aktualizowania danych, które zależą od identyfikatora używanego do znajdowania rekordów.

Metadane

Warto najpierw zapoznać się z klasą Metadata, ponieważ jest ona niezbędna do aktualizowania danych. Podczas tworzenia każdy obiekt Record w Health Connect ma pole metadata. Z synchronizacją są powiązane te właściwości:

Właściwości Opis
id Każdy element Record w Health Connect ma unikalną wartość id.
Health Connect automatycznie wypełnia to pole podczas wstawiania nowego rekordu.
lastModifiedTime Każdy Record śledzi też czas ostatniej modyfikacji rekordu.
Health Connect automatycznie wypełnia to pole.
clientRecordId Każdy element Record może mieć powiązany z nim unikalny identyfikator, który służy jako odniesienie w magazynie danych aplikacji.
Tę wartość podaje Twoja aplikacja.
clientRecordVersion Jeśli rekord ma clientRecordId, można użyć clientRecordVersion, aby dane były zsynchronizowane z wersją w magazynie danych aplikacji.
Tę wartość podaje aplikacja.

Aktualizowanie po odczytaniu według zakresu czasu

Aby zaktualizować dane, najpierw przygotuj potrzebne rekordy. W razie potrzeby wprowadź zmiany w rekordach. Następnie zadzwoń pod numer updateRecords, aby wprowadzić zmiany.

Poniższy przykład pokazuje, jak zaktualizować dane. W tym celu wartości przesunięcia strefy czasowej każdego rekordu są dostosowywane do czasu PST.

suspend fun updateSteps(
    healthConnectClient: HealthConnectClient,
    prevRecordStartTime: Instant,
    prevRecordEndTime: Instant
) {
    try {
        val request = healthConnectClient.readRecords(
            ReadRecordsRequest(
                recordType = StepsRecord::class, timeRangeFilter = TimeRangeFilter.between(
                    prevRecordStartTime,
                    prevRecordEndTime
                )
            )
        )

        val newStepsRecords = arrayListOf<StepsRecord>()
        for (record in request.records) {
            // Adjusted both offset values to reflect changes
            val sr = StepsRecord(
                count = record.count,
                startTime = record.startTime,
                startZoneOffset = record.startTime.atZone(ZoneId.of("PST")).offset,
                endTime = record.endTime,
                endZoneOffset = record.endTime.atZone(ZoneId.of("PST")).offset,
                metadata = record.metadata
            )
            newStepsRecords.add(sr)
        }

        healthConnectClient.updateRecords(newStepsRecords)
    } catch (e: Exception) {
        // Run error handling here
    }
}

Upsert za pomocą identyfikatora rekordu klienta

Jeśli używasz opcjonalnych wartości identyfikatora i wersji rekordu klienta, zalecamy używanie insertRecords zamiast updateRecords.

Funkcja insertRecords umożliwia wstawianie danych przez upsert. Jeśli dane istnieją w Health Connect na podstawie podanego zestawu identyfikatorów rekordów klienta, zostaną zastąpione. W przeciwnym razie zostaną zapisane jako nowe dane. Ten scenariusz jest przydatny, gdy chcesz zsynchronizować dane z magazynu danych aplikacji z Health Connect.

Poniższy przykład pokazuje, jak wykonać operację upsert na danych pobranych z magazynu danych aplikacji:

 fun pullStepsFromDatastore(startTime: Instant, endTime: Instant) : ArrayList<StepsRecord> {
    val appStepsRecords = arrayListOf<StepsRecord>()
    // Pull data from app datastore
    // ...
    // Make changes to data if necessary
    // ...
    // Store data in appStepsRecords
    // ...
    var sr = StepsRecord(
        metadata = Metadata.activelyRecorded(
            clientRecordId = "Your client record ID",
            clientRecordVersion = 0L,
            device = Device(type = Device.TYPE_WATCH)
        ),
        startTime = startTime,
        startZoneOffset = startTime.atZone(ZoneId.of("PST")).offset,
        endTime = endTime,
        endZoneOffset = endTime.atZone(ZoneId.of("PST")).offset,
        count = 120
    )
    appStepsRecords.add(sr)
    // ...
    return appStepsRecords
}

suspend fun upsertSteps(
    healthConnectClient: HealthConnectClient,
    newStepsRecords: ArrayList<StepsRecord>
) {
    try {
        healthConnectClient.insertRecords(newStepsRecords)
    } catch (e: Exception) {
        // Run error handling here
    }
}

Następnie możesz wywołać te funkcje w głównym wątku.

upsertSteps(healthConnectClient, pullStepsFromDatastore(
    startTime = startTime,
    endTime = endTime
))

Sprawdzanie wartości w wersji rekordu klienta

Jeśli proces aktualizowania danych obejmuje wersję rekordu klienta, Health Connect przeprowadza porównania wartości clientRecordVersion. Jeśli wersja z wstawionych danych jest wyższa niż wersja z istniejących danych, następuje operacja upsert. W przeciwnym razie proces ignoruje zmianę, a wartość pozostaje taka sama.

Aby uwzględnić obsługę wersji w danych, musisz podać Metadata.clientRecordVersion z wartością Long na podstawie logiki obsługi wersji.

val endTime = Instant.now()
val startTime = endTime.minus(Duration.ofMinutes(15))

val stepsRecord = StepsRecord(
    count = 100L,
    startTime = startTime,
    startZoneOffset = ZoneOffset.UTC,
    endTime = endTime,
    endZoneOffset = ZoneOffset.UTC,
    metadata = Metadata.activelyRecorded(
        clientRecordId = "Your supplied record ID",
        clientRecordVersion = 0L, // Your supplied record version
        device = Device(type = Device.TYPE_WATCH)
    )
)

Operacje upsert nie powodują automatycznego zwiększania wartości version, gdy zachodzą zmiany, co zapobiega nieoczekiwanemu zastępowaniu danych. W takim przypadku musisz ręcznie podać wyższą wartość.

Ogólne wskazówki

Aplikacja powinna zapisywać wszystkie obsługiwane dane własne. Opcjonalnie możesz zezwolić aplikacji na zapisywanie danych uzyskanych ze źródeł zewnętrznych. Jeśli jednak aplikacja odczytała dane z Health Connect, nie powinna ich zapisywać z powrotem w Health Connect.

Podczas zapisywania danych, które zostały zaimportowane lub pochodzą z innego źródła, należy prawidłowo przypisać ich pochodzenie i metadane urządzenia źródłowego. Aby to zrobić, musisz podać te metadane dla każdego zapisu:

  • recordingMethod: w przypadku danych zapisywanych automatycznie lub ręcznie oczekujemy, że metoda zapisu zostanie zaktualizowana, aby odzwierciedlała typ zapisanej aktywności:
    • RECORDING_METHOD_AUTOMATICALLY_RECORDED: jeśli dane zostały zarejestrowane automatycznie, np. opaska fitness automatycznie wykryła, że użytkownik biegał.
    • RECORDING_METHOD_ACTIVELY_RECORDED: jeśli użytkownik rozpoczął nową aktywność, np. jazdę na rowerze, na urządzeniu do noszenia.
    • RECORDING_METHOD_MANUAL_ENTRY: jeśli użytkownik wpisał dane ręcznie.
  • device.type: musisz określić typ urządzenia, wybierając jeden z obsługiwanych typów Device.
  • device.manufacturer: producent urządzenia, np. „Fitbit”.
  • device.model: model urządzenia, np. „Charge 3”.
  • device.udi: (opcjonalnie) identyfikator urządzenia (DI) będący częścią niepowtarzalnego kodu identyfikacyjnego wyrobu (UDI) urządzenia medycznego. Szczegółowe informacje o wymaganych uprawnieniach i wytycznych dotyczących prywatności znajdziesz w przewodniku po metadanych.

Prawidłowe ustawienie metadanych ma kluczowe znaczenie dla przejrzystości danych i pomaga użytkownikom zrozumieć, skąd pochodzą ich informacje o zdrowiu. Szczegółowe informacje znajdziesz w przewodniku po metadanych Health Connect.

Jeśli dane w Twojej aplikacji zostały zaimportowane z innej aplikacji, to ta druga aplikacja jest odpowiedzialna za zapisywanie własnych danych w Health Connect.

Warto też wdrożyć logikę, która obsługuje wyjątki zapisu, takie jak dane poza zakresem lub błąd systemu wewnętrznego. Strategie wycofywania i ponawiania możesz stosować w mechanizmie planowania zadań. Jeśli zapisywanie w Health Connect ostatecznie się nie powiedzie, upewnij się, że aplikacja może przejść dalej. Nie zapomnij o rejestrowaniu i zgłaszaniu błędów, aby ułatwić diagnozowanie.

Podczas śledzenia danych możesz skorzystać z kilku sugestii, w zależności od tego, jak aplikacja zapisuje dane.

Obsługa stref czasowych

Podczas zapisywania danych związanych z czasem unikaj domyślnego ustawiania przesunięć na zoneOffset.UTC, ponieważ może to prowadzić do niedokładnych sygnatur czasowych, gdy użytkownicy znajdują się w innych strefach. Zamiast tego oblicz przesunięcie na podstawie rzeczywistej lokalizacji urządzenia. Strefę czasową urządzenia możesz pobrać za pomocą ZoneId.systemDefault().

val endTime = Instant.now()
val startTime = endTime.minus(Duration.ofDays(1))
val stepsRecords = mutableListOf<StepsRecord>()
var sampleTime = startTime
val minutesBetweenSamples = 15L
while (sampleTime < endTime) {
    // Get the default ZoneId then convert it to an offset
    val zoneOffset = ZoneOffset.systemDefault().rules.getOffset(sampleTime)
    stepsRecords += StepsRecord(
        startTime = sampleTime.minus(Duration.ofMinutes(minutesBetweenSamples)),
        startZoneOffset = zoneOffset,
        endTime = sampleTime,
        endZoneOffset = zoneOffset,
        count = Random.nextLong(1, 100),
        metadata = Metadata.activelyRecorded(device = Device(type = Device.TYPE_WATCH)),
    )
    sampleTime = sampleTime.plus(Duration.ofMinutes(minutesBetweenSamples))
}
healthConnectClient.insertRecords(
    stepsRecords
)

Więcej informacji znajdziesz w dokumentacji ZoneId.

Częstotliwość i szczegółowość zapisu

Podczas zapisywania danych w Health Connect używaj odpowiedniej rozdzielczości. Użycie odpowiedniej rozdzielczości pomaga zmniejszyć obciążenie pamięci masowej, a jednocześnie zachować spójne i dokładne dane. Rozdzielczość danych obejmuje 2 aspekty:

  • Częstotliwość zapisów: jak często aplikacja zapisuje nowe dane w Health Connect.
    • Zapisuj dane tak często, jak to możliwe, gdy dostępne są nowe dane, pamiętając jednocześnie o wydajności urządzenia.
    • Aby uniknąć negatywnego wpływu na żywotność baterii i inne aspekty wydajności, maksymalny odstęp między zapisami powinien wynosić 15 minut.
  • Szczegółowość zapisanych danych: jak często dane były próbkowane.
    • Możesz na przykład zapisywać próbki tętna co 5 sekund.
    • Nie każdy typ danych wymaga tej samej częstotliwości próbkowania. Aktualizowanie danych o liczbie kroków co sekundę nie przynosi większych korzyści w porównaniu z rzadszymi aktualizacjami, np. co 60 sekund.
    • Wyższe częstotliwości próbkowania mogą zapewnić użytkownikom bardziej szczegółowy i dokładny wgląd w dane dotyczące ich zdrowia i aktywności fizycznej. Częstotliwość próbkowania powinna zapewniać równowagę między szczegółowością a wydajnością.

Dodatkowe wskazówki

Podczas zapisywania danych postępuj zgodnie z tymi wskazówkami:

  • Podczas każdej synchronizacji zapisuj tylko nowe dane i dane zaktualizowane, które zostały zmodyfikowane od czasu ostatniej synchronizacji.
  • Podziel żądania na fragmenty, tak aby każde żądanie zapisu zawierało maksymalnie 1000 rekordów.
  • Ogranicz zadania, aby były uruchamiane tylko wtedy, gdy urządzenie jest nieaktywne, a bateria nie jest rozładowana.
  • W przypadku zadań w tle użyj biblioteki WorkManager, aby zaplanować zadania okresowe z maksymalnym okresem 15 minut.

Poniższy kod używa biblioteki WorkManager do planowania okresowych zadań w tle z maksymalnym czasem trwania wynoszącym 15 minut i elastycznym interwałem wynoszącym 5 minut. Ta konfiguracja jest ustawiana za pomocą klasy PeriodicWorkRequest.Builder.

val constraints = Constraints.Builder()
    .requiresBatteryNotLow()
    .requiresDeviceIdle(true)
    .build()

val writeDataWork = PeriodicWorkRequestBuilder<WriteDataToHealthConnectWorker>(
        15,
        TimeUnit.MINUTES,
        5,
        TimeUnit.MINUTES
    )
    .setConstraints(constraints)
    .build()

Aktywne śledzenie

Obejmuje to aplikacje, które śledzą zdarzenia, takie jak ćwiczenia i sen, lub dane wprowadzane ręcznie przez użytkownika, takie jak odżywianie. Te rekordy są tworzone, gdy aplikacja działa na pierwszym planie, lub w rzadkich przypadkach, gdy jest używana kilka razy dziennie.

Sprawdź, czy aplikacja nie utrzymuje Health Connect w stanie działania przez cały czas trwania zdarzenia.

Dane muszą być zapisywane w Health Connect na jeden z 2 sposobów:

  • Po zakończeniu wydarzenia zsynchronizuj dane z Health Connect. Możesz na przykład synchronizować dane, gdy użytkownik zakończy śledzoną sesję ćwiczeń.
  • Zaplanuj jednorazowe zadanie za pomocą WorkManager, aby zsynchronizować dane później.

Sprawdzone metody dotyczące szczegółowości i częstotliwości zapisów

Podczas zapisywania danych w Health Connect używaj odpowiedniej rozdzielczości. Użycie odpowiedniej rozdzielczości pomaga zmniejszyć obciążenie pamięci masowej, a jednocześnie zachować spójne i dokładne dane. Rozdzielczość danych obejmuje 2 aspekty:

  1. Częstotliwość zapisów: jak często aplikacja przesyła nowe dane do Health Connect. Zapisuj dane tak często, jak to możliwe, gdy dostępne są nowe dane, pamiętając o wydajności urządzenia. Aby uniknąć negatywnego wpływu na żywotność baterii i inne aspekty wydajności, maksymalny interwał między zapisami powinien wynosić 15 minut.

  2. Szczegółowość zapisanych danych: jak często były próbkowane dane, które zostały przesłane. Możesz na przykład zapisywać próbki tętna co 5 sekund. Nie każdy typ danych wymaga takiej samej częstotliwości próbkowania. Aktualizowanie danych o liczbie kroków co sekundę nie przynosi większych korzyści w porównaniu z rzadszymi aktualizacjami, np. co 60 sekund. Wyższe częstotliwości próbkowania mogą jednak zapewnić użytkownikom bardziej szczegółowy i dokładny wgląd w dane o zdrowiu i aktywności fizycznej. Częstotliwości próbkowania powinny zapewniać równowagę między szczegółowością a wydajnością.

Struktura rekordów danych serialu

W przypadku typów danych, które używają serii próbek, takich jak HeartRateRecord, ważne jest, aby prawidłowo ustrukturyzować rekordy. Zamiast tworzyć pojedynczy, całodniowy rekord, który jest stale aktualizowany, należy utworzyć kilka mniejszych rekordów, z których każdy reprezentuje określony przedział czasu.

Na przykład w przypadku danych o tętnie należy utworzyć nowy obiekt HeartRateRecord dla każdej minuty. Każdy rekord będzie miał czas rozpoczęcia i zakończenia obejmujący tę minutę i będzie zawierał wszystkie próbki tętna zarejestrowane w tym czasie.

Podczas regularnych synchronizacji z Health Connect (np. co 15 minut) aplikacja powinna zapisywać wszystkie jednominutowe rekordy utworzone od poprzedniej synchronizacji. Dzięki temu rozmiar rekordów jest łatwy do zarządzania, a wydajność zapytań i przetwarzania danych jest większa.

Ten przykład pokazuje, jak utworzyć obiekt HeartRateRecord dla jednej minuty, zawierający wiele próbek:

val startTime = Instant.now().truncatedTo(ChronoUnit.MINUTES)
val endTime = startTime.plus(Duration.ofMinutes(1))

val heartRateRecord = HeartRateRecord(
    startTime = startTime,
    startZoneOffset = ZoneOffset.UTC,
    endTime = endTime,
    endZoneOffset = ZoneOffset.UTC,
    // Create a new record every minute, containing a list of samples.
    samples = listOf(
        HeartRateRecord.Sample(
            time = startTime + Duration.ofSeconds(15),
            beatsPerMinute = 80,
        ),
        HeartRateRecord.Sample(
            time = startTime + Duration.ofSeconds(30),
            beatsPerMinute = 82,
        ),
        HeartRateRecord.Sample(
            time = startTime + Duration.ofSeconds(45),
            beatsPerMinute = 85,
        )
    ),
    metadata = Metadata.activelyRecorded(
        device = Device(type = Device.TYPE_WATCH)
    ))

Zapisuj dane monitorowane przez cały dzień

W przypadku danych zbieranych na bieżąco, takich jak liczba kroków, aplikacja powinna zapisywać je w Health Connect tak często, jak to możliwe, gdy tylko pojawią się nowe dane. Aby uniknąć negatywnego wpływu na żywotność baterii i inne aspekty wydajności, maksymalny odstęp między zapisami powinien wynosić 15 minut.

Tabela 1. Wskazówki dotyczące zapisywania danych

Typ danych

Jednostka

Oczekiwane

Przykład

Kroki

kroki

Co minutę

23:14–23:15 – 5 kroków

23:16–23:17 – 22 kroki

23:17–23:18 – 8 kroków

StepsCadence

kroki/min

Co minutę

23:14–23:15 – 5 kr./min

23:16–23:17 – 22 kr./min

23:17–23:18 – 8 kr./min

Pchnięcia wózka inwalidzkiego

pchnięcia

Co minutę

23:14–23:15 – 5 pchnięć

23:16–23:17 – 22 pchnięcia

23:17–23:18 – 8 pchnięć

ActiveCaloriesBurned

Kalorie

Co 15 minut

23:15–23:30 – 2 kalorie

23:30–23:45 – 25 kalorii

23:45–00:00 – 5 kalorii

TotalCaloriesBurned

Kalorie

Co 15 minut

23:15–23:30 – 16 kalorii

23:30 - 23:45 - 16 kalorii

23:45 - 00:00 - 16 kalorii

Odległość

km/min

Co minutę

23:14–23:15 – 0,008 km

23:16–23:16 – 0,021 km

23:17–23:18 – 0,012 km

ElevationGained

m

Co minutę

20:36 - 20:37 - 3.048m

20:39–20:40 – 3048 m

23:23 - 23:24 - 9.144m

PokonanePiętra

piętra

Co minutę

23:14–23:15 – 5 pięter

23:16 - 23:16 - 22 piętra

23:17 - 23:18 - 8 pięter

HeartRate

uderz./min

4 razy na minutę

6:11:15 – 55 uderz./min

6:11:30 – 56 uderz./min

6:11:45 – 56 uderz./min

6:12:00 – 55 uderz./min

ZmiennośćRytmuSercaRmssd

ms

Co minutę

6:11 – 23 ms

RespiratoryRate

oddechy/minutę

Co minutę

23:14–23:15 – 60 oddechów na minutę

23:16 - 23:16 - 62 oddechy na minutę

23:17–23:18 – 64 oddechy na minutę

OxygenSaturation

%

Co godzinę

6:11 - 95.208%

Dane powinny być zapisywane w Health Connect po zakończeniu treningu lub sesji snu. W przypadku aktywnego śledzenia, np. ćwiczeń i snu, lub ręcznego wprowadzania danych przez użytkownika, np. dotyczących odżywiania, te rekordy są tworzone, gdy aplikacja działa na pierwszym planie, lub w rzadkich przypadkach, gdy jest używana kilka razy dziennie.

Sprawdź, czy aplikacja nie utrzymuje Health Connect w stanie działania przez cały czas trwania wydarzenia.

Dane muszą być zapisywane w Health Connect na jeden z 2 sposobów:

  • Po zakończeniu wydarzenia zsynchronizuj dane z Health Connect. Możesz na przykład synchronizować dane, gdy użytkownik zakończy śledzoną sesję ćwiczeń.
  • Zaplanuj jednorazowe zadanie za pomocą WorkManagera, aby zsynchronizować dane później.

sesje ćwiczeń i snu,

Aplikacja powinna co najmniej spełniać wymagania podane w kolumnie Oczekiwane w tabeli 2. Jeśli to możliwe, postępuj zgodnie ze wskazówkami w kolumnie Najlepsze.

W tabeli poniżej pokazujemy, jak zapisywać dane podczas ćwiczeń:

Tabela 2. Wskazówki dotyczące zapisywania danych podczas sesji ćwiczeń

Typ danych

Jednostka

Oczekiwane

Pozdrawiam

Przykład

Kroki

kroki

Co minutę

Co sekundę

23:14–23:15 – 5 kroków

23:16–23:17 – 22 kroki

23:17–23:18 – 8 kroków

StepsCadence

kroki/min

Co minutę

Co sekundę

23:14–23:15 – 35 kr./min

23:16–23:17 – 37 kr./min

23:17–23:18 – 40 kr./min

Pchnięcia wózka inwalidzkiego

pchnięcia

Co minutę

Co sekundę

23:14–23:15 – 5 pchnięć

23:16–23:17 – 22 pchnięcia

23:17–23:18 – 8 pchnięć

CyclingPedalingCadence

obr./min

Co minutę

Co sekundę

23:14–23:15 – 65 obr./min

23:16–23:17 – 70 obr./min

23:17–23:18 – 68 obr./min

Zasilanie

waty

Co minutę

Co sekundę

23:14–23:15 – 250 watów

23:16–23:17 – 255 watów

23:17–23:18 – 245 W

Szybkość

km/min

Co minutę

Co sekundę

23:14–23:15 – 0,3 km/min

23:16–23:17 – 0,4 km/min

23:17–23:18 – 0,4 km/min

Odległość

km/m

Co minutę

Co sekundę

23:14–23:15 – 0,008 km

23:16–23:16 – 0,021 km

23:17–23:18 – 0,012 km

ActiveCaloriesBurned

Kalorie

Co minutę

Co sekundę

23:14–23:15 – 20 kalorii

23:16 - 23:17 - 20 kalorii

23:17 - 23:18 - 25 kalorii

TotalCaloriesBurned

Kalorie

Co minutę

Co sekundę

23:14–23:15 – 36 kalorii

23:16 - 23:17 - 36 kalorii

23:17 - 23:18 - 41 kalorii

ElevationGained

m

Co minutę

Co sekundę

20:36 - 20:37 - 3.048m

20:39–20:40 – 3048 m

23:23 - 23:24 - 9.144m

ExerciseRoutes

szer./dł./wys.

Co 3–5 sekund

Co sekundę

HeartRate

uderz./min

4 razy na minutę

Co sekundę

23:14–23:15 – 150 uderz./min

Tabela 3 pokazuje, jak zapisywać dane podczas sesji snu lub po jej zakończeniu:

Tabela 3. Wskazówki dotyczące zapisywania danych podczas sesji snu lub po niej

Typ danych

Jednostka

Oczekiwane próbki

Przykład

Fazy snu

etapie

Szczegółowy okres dla każdej fazy snu

23:46 - 23:50 - przebudzenie

23:50–23:56 – sen płytki

23:56 - 00:16 - sen głęboki

RestingHeartRate

uderz./min

Jedna wartość dziennie (oczekiwana rano)

6:11 - 60 uderz./min

OxygenSaturation

%

Jedna wartość dziennie (oczekiwana rano).

6:11 - 95.208%

Wydarzenia obejmujące wiele dyscyplin sportowych

To podejście wykorzystuje istniejące typy i struktury danych oraz weryfikuje zgodność z obecnymi implementacjami Health Connect i czytnikami danych. Jest to powszechne podejście stosowane przez platformy fitnessowe.

Dodatkowo poszczególne sesje, takie jak pływanie, jazda na rowerze i bieganie, nie są powiązane w Health Connect, a czytniki danych muszą wnioskować o relacji między tymi sesjami na podstawie ich bliskości czasowej. Przejścia między segmentami, np. z pływania na jazdę na rowerze, nie są wyraźnie reprezentowane.

Poniższy przykład pokazuje, jak zapisać dane dotyczące triathlonu:

val swimStartTime = Instant.parse("2024-08-22T08:00:00Z")
val swimEndTime = Instant.parse("2024-08-22T08:30:00Z")
val bikeStartTime = Instant.parse("2024-08-22T08:40:00Z")
val bikeEndTime = Instant.parse("2024-08-22T09:40:00Z")
val runStartTime = Instant.parse("2024-08-22T09:50:00Z")
val runEndTime = Instant.parse("2024-08-22T10:20:00Z")

val swimSession = ExerciseSessionRecord(
    startTime = swimStartTime,
    endTime = swimEndTime,
    exerciseType = ExerciseSessionRecord.EXERCISE_TYPE_SWIMMING_OPEN_WATER,
    metadata = Metadata.activelyRecorded(
        device = Device(type = Device.TYPE_WATCH)
    ),
    startZoneOffset = null,
    endZoneOffset = null,
)

val bikeSession = ExerciseSessionRecord(
    startTime = bikeStartTime,
    endTime = bikeEndTime,
    exerciseType = ExerciseSessionRecord.EXERCISE_TYPE_BIKING,
    metadata = Metadata.activelyRecorded(
        device = Device(type = Device.TYPE_WATCH)
    ),
    startZoneOffset = null,
    endZoneOffset = null,
)

val runSession = ExerciseSessionRecord(
    startTime = runStartTime,
    endTime = runEndTime,
    exerciseType = ExerciseSessionRecord.EXERCISE_TYPE_RUNNING,
    metadata = Metadata.activelyRecorded(
        device = Device(type = Device.TYPE_WATCH)
    ),
    startZoneOffset = null,
    endZoneOffset = null,
)

healthConnectClient.insertRecords(listOf(swimSession, bikeSession, runSession))

Obsługa wyjątków

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

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

Tabela 1. Wyjątki Health Connect i zalecane sprawdzone metody
Wyjątek Opis Zalecana sprawdzona metoda
IllegalStateException Wystąpiła jedna z tych sytuacji:

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

Zanim wyślesz żądanie, rozwiąż możliwe problemy z danymi wejściowymi. Zamiast używać zmiennych bezpośrednio w żądaniach, lepiej przypisz im wartości lub użyj ich jako parametrów w funkcji niestandardowej, aby móc stosować strategie obsługi błędów.
IOException Podczas odczytu i zapisu danych z dysku wystąpiły problemy. Aby uniknąć tego problemu, skorzystaj z tych sugestii:

  • Utwórz kopię zapasową wszystkich danych wejściowych użytkownika.
  • radzić sobie z problemami, które mogą wystąpić podczas operacji zapisu zbiorczego; Upewnij się na przykład, że proces przechodzi przez problem i wykonuje pozostałe operacje.
  • Zastosuj strategie ponawiania prób i wycofywania, aby rozwiązać problemy z żądaniami.

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

Na przykład aplikacja próbuje usunąć rekord z danym uid. Wyjątek jest jednak zgłaszany, gdy aplikacja po sprawdzeniu w usłudze podstawowej stwierdzi, że rekord nie istnieje.
Aby uniknąć tego problemu, skorzystaj z tych sugestii:

  • Regularnie synchronizuj magazyn danych aplikacji z Health Connect.
  • Zastosuj strategie ponawiania prób i wycofywania, aby rozwiązać problemy z żądaniami.

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