本指南適用於 Health Connect 1.1.0-alpha12 以上版本。
大多數與健康資料同步整合的應用程式都有其專屬的資料儲存庫,用來做為可靠資料來源。健康資料同步提供多種方式,可確保應用程式保持同步。
視應用程式架構而定,同步處理程序可能涉及下列部分或所有動作:
- 將應用程式資料儲存庫中的全新/更新資料饋送至健康資料同步。
- 從健康資料同步提取資料變更,並套用至應用程式的資料儲存庫。
- 在應用程式的資料儲存庫中刪除資料時,也從健康資料同步刪除該資料。
無論是上述哪一種情況,都請確保同步處理程序能使健康資料同步和應用程式儲存庫的資料保持一致。
將資料饋送至健康資料同步
同步處理程序的第一階段,是將應用程式資料儲存庫中的資料饋送至健康資料同步資料儲存庫。
準備資料
應用程式資料儲存庫中的記錄通常包含下列詳細資料:
- 專屬金鑰,例如
UUID。 - 版本或時間戳記。
將資料同步至健康資料同步時,請找出並只提供自上次同步後插入、更新或刪除的資料。
將資料寫入健康資料同步
如要將資料饋送至健康資料同步,請執行下列步驟:
- 從應用程式的資料儲存庫取得全新、更新或刪除的項目清單。
- 針對每個項目,建立適合該資料類型的
Record物件。舉例來說,您可以為體重相關資料建立WeightRecord物件。 請為每個
Record指定Metadata物件。這包括clientRecordId,這是應用程式資料儲存庫中的 ID,可用於識別特定記錄。您可以使用現有的專屬金鑰。如果資料有版本編號,也請提供與資料版本編號一致的clientRecordVersion。如果資料尚未建立版本,您可以使用目前時間戳記的Long值做為替代項目。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))
使用
insertRecords將資料新增或更新至健康資料同步。更新/插入資料的含意是,只要健康資料同步資料儲存庫中有clientRecordId值,且clientRecordVersion高於現有的值,那麼健康資料同步中的所有現有資料都會遭到覆寫。否則,更新/插入的資料會以新資料的形式寫入。healthConnectClient.insertRecords(arrayListOf(record))
如要瞭解饋送資料的具體注意事項,請參閱「寫入資料」的最佳做法。
儲存健康資料同步 ID
如果應用程式也會從 健康資料同步 讀取資料,請在新增或更新記錄後,儲存記錄的 健康資料同步 id。從健康資料同步提取資料變更時,您需要使用這個 id 處理刪除作業。
insertRecords 函式會傳回包含 id 值清單的 InsertRecordsResponse。請使用回應取得並儲存記錄 ID。
val response = healthConnectClient.insertRecords(listOf(record)) for (recordId in response.recordIdsList) { // Store recordId to your app's datastore }
從健康資料同步提取資料
同步處理程序的第二階段,是將任何資料相關變更從健康資料同步提取至應用程式的資料儲存庫。資料相關變更可能包括更新和刪除行為。
取得變更權杖
如要取得清單,瞭解要從健康資料同步提取哪些變更,應用程式需要先追蹤「變更」權杖。您可以在要求「變更」時使用這些權杖,以便同時傳回資料變更清單,以及將於下次使用的全新「變更」權杖。
如要取得「變更」權杖,請呼叫 getChangesToken,並提供必要的資料類型。
val changesToken = healthConnectClient.getChangesToken( ChangesTokenRequest(recordTypes = setOf(WeightRecord::class)) )
檢查資料變更
取得「變更」權杖後,請使用該權杖來取得所有「變更」。建議您建立可通過所有「變更」的迴圈,藉此檢查是否有可用的資料變更。操作步驟如下:
- 使用權杖呼叫
getChanges,取得變更清單。 - 檢查各項變更的類型是
UpsertionChange或DeletionChange,並執行必要作業。- 如果是
UpsertionChange,請只取用非來自通話應用程式的變更,確保不會重新匯入資料。
- 如果是
- 指派下一個「變更」權杖做為新權杖。
- 重複執行步驟 1 到 3,直到沒有剩餘的「變更」為止。
- 儲存下一個權杖,供日後匯入時使用。
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 }
如要瞭解提取資料的具體注意事項,請參閱「同步處理資料」的最佳做法。
處理資料變更
您可以讓應用程式的資料儲存庫反映相關變更。如果是 UpsertionChange,請使用 id 和源自其 metadata 的 lastModifiedTime 新增或更新記錄。如果是 DeletionChange,請使用提供的 id 來刪除記錄。您必須按照「儲存健康資料同步 ID」一節所述,儲存記錄 id。
刪除健康資料同步資料
當使用者從您的應用程式刪除自己的資料時,請確保這些資料也會從 健康資料同步 中移除。請使用 deleteRecords 執行這項操作。這會取得記錄類型以及 id 和 clientRecordId 值的清單,方便您批次處理多筆要刪除的資料。您也可以使用替代的 deleteRecords,其可接受 timeRangeFilter。
從穿戴式裝置同步處理資料,延遲時間短
如要將穿戴式健身裝置的資料同步到健康資料同步,且延遲時間短,請使用 CompanionDeviceService。這個方法適用於支援 BLE GATT 通知或指示,且指定 Android 8.0 (API 級別 26) 以上版本的裝置。CompanionDeviceService 可讓應用程式從穿戴式裝置接收資料,並寫入健康資料同步,即使應用程式尚未執行也沒問題。如要進一步瞭解 BLE 最佳做法,請參閱「藍牙低功耗總覽」。
建立裝置關聯
首先,應用程式必須引導使用者完成一次性程序,使用 CompanionDeviceManager 將穿戴式裝置與應用程式建立關聯。這會授予應用程式與裝置互動所需的權限。詳情請參閱「配對裝置配對」。
在資訊清單中宣告服務
接著,在應用程式的資訊清單檔案中宣告 CompanionDeviceService。請將以下內容新增到 AndroidManifest.xml:
<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
最後,建立擴充 CompanionDeviceService 的類別。這項服務會處理與穿戴式裝置的連線,並透過 BLE GATT 回呼接收資料。收到新資料時,系統會立即寫入 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() } } }
同步處理資料的最佳做法
以下因素會影響同步處理程序。
權杖到期
未使用的變更權杖會在 30 天內到期,因此請務必採用適當的同步策略,避免在這類情況下遺失資訊。策略可包含以下方法:
- 搜尋應用程式資料儲存庫,找出最近取用且含有健康資料同步
id的記錄。 - 要求 Health Connect 提供特定時間戳記之後的記錄,並在應用程式資料儲存庫中插入或更新該記錄。
- 要求提供變更權杖,並保留至下次需要時使用。
建議的變更管理策略
如果應用程式收到無效或過期的「變更」權杖,建議您根據邏輯適用情形,採用下列管理策略:
- 讀取及簡化所有資料。這是最理想的策略。
- 儲存上次從 健康資料同步 讀取資料時的時間戳記。
- 權杖過期時,從最近的時間戳記或過去 30 天重新讀取所有資料。接著請根據先前讀取的資料,使用 ID 簡化這些資料。
- 在理想情況下,請實作用戶端 ID,因為必須使用用戶端 ID 才能更新資料。
- 僅讀取上次讀取時間戳記後的資料。這會導致變更權杖到期前後的資料出現落差,但時間範圍會較短,可能需要數小時至數天。
- 儲存上次從 健康資料同步 讀取資料時的時間戳記。
- 在權杖到期時,讀取這個時間戳記後的所有資料。
- 刪除再讀取過去 30 天的資料。這更貼近第一項整合作業的情況。
- 刪除應用程式在過去 30 天內從健康資料同步讀取的所有資料。
- 刪除完成後,再次讀取所有資料。
- 讀取過去 30 天的資料,且不刪除重複資料。這是最不理想的策略,且會導致使用者看到重複的資料。
- 刪除應用程式在過去 30 天內從健康資料同步讀取的所有資料。
- 允許重複的項目。
資料類型變更權杖
如果應用程式可獨立取用多種資料類型,請針對每種資料類型使用單獨的變更權杖。請只在同時取用或完全不取用多種資料類型時,搭配使用資料類型清單與 Changes Sync API。
前景讀取
應用程式只有在前景運作時,才能從健康資料同步讀取資料。從健康資料同步同步處理資料時,健康資料同步的存取作業隨時可能中斷。舉例來說,應用程式從健康資料同步讀取大量資料時,必須能處理同步作業中途發生的干擾,並在下次開啟應用程式時繼續這項作業。
背景讀取
您可以要求讓應用程式在背景執行,並從健康資料同步讀取資料。如果您要求 Background Read 權限,使用者可以授予應用程式在背景讀取資料的權限。
匯入時間
如果應用程式無法在資料新增時收到通知,則應在以下兩個時間點檢查新資料:
- 每當應用程式開始在前景運作時。請在這種情況下使用生命週期事件。
- 應用程式持續在前景運作的期間。請定期檢查新資料。每當有新資料時,請通知使用者更新畫面,反映變更情形。