Ten przewodnik jest zgodny z wersją Health Connect 1.1.0-alpha12.
W tym przewodniku omówiliśmy proces zapisywania i aktualizowania danych w Health Connect.
Konfigurowanie struktury danych
Zanim zapiszemy dane, musimy najpierw skonfigurować rekordy. Istnieje ponad 50 typów danych, z których każdy ma swoją 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. Licznik kroków to powszechny pomiar na platformach związanych ze zdrowiem, kondycją i wellness.
Ten 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. Obejmuje ona wiele opcjonalnych pól składników odżywczych, od węglowodanów po witaminy. Każdy punkt danych przedstawia 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 Mass
, a energy
– w jednostkach Energy
.
Ten przykład pokazuje, jak ustawić dane dotyczące wartości odżywczej 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 serii. Przykładem jest typ danych Tętno, który rejestruje serię próbek bicia serca wykrytych między odczytami.
W przypadku tego typu danych parametr samples
jest reprezentowany przez listę próbek tętna. Każda próbka zawiera wartość beatsPerMinute
i wartość time
.
Ten 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)
))
Zapisywanie danych
Jednym z częstych procesów w Health Connect jest zapisywanie danych. Aby dodać rekordy, użyj insertRecords
.
Ten przykład pokazuje, jak zapisać liczbę kroków wstawiania danych:
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 chcesz zmienić co najmniej 1 rekord, zwłaszcza gdy musisz zsynchronizować bazę danych aplikacji z danymi z Health Connect, możesz zaktualizować swoje dane. Istnieją 2 sposoby aktualizowania dotychczasowych danych. Zależy to od identyfikatora używanego do znajdowania rekordów.
Metadane
Warto najpierw zbadać klasę Metadata
, ponieważ jest to konieczne podczas aktualizowania danych. W momencie utworzenia każdy typ danych Record
w Health Connect ma pole metadata
. W przypadku synchronizacji istotne są te właściwości:
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 element Record przechowuje też informację o ostatniej modyfikacji rekordu.Health Connect wypełnia to automatycznie. |
clientRecordId
|
Każdy element Record może mieć powiązany unikalny identyfikator, który służy jako odniesienie w danych aplikacji.
Tę wartość podaje aplikacja. |
clientRecordVersion
|
Jeśli rekord ma wartość clientRecordId , możesz użyć wartości clientRecordVersion , aby dane były zsynchronizowane z wersją w puli danych aplikacji.Tę wartość podaje aplikacja. |
Aktualizacja za pomocą identyfikatora rekordu
Aby zaktualizować dane, najpierw przygotuj potrzebne rekordy. W razie potrzeby wprowadź zmiany w rekordach. Następnie wywołaj funkcję updateRecords
, aby wprowadzić zmiany.
Ten przykład pokazuje, jak zaktualizować dane. W tym celu każda pozycja ma wartości przesunięcia strefy czasowej skorygowane na czas 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
}
}
Wgrywanie i aktualizowanie za pomocą identyfikatora rekordu klienta
Jeśli używasz opcjonalnych wartości identyfikatora rekordu klienta i wersji rekordu klienta, zalecamy użycie wartości insertRecords
zamiast updateRecords
.
Funkcja insertRecords
umożliwia upsertowanie danych.
Jeśli dane istnieją w Health Connect na podstawie podanego zbioru identyfikatorów rekordów klienta, zostaną zastąpione. W przeciwnym razie są one zapisywane jako nowe dane.
Ten scenariusz jest przydatny, gdy chcesz zsynchronizować dane z danych aplikacji z Health Connect.
Ten przykład pokazuje, jak wykonać operację upsert na danych pobranych z 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 aktualizacji danych obejmuje wersję rekordu klienta, Health Connect przeprowadza porównania w wartościach clientRecordVersion
. Jeśli wersja z wstawionych danych jest wyższa niż wersja z dotychczasowych danych, następuje aktualizacja. W przeciwnym razie proces zignoruje zmianę, a wartość pozostanie taka sama.
Aby uwzględnić wersjonowanie w danych, musisz podać wartość Metadata.clientRecordVersion
z wartością Long
określoną na podstawie logiki 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.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, zapobiegając nieoczekiwanym przypadkom nadpisywania danych. W tym przypadku musisz ręcznie podać wyższą wartość.
Sprawdzone metody zapisywania danych
Aplikacje mogą zapisywać w Health Connect tylko dane pochodzące z własnych źródeł.
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ż zaimplementować logikę, która obsługuje wyjątki podczas zapisywania, takie jak dane poza zakresem lub błąd wewnętrzny systemu. Możesz zastosować swoje strategie wycofywania i ponownego próbowania w mechanizmie planowania zadań. Jeśli zapisywanie danych w Health Connect nie powiedzie się, sprawdź, czy aplikacja może przejść przez ten punkt eksportu. Aby ułatwić diagnozę, nie zapomnij odnotować i zgłosić błędów.
Podczas śledzenia danych możesz postępować zgodnie z kilkoma sugestiami, w zależności od sposobu zapisywania danych przez aplikację.
Śledzenie pasywne
Dotyczy to również aplikacji, które wykonują pasywne śledzenie aktywności fizycznej lub stanu zdrowia, np. ciągłe rejestrowanie kroków lub tętna w tle.
Aplikacja musi okresowo zapisywać dane w Health Connect w następujący sposób:
- Podczas każdej synchronizacji zapisuj tylko nowe dane i zaktualizowane dane, które zostały zmodyfikowane od czasu ostatniej synchronizacji.
- Podziel żądania na fragmenty, aby na każde żądanie zapisu przypadało maksymalnie 1000 rekordów.
- Użyj polecenia
WorkManager
, aby zaplanować okresowe zadania w tle z okresem co najmniej 15 minut. Ogranicz zadania do działania tylko wtedy, gdy urządzenie jest nieaktywne i nie ma niskiego poziomu naładowania baterii.
val constraints = Constraints.Builder() .requiresBatteryNotLow() .requiresDeviceIdle(true) .build() val writeDataWork = PeriodicWorkRequestBuilder<WriteDataToHealthConnectWorker>( 15, TimeUnit.MINUTES, 5, TimeUnit.MINUTES ) .setConstraints(constraints) .build()
Aktywna lokalizacja
Dotyczy to aplikacji, które śledzą dane na podstawie zdarzeń, takich jak ćwiczenia i sen, lub danych wprowadzanych ręcznie przez użytkownika, np. dotyczących odżywiania. Te rekordy są tworzone, gdy aplikacja jest na pierwszym planie, lub w rzadkich przypadkach, gdy jest używana kilka razy dziennie.
Upewnij się, że aplikacja nie utrzymuje Health Connect w stanie działania przez cały czas trwania zdarzenia.
Dane muszą być zapisywane w Health Connect w jeden z 2 sposobów:
- Po zakończeniu wydarzenia zsynchronizuj dane z Health Connect. Na przykład zsynchronizuj dane, gdy użytkownik zakończy śledzenie sesji ćwiczeń.
- Zaplanuj jednorazowe zadanie za pomocą
WorkManager
, aby zsynchronizować dane w późniejszym terminie.
Sprawdzone metody dotyczące szczegółowości i częstotliwości zapisów
Podczas zapisywania danych w Health Connect używaj odpowiedniej rozdzielczości. Korzystanie z odpowiedniej rozdzielczości pomaga zmniejszyć obciążenie pamięci, a jednocześnie zachować spójne i prawidłowe dane. Rozdzielczość danych obejmuje 2 elementy:
- Częstotliwość zapisywania: określa, jak często aplikacja przesyła nowe dane do Health Connect. Na przykład zapisywać nowe dane co 15 minut.
- Szczegółowość zapisywanych danych: jak często dane, które są przesyłane, były próbkowane. Na przykład zapisuj próbki tętna co 5 s. Nie wszystkie typy danych wymagają tej samej częstotliwości próbkowania. Aktualizowanie danych o liczbie kroków co sekundę nie przynosi wielu korzyści w porównaniu z rzadszym odświeżaniem, np. co 60 sekund. Jednak wyższe częstotliwości próbkowania mogą zapewnić użytkownikom bardziej szczegółowy wgląd w ich dane dotyczące zdrowia i kondycji. Częstotliwości próbkowania powinny zapewniać równowagę między szczegółowością a wydajnością.
zapisywanie danych monitorowanych przez cały dzień,
W przypadku danych zbieranych w ciągłym trybie, takich jak liczba kroków, aplikacja powinna zapisywać dane w Health Connect co najmniej co 15 minut w ciągu dnia.
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 |
Kadencja kroków |
kroki/min |
Co minutę |
23:14 – 23:15 – 5 km/h 23:16 – 23:17 – 22 spm 23:17 – 23:18 – 8 spm |
Pchnięcia wózka inwalidzkiego |
naciśnięcia |
Co minutę |
23:14 – 23:15 – 5 push 23:16 – 23:17 – 22 pushe 23:17 – 23:18 – 8 kliknięć |
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 |
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 |
Przebyte przewyższenie |
min |
Co minutę |
20:36 - 20:37 - 3,048 m 20:39 – 20:40 – 3,048 m 23:23 – 23:24 – 9,144 m |
Zdobyte pię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 |
Co minutę |
6:11 godz. – 55 uderzeń na minutę |
HeartRateVariabilityRmssd |
ms |
Co minutę |
6:11 rano – 23 ms |
RespiratoryRate |
oddechów/min |
Co minutę |
23:14 – 23:15 – 60 oddechów na minutę 23:16 - 23:16 - 62 oddechów/minutę 23:17 – 23:18 – 64 oddechy na minutę |
OxygenSaturation |
% |
Co godzinę |
6:11 – 95,208% |
Zapisuj sesje
Dane powinny być zapisywane w Health Connect po zakończeniu treningu lub sesji snu.
Sprawdzoną metodą jest nagrywanie sesji snu lub ćwiczeń za pomocą urządzenia do nagrywania i odpowiednich metadanych, w tym RecordingMethod
.
Aplikacja powinna być zgodna z zaleceniami podanymi w kolumnie „Oczekiwane”. W miarę możliwości postępuj zgodnie z „najlepszymi” wytycznymi.
Dane śledzone podczas ć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 |
Kadencja kroków |
kroki/min |
Co minutę |
Co sekundę |
23:14-23:15 – 35 spm 23:16 - 23:17 - 37 spm 23:17 – 23:18 – 40 spm |
Pchnięcia wózka inwalidzkiego |
naciśnięcia |
Co minutę |
Co sekundę |
23:14–23:15 – 5 kliknięć 23:16 – 23:17 – 22 pushe 23:17 – 23:18 – 8 kliknięć |
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 W 23:16 – 23:17 – 255 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 |
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 |
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 |
Przebyte przewyższenie |
min |
Co minutę |
Co sekundę |
20:36 - 20:37 - 3,048 m 20:39 – 20:40 – 3,048 m 23:23 – 23:24 – 9,144 m |
ExerciseRoutes |
lat/lng/alt |
Co 3–5 sekund |
Co sekundę |
|
HeartRate |
uderz./min |
Co minutę |
Co sekundę |
23:14–23:15 – 150 uderzeń na minutę 23:16 - 23:17 -152 bpm 23:17 – 23:18 – 155 uderzeń na minutę |
Dane gromadzone podczas snu
Typ danych |
Jednostka |
Oczekiwane próbki |
Przykład |
Etapy snu |
etap |
szczegółowy okres w poszczególnych fazach snu, |
23:46 – 23:50 – przebudzenie 23:50 – 23:56 – sen płytki 23:56 – 00:16 – sen głęboki |
RestingHeartRate |
uderz./min |
pojedyncza wartość dzienna (oczekuje się ją z samego rana); |
6:11 godz. – 60 uderzeń na minutę |
OxygenSaturation |
% |
pojedyncza wartość dzienna (oczekuje się ją z samego rana); |
6:11 – 95,208% |