Zapisywanie danych

Ten przewodnik jest zgodny z wersją Health Connect 1.1.0-alpha12.

W tym przewodniku opisujemy proces zapisywania i aktualizowania danych w Health Connect.

Obsługa wartości zerowych

Niektóre typy danych, takie jak kroki, odległość czy kalorie, mogą mieć wartość 0. Wartości zerowe należy zapisywać tylko wtedy, gdy odzwierciedlają one prawdziwą nieaktywność, gdy użytkownik miał na sobie urządzenie. Nie zapisuj wartości zerowych, jeśli urządzenie nie było noszone, brakuje danych lub bateria się wyczerpała. W takich przypadkach pomiń rekord, aby uniknąć wprowadzania w błąd.

Konfigurowanie struktury danych

Zanim zapiszemy dane, musimy najpierw skonfigurować rekordy. W przypadku ponad 50 rodzajów danych każdy z nich 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 powszechnie stosowany pomiar na platformach związanych ze zdrowiem, aktywnością fizyczną i dobrym samopoczuciem.

Poniższy przykład pokazuje, jak ustawić dane dotyczące liczby kroków:

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

val stepsRecord = StepsRecord(
    count = 120,
    startTime = startTime,
    endTime = endTime,
    startZoneOffset = ZoneOffset.UTC,
    endZoneOffset = ZoneOffset.UTC,
    metadata = Metadata.autoRecorded(
        device = Device(type = Device.TYPE_WATCH)
    )
)

Rekordy z jednostkami miary

Health Connect może przechowywać wartości wraz z jednostkami miary, aby zapewnić dokładność. Przykładem jest typ danych Nutrition, który jest obszerny i wszechstronny. Zawiera 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ą podawane w jednostkach masy, a energy – w jednostce 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.manualEntry(
        device = Device(type = Device.TYPE_PHONE)
    )
)

Rekordy z danymi serii

Health Connect może przechowywać listę danych szeregowych. Przykładem jest typ danych Tętno, który rejestruje serię próbek uderzeń 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 wartość 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.autoRecorded(
        device = Device(type = Device.TYPE_WATCH)
    ))

Prośba użytkownika o uprawnienia

Po utworzeniu instancji klienta aplikacja musi poprosić użytkownika o uprawnienia. Użytkownicy muszą mieć możliwość przyznania lub odmowy przyznania uprawnień w dowolnym momencie.

Aby to zrobić, utwórz zestaw uprawnień dla wymaganych typów danych. Sprawdź, czy uprawnienia w zestawie są najpierw zadeklarowane w pliku manifestu Androida.

// Create a set of permissions for required data types
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ż przyznane wymagane uprawnienia. Jeśli nie, użyj createRequestPermissionResultContract, aby poprosić o te uprawnienia. Wyświetli się ekran uprawnień Health Connect.

// Create the permissions launcher
val requestPermissionActivityContract = PermissionController.createRequestPermissionResultContract()

val requestPermissions = registerForActivityResult(requestPermissionActivityContract) { granted ->
  if (granted.containsAll(PERMISSIONS)) {
    // Permissions successfully granted
  } else {
    // Lack of required permissions
  }
}

suspend fun checkPermissionsAndRun(healthConnectClient: HealthConnectClient) {
  val granted = healthConnectClient.permissionController.getGrantedPermissions()
  if (granted.containsAll(PERMISSIONS)) {
    // Permissions already granted; proceed with inserting or reading data
  } else {
    requestPermissions.launch(PERMISSIONS)
  }
}

Użytkownicy mogą w dowolnym momencie przyznawać i wycofywać uprawnienia, dlatego aplikacja musi okresowo sprawdzać, czy uprawnienia zostały przyznane, i obsługiwać sytuacje, w których uprawnienia zostaną utracone.

Zapisywanie danych

Jednym z najczęstszych procesów w Health Connect jest zapisywanie danych. Aby dodać rekordy, użyj ikony insertRecords.

Ten przykład pokazuje, jak zapisywać dane dotyczące liczby kroków:

suspend fun insertSteps(healthConnectClient: HealthConnectClient) {
    val endTime = Instant.now()
    val startTime = endTime.minus(Duration.ofMinutes(5))
    try {
        val stepsRecord = StepsRecord(
            count = 120,
            startTime = startTime,
            endTime = endTime,
            startZoneOffset = ZoneOffset.UTC,
            endZoneOffset = ZoneOffset.UTC,
            metadata = Metadata.autoRecorded(
                device = Device(type = Device.TYPE_WATCH)
            )
        )
        healthConnectClient.insertRecords(listOf(stepsRecord))
    } catch (e: Exception) {
        // Run error handling here
    }
}

Aktualizowanie danych

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

Metadane

Warto najpierw przyjrzeć się klasie Metadata, ponieważ jest ona niezbędna podczas aktualizowania danych. Każdy Record w Health Connect ma pole metadata. Poniższe właściwości są istotne w przypadku synchronizacji:

Właściwości Opis
id Każdy 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 Record może mieć unikalny identyfikator, który będzie służyć jako odniesienie w pamięci danych aplikacji.
Aplikacja podaje tę wartość.
clientRecordVersion Jeśli rekord zawiera clientRecordId, można użyć clientRecordVersion, aby dane były zsynchronizowane z wersją w pamięci danych aplikacji.
Aplikacja podaje tę wartość.

Aktualizacja po przeczytaniu według zakresu czasu

Aby zaktualizować dane, najpierw przygotuj potrzebne rekordy. Wprowadź w razie potrzeby 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
    }
}

Wstawianie lub aktualizowanie za pomocą identyfikatora rekordu klienta

Jeśli używasz opcjonalnych wartości Identyfikator rekordu klienta i Wersja rekordu klienta, zalecamy używanie znaku insertRecords zamiast znaku updateRecords.

Funkcja insertRecords może wstawiać dane lub je aktualizować. Jeśli dane istnieją w Health Connect na podstawie podanego zestawu identyfikatorów rekordów klienta, zostaną zastąpione. W przeciwnym razie jest zapisywana jako nowe dane. Ten scenariusz jest przydatny, gdy musisz synchronizować dane z pamięci danych aplikacji z Health Connect.

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

suspend fun pullStepsFromDatastore() : 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.autoRecorded(
            clientRecordId = "Your client record ID",
            device = Device(type = Device.TYPE_WATCH)
        ),
        // Assign more parameters for this record
    )
    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ływać te funkcje w głównym wątku.

upsertSteps(healthConnectClient, pullStepsFromDatastore())

Sprawdzanie wartości w wersji rekordu klienta

Jeśli proces wstawiania danych obejmuje wersję rekordu klienta, Health Connect przeprowadza porównanie wartości w clientRecordVersion. Jeśli wersja w wstawionych danych jest wyższa niż wersja w danych, które już istnieją, nastąpi aktualizacja. W przeciwnym razie proces zignoruje zmianę, a wartość pozostanie bez zmian.

Aby uwzględnić w danych wersjonowanie, musisz podać wartość Metadata.clientRecordVersion z wartością Long na podstawie logiki wersjonowania.

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.manualEntry(
        clientRecordId = "Your supplied record ID",
        clientRecordVersion = 0L, // Your supplied record version
        device = Device(type = Device.TYPE_WATCH)
    )
)

Operacje upsert nie zwiększają automatycznie wartości version, gdy występują zmiany, co zapobiega nieoczekiwanym przypadkom nadpisywania danych. W takim przypadku musisz ręcznie podać wyższą wartość.

Ogólne wskazówki

Aplikacje mogą zapisywać w Health Connect tylko dane pochodzące z własnych źródeł.

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

Warto też wdrożyć logikę obsługującą wyjątki zapisu, takie jak dane wykraczające poza zakres lub błąd systemu wewnętrznego. Możesz zastosować strategie wycofywania i ponawiania w mechanizmie planowania zadań. Jeśli zapisywanie danych w Health Connect ostatecznie się nie powiedzie, upewnij się, że aplikacja może przejść ten punkt eksportu. Nie zapomnij rejestrować i zgłaszać błędów, aby ułatwić diagnozę.

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

Obsługa stref czasowych

Podczas zapisywania rekordów opartych na czasie 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ą funkcji ZoneId.systemDefault().

val endTime = Instant.now()
val startTime = endTime.minus(java.time.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(java.time.Duration.ofMinutes(minutesBetweenSamples)),
        startZoneOffset = zoneOffset,
        endTime = sampleTime,
        endZoneOffset = zoneOffset,
        count = Random.nextLong(1, 100),
        metadata = Metadata.unknownRecordingMethod(),
    )
    sampleTime = sampleTime.plus(java.time.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żywanie odpowiedniej rozdzielczości pomaga zmniejszyć obciążenie pamięci masowej przy jednoczesnym zachowaniu spójnych i dokładnych danych. Rozdzielczość danych obejmuje 2 aspekty:

  • Częstotliwość zapisywania: jak często aplikacja zapisuje nowe dane w Health Connect.
    • Zapisuj dane tak często, jak to możliwe, gdy są dostępne nowe dane, pamiętając 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 próbkowano dane.
    • Na przykład zapisuj 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 niż aktualizowanie ich rzadziej, np. co 60 sekund.
    • Wyższe częstotliwości próbkowania mogą zapewnić użytkownikom bardziej szczegółowy wgląd w dane dotyczące zdrowia i aktywności fizycznej. Częstotliwości próbkowania powinny zachowywać równowagę między szczegółowością a wydajnością.

Dodatkowe wskazówki

Podczas wpisywania danych postępuj zgodnie z tymi wytycznymi:

  • Podczas każdej synchronizacji zapisuj tylko nowe i zaktualizowane dane, które zostały zmodyfikowane od czasu ostatniej synchronizacji.
  • Dziel żądania na części, tak aby każde żądanie zapisu zawierało maksymalnie 1000 rekordów.
  • Ogranicz zadania tak, aby były wykonywane tylko wtedy, gdy urządzenie jest nieaktywne i nie ma niskiego poziomu baterii.
  • W przypadku zadań w tle używaj WorkManager do planowania okresowych zadań z maksymalnym okresem 15 minut.

Poniższy kod wykorzystuje WorkManager do planowania okresowych zadań w tle z maksymalnym okresem 15 minut i elastycznym interwałem 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, np. informacje o odżywianiu. Te rekordy są tworzone, gdy aplikacja jest na pierwszym planie lub w rzadkich przypadkach, gdy jest używana kilka razy dziennie.

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

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

  • Synchronizuj dane z Health Connect po zakończeniu wydarzenia. Na przykład synchronizuj dane, gdy użytkownik zakończy śledzoną sesję ćwiczeń.
  • Zaplanuj jednorazowe zadanie za pomocą WorkManager, aby później zsynchronizować dane.

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żywanie odpowiedniej rozdzielczości pomaga zmniejszyć obciążenie pamięci masowej przy jednoczesnym zachowaniu spójnych i dokładnych danych. 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 są dostępne nowe dane, pamiętając 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.

  2. Szczegółowość zapisywanych danych: jak często próbkowane były dane przesyłane do usługi. Na przykład zapisuj 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 niż aktualizowanie ich rzadziej, 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 dotyczące zdrowia i aktywności fizycznej. Częstotliwości próbkowania powinny zachowywać równowagę między szczegółowością a wydajnością.

Struktura rekordów danych serii

W przypadku typów danych, które wykorzystują serię próbek, np. HeartRateRecord, ważne jest prawidłowe strukturyzowanie rekordów. Zamiast tworzyć jeden długi rekord, który jest stale aktualizowany, utwórz kilka mniejszych rekordów, z których każdy będzie reprezentować określony przedział czasu.

Na przykład w przypadku danych o tętnie należy utworzyć nowy 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 tej minucie.

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

W tym przykładzie pokazujemy, jak utworzyć HeartRateRecord dla pojedynczej minuty zawierającej 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.autoRecorded(
        device = Device(type = Device.TYPE_WATCH)
    ))

Zapisywanie danych monitorowanych przez cały dzień

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

Tabela 1. Wskazówki dotyczące pisania 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 naciśnięć

23:16–23:17 – 22 naciśnięcia

23:17–23:18 – 8 naciśnięć

KalorieSpalonePodczasAktywności

Kalorie

Co 15 minut

23:15–23:30 – 2 kalorie

23:30–23:45 – 25 kalorii

23:45–00:00 – 5 kalorii

SumaSpalonychKalorii

Kalorie

Co 15 minut

23:15–23:30 – 16 kalorii

23:30–23:45 – 16 kalorii

23:45–00:00 – 16 kalorii

Dystans

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 – 3,048 m

23:23 - 23:24 - 9.144m

FloorsClimbed

piętra

Co minutę

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

23:16 - 23:16 - 22 floors

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

HeartRate

uderz./min

4 razy na minutę

6:11:15 – 55 uderz./min

6:11:30 – 56 uderzeń na minutę

6:11:45 – 56 uderz./min

6:12:00 – 55 uderzeń na minutę

HeartRateVariabilityRmssd

ms

Co minutę

6:11 – 23 ms

RespiratoryRate

oddechy/minutę

Co minutę

23:14 - 23:15 - 60 oddechów/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. informacji o odżywianiu, te rekordy są tworzone, gdy aplikacja jest na pierwszym planie lub w rzadkich przypadkach, gdy jest używana kilka razy dziennie.

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

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

  • Synchronizuj dane z Health Connect po zakończeniu wydarzenia. Na przykład synchronizuj dane, gdy użytkownik zakończy śledzoną sesję ćwiczeń.
  • Zaplanuj jednorazowe zadanie za pomocą WorkManager, aby później zsynchronizować dane.

Sesje ćwiczeń i snu

Aplikacja powinna co najmniej spełniać wymagania podane w kolumnie Oczekiwane w tabeli 2. W miarę możliwości postępuj zgodnie z wskazówkami w kolumnie Najlepsze.

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

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 spm

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 naciśnięć

23:16–23:17 – 22 naciśnięcia

23:17–23:18 – 8 naciśnięć

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

Moc

waty

Co minutę

Co sekundę

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

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

23:17–23:18 – 245 wató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

Dystans

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

KalorieSpalonePodczasAktywności

Kalorie

Co minutę

Co sekundę

23:14–23:15 – 20 kalorii

23:16–23:17 – 20 kalorii

23:17–23:18 – 25 kalorii

SumaSpalonychKalorii

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 – 3,048 m

23:23 - 23:24 - 9.144m

ExerciseRoutes

szerokość/długość/wysokość

Co 3–5 sekund

Co sekundę

HeartRate

uderz./min

4 razy na minutę

Co sekundę

23:14–23:15 – 150 uderzeń na minutę

Tabela 3 pokazuje, jak zapisywać dane podczas sesji snu lub po niej:

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

Typ danych

Jednostka

Oczekiwane próbki

Przykład

Fazy snu

etap,

Szczegółowy okres czasu w każdej fazie 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ść dzienna (oczekiwana z rana)

6:11 – 60 uderzeń na minutę

OxygenSaturation

%

Jedna wartość dzienna (oczekiwana z rana)

6:11 - 95.208%

Wydarzenia obejmujące wiele dyscyplin sportowych

W tym podejściu wykorzystywane są istniejące typy i struktury danych, a także weryfikowana jest zgodność z obecnymi implementacjami Health Connect i czytnikami danych. Jest to powszechne podejście stosowane przez platformy fitness.

Dodatkowo poszczególne sesje, takie jak pływanie, jazda na rowerze i bieganie, nie są ze sobą powiązane w Health Connect, a aplikacje odczytujące dane muszą wnioskować o związku 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 przedstawione.

Poniższy przykład pokazuje, jak zapisywać 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.autoRecorded(
      device = Device(type = Device.TYPE_WATCH)
    )
)

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

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

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

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 ma nieprawidł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 można było stosować strategie obsługi błędów.
IOException Występują problemy z odczytywaniem i zapisywaniem danych na dysku. Aby uniknąć tego problemu, wykonaj te czynności:

  • Twórz kopie zapasowe wszystkich danych wprowadzonych przez użytkownika.
  • Musi być w stanie poradzić sobie z wszelkimi problemami, które wystąpią podczas operacji zapisu zbiorczego. Na przykład upewnij się, że proces przechodzi dalej 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 sprawdzi w usłudze bazowej, że rekord nie istnieje.
Aby uniknąć tego problemu, wykonaj te czynności:

  • Regularnie synchronizuj dane między bazą 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.