Verileri senkronize et

Bu kılavuz, Health Connect'in 1.1.0-alpha12 sürümüyle uyumludur.

Health Connect ile entegre olan çoğu uygulamanın, doğruluk kaynağı olarak hizmet veren kendi veri deposu vardır. Health Connect, uygulamanızı senkronize tutmanın yollarını sunar.

Senkronizasyon işlemi, uygulamanızın mimarisine bağlı olarak aşağıdaki işlemlerden bazılarını veya tümünü içerebilir:

  • Uygulamanızın veri deposundaki yeni veya güncellenmiş verileri Health Connect'e aktarın.
  • Health Connect'teki veri değişikliklerini uygulamanızın veri deposuna çekin.
  • Uygulamanızın veri deposunda silinen verileri Health Connect'ten silme

Her durumda, senkronizasyon işleminin hem Health Connect'i hem de uygulamanızın veri deposunu uyumlu tuttuğundan emin olun.

Health Connect'e veri aktarma

Senkronizasyon sürecinin ilk bölümünde, uygulamanızın veri deposundaki veriler Health Connect veri deposuna aktarılır.

Verilerinizi hazırlama

Uygulamanızın veri deposundaki kayıtlar genellikle aşağıdaki ayrıntıları içerir:

  • UUID gibi benzersiz bir anahtar.
  • Sürüm veya zaman damgası

Verileri Health Connect ile senkronize ederken yalnızca son senkronizasyondan bu yana eklenen, güncellenen veya silinen verileri tanımlayın ve bunları aktarın.

Health Connect'e veri yazma

Health Connect'e veri aktarmak için aşağıdaki adımları uygulayın:

  1. Uygulamanızın veri deposundaki yeni, güncellenmiş veya silinmiş girişlerin listesini alın.
  2. Her giriş için söz konusu veri türüne uygun bir Record nesnesi oluşturun. Örneğin, ağırlıkla ilgili veriler için bir WeightRecord nesnesi oluşturun.
  3. Her Record ile bir Metadata nesnesi belirtin. Bu, kaydı benzersiz şekilde tanımlamak için kullanabileceğiniz, uygulamanızın veri deposundaki bir kimlik olan clientRecordId'yı içerir. Bunun için mevcut benzersiz anahtarınızı kullanabilirsiniz. Verileriniz sürüm oluşturma işlemine tabi tutuluyorsa verilerinizde kullanılan sürüm oluşturma işlemiyle uyumlu bir clientRecordVersion de sağlayın. Sürüm oluşturulmamışsa alternatif olarak geçerli zaman damgasının Long değerini kullanabilirsiniz.

    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. insertRecords kullanarak Health Connect'e veri ekleme/güncelleme Veri ekleme/güncelleme işlemi, Health Connect veri deposunda clientRecordId değerleri bulunduğu ve clientRecordVersion değeri mevcut değerden yüksek olduğu sürece Health Connect'teki mevcut verilerin üzerine yazılacağı anlamına gelir. Aksi takdirde, eklenen veriler yeni veri olarak yazılır.

    healthConnectClient.insertRecords(arrayListOf(record))
    

Veri beslemeyle ilgili pratik hususlar hakkında bilgi edinmek için Veri yazma ile ilgili en iyi uygulamalara göz atın.

Health Connect kimliklerini saklama

Uygulamanız Health Connect'ten de veri okuyorsa verileri ekledikten sonra kayıtlar için Health Connect id'ı saklayın. Health Connect'ten veri değişikliklerini çektiğinizde silme işlemlerini gerçekleştirmek için bu id gereklidir.

insertRecords işlevi, id değerlerinin listesini içeren bir InsertRecordsResponse döndürür. Kayıt kimliklerini almak ve saklamak için yanıtı kullanın.

val response = healthConnectClient.insertRecords(arrayListOf(record))

for (recordId in response.recordIdsList) {
    // Store recordId to your app's datastore
}

Health Connect'ten veri çekme

Senkronizasyon sürecinin ikinci bölümünde, Health Connect'teki veri değişiklikleri uygulamanızın veri deposuna aktarılır. Veri değişiklikleri güncellemeleri ve silme işlemlerini içerebilir.

Değişiklik jetonu alma

Health Connect'ten çekilecek değişikliklerin listesini almak için uygulamanızın Değişiklikler jetonlarını takip etmesi gerekir. Hem veri değişikliklerinin listesini hem de bir sonraki sefer kullanılacak yeni bir Changes jetonunu döndürmek için Changes isteğinde bulunurken bunları kullanabilirsiniz.

Changes jetonu almak için getChangesToken işlevini çağırın ve gerekli veri türlerini sağlayın.

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

Veri değişikliklerini kontrol etme

Changes jetonu aldığınıza göre, tüm Changes öğelerini almak için bu jetonu kullanın. Kullanılabilir veri değişiklikleri olup olmadığını kontrol eden tüm Değişiklikler'i incelemek için bir döngü oluşturmanızı öneririz. Şu adımları uygulayabilirsiniz:

  1. getChanges işlevini jetonu kullanarak çağırıp Değişiklikler listesini alın.
  2. Her değişikliğin türünün UpsertionChange veya DeletionChange olup olmadığını kontrol edin ve gerekli işlemleri yapın.
    • UpsertionChange için, verileri yeniden içe aktarmadığınızdan emin olmak üzere yalnızca arama uygulamasından gelmeyen değişiklikleri yapın.
  3. Bir sonraki Changes jetonunu yeni jetonunuz olarak atayın.
  4. Değişiklik kalmayana kadar 1-3. adımları tekrarlayın.
  5. Sonraki jetonu saklayın ve gelecekteki bir içe aktarma işlemi için ayırın.
suspend fun processChanges(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
}

Veri çekmeyle ilgili pratik hususlar hakkında bilgi edinmek için Verileri senkronize etme ile ilgili en iyi uygulamaları inceleyin.

Veri değişikliklerini işleme

Uygulamanızın veri deposundaki değişiklikleri yansıtın. UpsertionChange için kaydı güncellemek üzere metadata kaynağından id ve lastModifiedTime öğelerini kullanın. DeletionChange için kaydı silmek üzere sağlanan id seçeneğini kullanın. Bunun için Store Health Connect IDs (Health Connect kimliklerini saklama) başlıklı makalede belirtildiği gibi id kaydını saklamış olmanız gerekir.

Health Connect'teki verileri silme

Bir kullanıcı kendi verilerini uygulamanızdan sildiğinde verilerin Health Connect'ten de kaldırıldığından emin olun. Bunu yapmak için deleteRecords kullanın. Bu işlev, kayıt türü ve id ile clientRecordId değerlerinin listesini alır. Bu sayede, silinecek birden fazla veriyi toplu olarak işlemek kolaylaşır. timeRangeFilter alan bir deleteRecords alternatifi de mevcuttur.

Giyilebilir cihazlardan düşük gecikmeli senkronizasyon

Giyilebilir fitness cihazındaki verileri Health Connect ile düşük gecikmeyle senkronize etmek için CompanionDeviceService kullanın. Bu yaklaşım, BLE GATT bildirimlerini veya göstergelerini destekleyen ve Android 8.0 (API seviyesi 26) ya da sonraki sürümleri hedefleyen cihazlarda çalışır. CompanionDeviceService, uygulamanızın giyilebilir cihazlardan veri almasına ve bu verileri Health Connect'e yazmasına olanak tanır. Bu işlem, uygulama zaten çalışmıyorken bile yapılabilir. BLE en iyi uygulamaları hakkında daha fazla bilgi için Bluetooth Düşük Enerjiye genel bakış başlıklı makaleyi inceleyin.

Cihazı ilişkilendirme

İlk olarak, uygulamanız CompanionDeviceManager kullanarak kullanıcının giyilebilir cihazı uygulamanızla ilişkilendirmesi için tek seferlik bir işlem yapmasını sağlamalıdır. Bu, uygulamanıza cihazla etkileşim kurmak için gerekli izinleri verir. Daha fazla bilgi için Yardımcı cihaz eşleme başlıklı makaleyi inceleyin.

Hizmeti manifestte tanımlayın

Ardından, uygulamanızın manifest dosyasında CompanionDeviceService iznini beyan edin. AndroidManifest.xml dosyanıza aşağıdakileri ekleyin:

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

CompanionDeviceService oluşturma

Son olarak, CompanionDeviceService öğesini genişleten bir sınıf oluşturun. Bu hizmet, giyilebilir cihaza bağlantıyı yönetir ve BLE GATT geri çağırmaları aracılığıyla veri alır. Yeni veriler alındığında hemen Health Connect'e yazılır.

import android.companion.CompanionDeviceService
import android.bluetooth.BluetoothGatt
import android.bluetooth.BluetoothGattCallback
import android.bluetooth.BluetoothGattCharacteristic
import androidx.health.connect.client.permission.HealthPermission
import androidx.health.connect.client.HealthConnectClient
import androidx.health.connect.client.records.HeartRateRecord
import androidx.health.connect.client.records.StepsRecord
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.launch

class MyWearableService : CompanionDeviceService() {

   // A coroutine scope for handling suspend functions like writing to Health Connect
   private val serviceScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
   private var healthConnectClient: HealthConnectClient? = null
   private var bluetoothGatt: BluetoothGatt? = null

   // This is called by the system when your wearable connects
   override fun onDeviceAppeared(address: String) {
       super.onDeviceAppeared(address)
       healthConnectClient = HealthConnectClient.getOrCreate(this)

       serviceScope.launch {
           // Check which permissions have been granted before subscribing to data from the wearable.
           // A service cannot request permissions, so your app must have already requested
           // and been granted them from an Activity.
           val granted = healthConnectClient?.permissionController?.getGrantedPermissions()

           // ... set up your GATT connection here ...

           // Once connected, subscribe to notifications for the data types you have
           // permission to write.
           if (granted?.contains(HealthPermission.getWritePermission(HeartRateRecord::class)) == true) {
               // subscribeToHeartRate(bluetoothGatt)
           }
       }
   }

   // The core of your low-latency pipeline is the BLE callback
   private val gattCallback = object : BluetoothGattCallback() {
       override fun onCharacteristicChanged(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, value: ByteArray) {
           super.onCharacteristicChanged(gatt, characteristic, value)

           // 1. Instantly receive the data
           val rawData = value

           // 2. Parse the data from the wearable
           val healthData = parseWearableData(rawData) // Your custom parsing logic

           // 3. Immediately process it. For simplicity, this example writes
           //    directly to Health Connect. A real-world app might write to its
           //    own datastore first and then sync with Health Connect.
           serviceScope.launch {
               writeToHealthConnect(healthData)
           }
       }
   }

   private suspend fun writeToHealthConnect(healthData: HealthData) {
       val records = prepareHealthConnectRecords(healthData) // Convert to Health Connect records
       try {
           healthConnectClient?.insertRecords(records)
       } catch (e: Exception) {
           // Handle exceptions
       }
   }

   // This is called by the system when your wearable disconnects
   override fun onDeviceDisappeared(address: String) {
       super.onDeviceDisappeared(address)
       // Clean up your GATT connection and other resources
       bluetoothGatt?.close()
   }
}

Verileri senkronize etmeyle ilgili en iyi uygulamalar

Aşağıdaki faktörler senkronizasyon sürecini etkiler.

Jetonun son kullanma tarihi

Kullanılmayan Changes jetonu 30 gün içinde sona erdiğinden, bu tür durumlarda bilgi kaybını önleyen bir senkronizasyon stratejisi kullanmanız gerekir. Stratejiniz aşağıdaki yaklaşımları içerebilir:

  • Uygulama veri deponuzda, en son kullanılan ve Health Connect'ten gelen id verisini içeren kaydı arayın.
  • Health Connect'ten belirli bir zaman damgasıyla başlayan kayıtları isteyin, ardından bunları uygulamanızın veri deposuna ekleyin veya güncelleyin.
  • Bir sonraki ihtiyaç duyulduğunda kullanmak üzere ayırmak için değişiklik jetonu isteyin.

Önerilen değişiklik yönetimi stratejileri

Uygulamanız geçersiz veya süresi dolmuş Changes jetonları alıyorsa mantığınızdaki uygulamasına bağlı olarak aşağıdaki yönetim stratejilerini kullanmanızı öneririz:

  • Tüm verileri okuyun ve tekilleştirin. Bu en ideal stratejidir.
    • Uygulamaların Health Connect'ten en son veri okuduğu zamanın zaman damgasını saklar.
    • Jetonun süresi dolduğunda en son zaman damgasından veya son 30 gün içinde tüm veriler yeniden okunur. Ardından, tanımlayıcıları kullanarak daha önce okunan verilerle tekilleştirin.
    • Veri güncellemeleri için gerekli olduğundan Client-ID'leri uygulamanız önerilir.
  • Yalnızca son okuma zaman damgasından sonraki verileri okuyun. Bu durum, değişiklik jetonunun süresinin dolduğu zamanlarda bazı veri uyuşmazlıklarına neden olur ancak bu süre birkaç saatten birkaç güne kadar sürebilir.
    • Uygulamaların Health Connect'ten en son veri okuduğu zamanın zaman damgasını saklar.
    • Jetonun süresi dolduğunda, bu zaman damgasından itibaren tüm verileri okur.
  • Son 30 gün içindeki verileri silip okuyun. Bu, ilk entegrasyonda olanlarla daha yakından ilişkilidir.
    • Uygulamanın son 30 gün içinde Health Connect'ten okuduğu tüm verileri silme
    • Silindikten sonra bu verilerin tamamı tekrar okunur.
  • Son 30 gün içindeki verileri tekilleştirme olmadan okuma. Bu, en az ideal stratejidir ve kullanıcılara yinelenen verilerin gösterilmesine neden olur.
    • Uygulamanın son 30 gün içinde Health Connect'ten okuduğu tüm verileri siler.
    • Yinelenen girişlere izin verin.

Veri türü değişiklikleri jetonları

Uygulamanız birden fazla veri türünü bağımsız olarak kullanıyorsa her veri türü için ayrı değişiklik jetonları kullanın. Yalnızca bu veri türleri birlikte veya hiç kullanılmıyorsa Değişiklikleri Senkronize Etme API'si ile birden fazla veri türünün bulunduğu bir liste kullanın.

Ön planda okuma işlemleri

Uygulamalar yalnızca ön plandayken Health Connect'teki verileri okuyabilir. Health Connect'ten veri senkronize ederken Health Connect'e erişim herhangi bir noktada kesintiye uğrayabilir. Örneğin, uygulamanız Health Connect'ten büyük miktarda veri okurken senkronizasyonun ortasında meydana gelen kesintileri işlemeli ve uygulama bir sonraki açılışında devam etmelidir.

Arka planda okuma

Uygulamanızın arka planda çalışmasını ve Health Connect'teki verileri okumasını isteyebilirsiniz. Background Read iznini isterseniz kullanıcınız, uygulamanıza arka planda veri okuma erişimi verebilir.

İçe aktarma zamanlamaları

Uygulamanız yeni veriler hakkında bildirim alamadığından yeni verileri iki noktada kontrol edin:

  • Uygulamanız her ön planda etkin hale geldiğinde. Bu durumda, yaşam döngüsü etkinliklerini kullanın.
  • Uygulamanız ön planda kalırken belirli aralıklarla. Yeni veriler olduğunda kullanıcıları bilgilendirerek değişiklikleri yansıtmak için ekranlarını güncellemelerine olanak tanır.