Synchronizuj dane

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

Większość aplikacji zintegrowanych z Health Connect ma własny magazyn danych, który służy jako źródło informacji. Health Connect umożliwia synchronizowanie aplikacji.

W zależności od architektury aplikacji proces synchronizacji może obejmować niektóre lub wszystkie z tych działań:

  • Przesyłaj nowe lub zaktualizowane dane z magazynu danych aplikacji do Health Connect.
  • pobierać zmiany danych z Health Connect do magazynu danych aplikacji;
  • Usuwaj dane z Health Connect, gdy zostaną usunięte z magazynu danych aplikacji.

W każdym przypadku upewnij się, że proces synchronizacji zapewnia zgodność danych w Health Connect i magazynie danych aplikacji.

Przekazywanie danych do Health Connect

Pierwszą częścią procesu synchronizacji jest przekazanie danych z magazynu danych aplikacji do magazynu danych Health Connect.

Przygotowywanie danych

Zwykle rekordy w magazynie danych aplikacji zawierają te informacje:

  • unikalny klucz, np. UUID;
  • Wersja lub sygnatura czasowa.

Podczas synchronizowania danych z Health Connect identyfikuj i przesyłaj tylko te dane, które zostały wstawione, zaktualizowane lub usunięte od czasu ostatniej synchronizacji.

Zapisywanie danych w Health Connect

Aby przekazywać dane do Health Connect, wykonaj te czynności:

  1. pobrać listę nowych, zaktualizowanych lub usuniętych wpisów z magazynu danych aplikacji;
  2. Dla każdego wpisu utwórz obiekt Record odpowiedni dla danego typu danych. Możesz na przykład utworzyć obiekt WeightRecord dla danych związanych z wagą.
  3. Określ obiekt Metadata dla każdego elementu Record. Obejmuje to clientRecordId, czyli identyfikator z magazynu danych aplikacji, którego możesz użyć do jednoznacznego zidentyfikowania rekordu. Możesz w tym celu użyć istniejącego unikalnego klucza. Jeśli Twoje dane są wersjonowane, podaj też clientRecordVersion, który jest zgodny z wersjonowaniem używanym w Twoich danych. Jeśli nie jest on wersjonowany, możesz użyć wartości Long bieżącej sygnatury czasowej.

    val recordVersion = 0L
    // Specify as needed
    // The clientRecordId is an ID that you choose for your record. This
    // is often the same ID you use in your app's datastore.
    val clientRecordId = "<your-record-id>"
    
    val record = WeightRecord(
        metadata = Metadata.activelyRecorded(
            clientRecordId = clientRecordId,
            clientRecordVersion = recordVersion,
            device = Device(type = Device.TYPE_SCALE)
        ),
        weight = Mass.kilograms(62.0),
        time = Instant.now(),
        zoneOffset = ZoneOffset.UTC,
    )
    healthConnectClient.insertRecords(listOf(record))

  4. Aktualizuj lub wstaw dane w Health Connect za pomocą insertRecords. Aktualizacja danych oznacza, że wszystkie istniejące dane w Health Connect zostaną zastąpione, o ile wartości clientRecordId istnieją w magazynie danych Health Connect, a wartość clientRecordVersion jest wyższa niż istniejąca wartość. W przeciwnym razie dane zostaną zapisane jako nowe.

    healthConnectClient.insertRecords(arrayListOf(record))

Aby dowiedzieć się więcej o praktycznych aspektach przekazywania danych, zapoznaj się ze sprawdzonymi metodami dotyczącymi zapisu danych.

Przechowywanie identyfikatorów Health Connect

Jeśli aplikacja odczytuje też dane z Health Connect, po przesłaniu rekordów przechowuj ich id z Health Connect. Potrzebujesz tego uprawnienia (id), aby przetwarzać usunięcia podczas pobierania zmian danych z Health Connect.

Funkcja insertRecords zwraca InsertRecordsResponse, który zawiera listę wartości id. Użyj odpowiedzi, aby uzyskać identyfikatory rekordów i je zapisać.

val response = healthConnectClient.insertRecords(listOf(record))
for (recordId in response.recordIdsList) {
    // Store recordId to your app's datastore
}

Pobieranie danych z Health Connect

Drugą częścią procesu synchronizacji jest pobieranie zmian danych z Health Connect do magazynu danych aplikacji. Zmiany danych mogą obejmować aktualizacje i usunięcia.

Uzyskiwanie tokena zmian

Aby uzyskać listę zmian do pobrania z Health Connect, aplikacja musi śledzić tokeny Changes. Możesz ich używać, gdy wysyłasz żądanie Changes, aby zwrócić zarówno listę zmian danych, jak i nowy token Changes, który zostanie użyty następnym razem.

Aby uzyskać token Changes, wywołaj getChangesToken i podaj wymagane typy danych.

val changesToken = healthConnectClient.getChangesToken(
    ChangesTokenRequest(recordTypes = setOf(WeightRecord::class))
)

Sprawdzanie zmian danych

Gdy masz już token Changes, użyj go, aby uzyskać wszystkie zmiany. Zalecamy utworzenie pętli, która będzie sprawdzać wszystkie zmiany pod kątem dostępnych zmian danych. Oto kolejne kroki:

  1. Wywołaj getChanges, używając tokena, aby uzyskać listę zmian.
  2. Sprawdź, czy typ każdej zmiany to UpsertionChange czy DeletionChange, i wykonaj niezbędne operacje.
    • W przypadku UpsertionChange uwzględniaj tylko zmiany, które nie pochodzą z aplikacji do dzwonienia, aby nie importować ponownie danych.
  3. Przypisz następny token Changes jako nowy token.
  4. Powtarzaj kroki 1–3, aż nie będzie już żadnych zmian.
  5. Zapisz następny token i zarezerwuj go na potrzeby przyszłego importu.

suspend fun processChanges(context: Context, token: String): String {
    var nextChangesToken = token
    do {
        val response = healthConnectClient.getChanges(nextChangesToken)
        response.changes.forEach { change ->
            when (change) {
                is UpsertionChange ->
                    if (change.record.metadata.dataOrigin.packageName != context.packageName) {
                        processUpsertionChange(change)
                    }
                is DeletionChange -> processDeletionChange(change)
            }
        }
        nextChangesToken = response.nextChangesToken
    } while (response.hasMore)
    // Return and store the changes token for use next time.
    return nextChangesToken
}

Aby dowiedzieć się więcej o praktycznych aspektach pobierania danych, zapoznaj się ze sprawdzonymi metodami synchronizowania danych.

Przetwarzanie zmian danych

Odzwierciedl zmiany w magazynie danych aplikacji. W przypadku UpsertionChange użyj id i lastModifiedTime z metadata, aby wykonać operację upsert na rekordzie. W przypadku DeletionChange użyj podanego id, aby usunąć rekord. Wymaga to zapisania rekordu id zgodnie z opisem w sekcji Przechowywanie identyfikatorów Health Connect.

Usuwanie danych z Health Connect

Gdy użytkownik usunie swoje dane z Twojej aplikacji, upewnij się, że zostały one również usunięte z Health Connect. Aby to zrobić, użyj deleteRecords. Ta metoda przyjmuje typ rekordu oraz listę wartości id i clientRecordId, co ułatwia zbiorcze usuwanie wielu danych. Dostępna jest też alternatywna metoda deleteRecords, która przyjmuje timeRangeFilter.

Synchronizacja z urządzeń do noszenia z małym opóźnieniem

Aby synchronizować dane z urządzenia do noszenia do Health Connect z niskim opóźnieniem, użyj CompanionDeviceService. To podejście działa na urządzeniach, które obsługują powiadomienia lub wskazania BLE GATT i są przeznaczone na Androida 8.0 (poziom API 26) lub nowszego. CompanionDeviceService umożliwia aplikacji odbieranie danych z urządzeń do noszenia i zapisywanie ich w Health Connect, nawet gdy aplikacja nie jest uruchomiona. Więcej informacji o sprawdzonych metodach dotyczących BLE znajdziesz w omówieniu Bluetooth Low Energy.

Powiąż urządzenie

Najpierw aplikacja musi przeprowadzić użytkownika przez jednorazowy proces powiązania urządzenia do noszenia z aplikacją za pomocą interfejsu CompanionDeviceManager. Dzięki temu aplikacja uzyska uprawnienia niezbędne do interakcji z urządzeniem. Więcej informacji znajdziesz w artykule Parowanie urządzenia towarzyszącego.

Zadeklaruj usługę w pliku manifestu

Następnie zadeklaruj CompanionDeviceService w pliku manifestu aplikacji. Dodaj do pliku AndroidManifest.xml te informacje:

<manifest ...>
   <application ...>
       <service
           android:name=".MyWearableService"
           android:exported="true"
           android:permission="android.permission.BIND_COMPANION_DEVICE_SERVICE">
           <intent-filter>
               <action android:name="android.companion.CompanionDeviceService" />
           </intent-filter>
       </service>
   </application>
</manifest>

Tworzenie CompanionDeviceService

Na koniec utwórz klasę, która rozszerza CompanionDeviceService. Ta usługa obsługuje połączenie z urządzeniem do noszenia i odbiera dane za pomocą wywołań zwrotnych BLE GATT. Gdy otrzymywane są nowe dane, są one natychmiast zapisywane w Health Connect.

private val serviceScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
private var healthConnectClient: HealthConnectClient? = null
private var bluetoothGatt: BluetoothGatt? = null

override fun onDeviceAppeared(address: String) {
    super.onDeviceAppeared(address)
    healthConnectClient = HealthConnectClient.getOrCreate(this)

    serviceScope.launch {
        val granted = healthConnectClient?.permissionController?.getGrantedPermissions()

        // 1. Check permissions ONCE when the device connects
        if (granted?.contains(HealthPermission.getWritePermission(HeartRateRecord::class)) ?: false) {
            // This is where you'd actually start the Bluetooth connection
            // bluetoothGatt = gattCallback.connect(...)
        }

        // 2. Do your initial database read
        readExerciseSessionAndRoute()
    }
}

private val gattCallback = object : BluetoothGattCallback() {
    override fun onCharacteristicChanged(
        gatt: BluetoothGatt,
        characteristic: BluetoothGattCharacteristic,
        value: ByteArray
    ) {
        super.onCharacteristicChanged(gatt, characteristic, value)

        // 3. ONLY process the incoming data here
        val rawData = value

        serviceScope.launch {
            // parseWearableData(rawData)
            // insertExerciseRoute() or writeToHealthConnect()
        }
    }
}

Sprawdzone metody synchronizowania danych

Na proces synchronizacji wpływają te czynniki:

Wygaśnięcie tokena

Nieużywany token Changes wygasa po 30 dniach, dlatego musisz użyć strategii synchronizacji, która zapobiega utracie informacji w takim przypadku. Strategia może obejmować te podejścia:

  • Wyszukaj w magazynie danych aplikacji ostatnio wykorzystany rekord, który ma też id z Health Connect.
  • Poproś o rekordy z Health Connect, które zaczynają się od określonej sygnatury czasowej, a następnie wstaw je lub zaktualizuj w magazynie danych aplikacji.
  • Poproś o token zmian, aby zarezerwować go na następny raz, gdy będzie potrzebny.

Strategie zarządzania zalecanymi zmianami

Jeśli Twoja aplikacja otrzymuje nieprawidłowe lub wygasłe tokeny Changes, zalecamy zastosowanie tych strategii zarządzania w zależności od ich zastosowania w logice:

  • Odczytywanie i usuwanie duplikatów wszystkich danych. To najlepsza strategia.
    • przechowywać sygnaturę czasową ostatniego odczytu danych z Health Connect;
    • Po wygaśnięciu tokena ponownie odczytaj wszystkie dane od ostatniej sygnatury czasowej lub z ostatnich 30 dni. Następnie usuń duplikaty z wcześniej odczytanych danych, używając identyfikatorów.
    • Najlepiej jest wdrożyć identyfikatory klientów, ponieważ są one wymagane do aktualizacji danych.
  • Odczytywanie tylko danych od ostatniej sygnatury czasowej odczytu. Powoduje to pewne rozbieżności w danych w okresie wygaśnięcia tokena zmian, ale ten okres jest krótszy i może trwać od kilku godzin do kilku dni.
    • przechowywać sygnaturę czasową ostatniego odczytu danych z Health Connect;
    • Po wygaśnięciu tokena odczytaj wszystkie dane od tej sygnatury czasowej.
  • Usuwanie i odczytywanie danych z ostatnich 30 dni Jest to bardziej zbliżone do tego, co dzieje się podczas pierwszej integracji.
    • Usuń wszystkie dane odczytane przez aplikację z Health Connect w ciągu ostatnich 30 dni.
    • Po usunięciu odczytaj ponownie wszystkie te dane.
  • Odczytywanie danych z ostatnich 30 dni bez usuwania duplikatów. Jest to najmniej idealna strategia, która powoduje wyświetlanie użytkownikom zduplikowanych danych.
    • Usuń wszystkie dane odczytane przez aplikację z Health Connect w ciągu ostatnich 30 dni.
    • Zezwalaj na zduplikowane wpisy.

Tokeny zmian typu danych

Jeśli aplikacja korzysta z więcej niż 1 typu danych niezależnie, użyj osobnych tokenów zmian dla każdego typu danych. Listy wielu typów danych używaj z interfejsem Changes Sync API tylko wtedy, gdy te typy danych są używane razem lub wcale.

Odczyty na pierwszym planie

Aplikacje mogą odczytywać dane z Health Connect tylko wtedy, gdy działają na pierwszym planie. Podczas synchronizowania danych z Health Connect dostęp do tej aplikacji może zostać w każdej chwili przerwany. Aplikacja musi na przykład obsługiwać przerwy w trakcie synchronizacji, gdy odczytuje dużą ilość danych z Health Connect, i kontynuować proces po ponownym otwarciu.

Odczyty w tle

Możesz poprosić o to, aby aplikacja działała w tle i odczytywała dane z Health Connect. Jeśli poprosisz o uprawnienie Background Read, użytkownik może przyznać aplikacji dostęp do odczytu danych w tle.

Importowanie kodów czasowych

Aplikacja nie może otrzymywać powiadomień o nowych danych, dlatego sprawdzaj, czy są nowe dane, w 2 momentach:

  • Za każdym razem, gdy aplikacja staje się aktywna na pierwszym planie. W takim przypadku użyj zdarzeń cyklu życia.
  • okresowo, gdy aplikacja pozostaje na pierwszym planie; Powiadamiaj użytkowników o dostępności nowych danych, aby mogli zaktualizować ekran i zobaczyć zmiany.