同步處理資料

本指南適用於 1.1.0-alpha12 版的「健康資料同步」。

大多數與健康資料同步整合的應用程式都有自己的資料儲存庫,做為可靠資料來源。「健康資料同步」提供多種方式,可確保應用程式保持同步。

視應用程式架構而定,同步處理程序可能包含下列部分或所有動作:

  • 將應用程式儲存庫中的全新資料或更新資料動態饋給至「健康資料同步」。
  • 將資料變更從「健康資料同步」提取至應用程式的資料儲存庫。
  • 在應用程式的資料儲存庫中刪除資料時,也從「健康資料同步」刪除該資料。

無論是上述哪一種情況,都請您確保同步處理程序能使 Health Connect 和應用程式儲存庫的資料保持一致。

將資料饋送至「健康資料同步」

同步處理程序的第一階段,就是將應用程式儲存庫的資料饋送至 Health Connect 資料儲存庫。

準備資料

應用程式資料儲存庫中的記錄通常包含下列詳細資料:

  • 專屬金鑰,例如 UUID
  • 版本或時間戳記。

將資料同步至「健康資料同步」時,請只找出並動態饋給自上次同步後插入、更新或刪除的資料。

將資料寫入「健康資料同步」

如要將資料饋送至「健康資料同步」,請執行下列步驟:

  1. 從應用程式的資料儲存庫取得新增、更新或刪除的項目清單。
  2. 針對每個項目,建立適合該資料類型的 Record 物件。舉例來說,您可以為體重相關資料建立 WeightRecord 物件。
  3. 為每個 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))
    
    
  4. 使用 insertRecords 將資料更新/插入至「健康資料同步」。更新/插入資料的含意是,只要 Health Connect 資料儲存庫中有 clientRecordId 值,且 clientRecordVersion 高於現有的值,那麼 Health Connect 中的所有現有資料都會遭到覆寫。但如果不是的話,則會以新資料的形式寫入更新/插入的資料。

    healthConnectClient.insertRecords(arrayListOf(record))
    

如要瞭解饋送資料的具體注意事項,請參閱「寫入資料」的最佳做法。

儲存健康資料同步 ID

如果應用程式也會從「健康資料同步」讀取資料,請在更新/插入記錄後,儲存記錄的「健康資料同步」id。從「健康資料同步」提取資料變更時,您需要這個 id 來處理刪除作業。

insertRecords 函式會傳回包含 id 值清單的 InsertRecordsResponse。請使用回應取得並儲存記錄 ID。

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

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

從「健康資料同步」提取資料

同步處理程序的第二階段,是將任何資料相關變更從「健康資料同步」提取至應用程式的資料儲存庫。資料相關變更可能包括更新和刪除行為。

取得變更權杖

如要取得清單,瞭解要從健康資料同步提取哪些變更,您的應用程式需要先追蹤「變更」權杖。您可以在要求「變更」時使用這些權杖,以便同時傳回資料變更清單,以及將於下次使用的全新「變更」權杖。

如要取得「變更」權杖,請呼叫 getChangesToken,並提供必要的資料類型。

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

檢查資料變更

取得「變更」權杖後,請使用該權杖來取得所有「變更」。建議您建立可通過所有「變更」的迴圈,藉此檢查是否有可用的資料變更。操作步驟如下:

  1. 使用權杖呼叫 getChanges,取得「變更」清單。
  2. 檢查各項變更的類型是 UpsertionChangeDeletionChange,並執行必要作業。
    • 如果是 UpsertionChange,請只取用非來自呼叫應用程式的變更,確保不會重新匯入資料。
  3. 指派下一個「變更」權杖做為新權杖。
  4. 重複執行步驟 1 到 3,直到沒有剩餘的「變更」為止。
  5. 儲存下一個權杖以供日後匯入時使用。
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
}

如要瞭解提取資料的具體注意事項,請參閱「同步處理資料」的最佳做法。

處理資料變更

您可以讓應用程式的資料儲存庫反映相關變更。如果是 UpsertionChange,請使用 id 和源自其 metadatalastModifiedTime 更新/插入記錄。如果是 DeletionChange,請使用提供的 id刪除記錄。 如要執行這項操作,您必須先儲存記錄 id,詳情請參閱「儲存健康資料同步 ID」。

刪除「健康資料同步」中的資料

當使用者從您的應用程式刪除自己的資料時,請確保這些資料也會從「健康資料同步」中移除。您可以使用 deleteRecords 執行此操作。這會取得記錄類型,以及 idclientRecordId 值的清單,方便您批次處理多筆要刪除的資料。此外,您也可以使用替代的 deleteRecords,其中會納入 timeRangeFilter

同步處理資料的最佳做法

以下因素會影響同步處理程序。

權杖到期

未使用的「變更」權杖會在 30 天內到期,因此請務必採用適當的同步策略,避免在這類情況下遺失資訊。策略可包含以下方法:

  • 搜尋應用程式資料儲存庫,找出最近取用且含有 Health Connect id 的記錄。
  • 要求 Health Connect 提供特定時間戳記之後的記錄,並在應用程式資料儲存庫中插入或更新該記錄。
  • 要求提供變更權杖,並保留至下次需要時使用。

建議的變更管理策略

如果應用程式收到無效或過期的「變更」權杖,建議您根據邏輯適用情形,採用下列管理策略:

  • 讀取及簡化所有資料。這是最理想的策略。
    • 儲存上次從「健康資料同步」讀取資料時的時間戳記。
    • 在權杖過期時,從最近的時間戳記或過去 30 天重新讀取所有資料。接著請根據先前讀取的資料,使用 ID 簡化這些資料。
    • 在理想情況下,請實作用戶端 ID,因為必須使用用戶端 ID 才能更新資料。
  • 僅讀取上次讀取時間戳記後的資料。這會導致變更權杖到期前後的資料出現落差,但時間範圍會較短,可能需要數小時至數天。
    • 儲存上次從「健康資料同步」讀取資料時的時間戳記。
    • 在權杖到期時,讀取這個時間戳記後的所有資料。
  • 刪除再讀取過去 30 天的資料。這更貼近第一項整合作業的情況。
    • 刪除應用程式在過去 30 天內從「健康資料同步」讀取的所有資料。
    • 刪除完成後,再次讀取所有資料。
  • 讀取過去 30 天的資料,且不刪除重複的資料。這是最不理想的策略,且會導致使用者看到重複的資料。
    • 刪除應用程式在過去 30 天內從「健康資料同步」讀取的所有資料。
    • 允許重複的項目。

資料類型變更權杖

如果應用程式可獨立取用多種資料類型,請針對每種資料類型使用單獨的變更權杖。請只在同時取用或完全不取用多種資料類型時,搭配使用資料類型清單與 Changes Sync API。

前景讀取

應用程式只有在前景運作時,才能從「健康資料同步」讀取資料。從「健康資料同步」同步處理資料時,存取作業隨時可能中斷。舉例來說,應用程式從「健康資料同步」讀取大量資料時,必須能處理同步作業中途發生的干擾,並在下次開啟應用程式時繼續這項作業。

背景讀取

您可以要求應用程式在背景執行,並從「健康資料同步」讀取資料。如果您要求 Background Read 權限,使用者可以授予應用程式在背景讀取資料的權限。

匯入時間

如果應用程式無法在資料新增時收到通知,則應在以下兩個時間點檢查新資料:

  • 每當應用程式開始在前景運作時。請在這種情況下使用生命週期事件。
  • 應用程式持續在前景運作的期間。請定期檢查新資料。每當有新資料時,請通知使用者更新畫面,反映變更情形。