本指南与健康数据共享版本 1.1.0-alpha12 兼容。
大多数与 Health Connect 集成的应用都有自己的数据存储区,以用作可信来源。Health Connect 提供了多种方法来让您的应用保持同步。
根据应用的架构,同步过程可能涉及以下部分或全部操作:
- 将新数据或更新后数据从应用的数据存储区馈送至 Health Connect。
- 将数据更改从 Health Connect 拉取到应用的数据存储区中。
- 从应用的数据存储区中删除数据时,一并从“健康数据共享”中删除这些数据。
无论是哪种情况,都要确保同步过程能使 Health Connect 与应用的数据存储区保持一致。
将数据馈送到 Health Connect
同步过程的第一部分是将数据从应用的数据存储区馈送到 Health Connect 数据存储区。
准备数据
应用的数据存储区中的记录通常包含以下详细信息:
- 唯一键,例如
UUID
。 - 版本或时间戳。
将数据同步到健康数据共享时,请仅识别并馈送自上次同步以来插入、更新或删除的数据。
向 Health Connect 中写入数据
如需将数据馈送到 Health Connect,请按以下步骤操作:
- 从应用的数据存储区获取新条目、更新条目或已删除条目的列表。
- 对于每个条目,创建相应数据类型的
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
向 Health Connect 更新/插入数据。更新/插入数据是指,只要 Health Connect 数据存储区中存在clientRecordId
值且clientRecordVersion
高于现有值,那么 Health Connect 中的任何现有数据都会被覆盖。否则,更新/插入的数据会作为新数据写入。healthConnectClient.insertRecords(arrayListOf(record))
如需了解馈送数据的实际注意事项,请查看写入数据的最佳实践。
存储 Health Connect 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
}
从 Health Connect 中拉取数据
同步过程的第二部分是将 Health Connect 中的所有数据更改拉取到应用的数据存储区。数据更改可能包括更新和删除。
获取更改令牌
如需获取要从 Health Connect 拉取的更改列表,您的应用需要跟踪更改令牌。您可以在请求更改时使用这些令牌,从而返回数据更改列表,以及返回新的更改令牌供下次使用。
要获取更改令牌,请调用 getChangesToken
并提供所需的数据类型。
val changesToken = healthConnectClient.getChangesToken(
ChangesTokenRequest(recordTypes = setOf(WeightRecord::class))
)
检查数据更改
现在,您已经获得了更改令牌,可以用它来获取所有更改了。我们建议您创建一个循环来获取所有更改,从而检查是否有可用数据更改。具体步骤如下:
- 使用令牌调用
getChanges
以获取更改列表。 - 检查各项更改的类型是否为
UpsertionChange
或DeletionChange
,然后执行必要的操作。- 对于
UpsertionChange
,请仅进行并非来自调用应用的更改,从而确保不会重新导入数据。
- 对于
- 将下一个更改令牌分配为新令牌。
- 重复步骤 1-3,直到没有剩余的更改为止。
- 存储下一个令牌,并将其预留以供日后导入。
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
,请使用 metadata
中的 id
和 lastModifiedTime
以更新/插入记录。对于 DeletionChange
,请使用提供的 id
删除该记录。这要求您已存储记录 id
,如存储健康数据共享 ID 中所述。
从 Health Connect 中删除数据
当用户从您的应用中删除自己的数据时,请确保这些数据也会从 Health Connect 中移除。请使用 deleteRecords
执行此操作。这需要使用记录类型以及 id
和 clientRecordId
值的列表,方便批量处理多种待删除的数据。此外,我们还提供了一种接受 timeRangeFilter
的替代 deleteRecords
。
同步数据的最佳实践
以下因素会影响同步过程。
令牌过期
由于闲置的更改令牌会在 30 天内过期,因此您必须遵守同步策略,以避免在此类情况下丢失信息。您的策略可以采用以下方法:
- 在应用的数据存储区中搜索最近用过的记录,记录中还应具有来自 Health Connect 的
id
。 - 向 Health Connect 请求以特定时间戳开头的记录,然后在应用的数据存储区中插入或更新这些记录。
- 请求一个更改令牌以备下次需要时使用。
建议的更改管理策略
如果应用获取的更改令牌无效或已过期,我们建议您根据该令牌在应用逻辑中的使用方式,采取以下管理策略:
- 读取所有数据并对其进行去重处理。这是最理想的策略。
- 存储上次从 Health Connect 读取数据的时间戳。
- 在令牌过期后,重新读取自最近时间戳以来或过去 30 天内的所有数据。然后,使用标识符对照之前读取的数据对其进行去重处理。
- 最好实现客户端 ID,因为在更新数据时需要用到该 ID。
- 只读取自上次读取时间戳以来的数据。这会导致在更改令牌过期前后出现一些数据差异,不过这段时间较短,可能是几个小时到几天。
- 存储上次从 Health Connect 读取数据的时间戳。
- 在令牌过期后,读取从这个时间戳开始的所有数据。
- 删除过去 30 天内的数据,然后再读取该数据。此操作更适合在首次集成时执行。
- 删除该应用在过去 30 天内从 Health Connect 读取的所有数据。
- 删除后,重新读取所有这些数据。
- 读取过去 30 天内的数据,但不进行去重处理。这是下下之策,会导致向用户显示重复数据。
- 删除该应用在过去 30 天内从 Health Connect 读取的所有数据。
- 允许条目重复。
数据类型更改令牌
如果您的应用可以独立使用多种类型的数据,则针对每种数据类型使用单独的更改令牌。仅当这些类型的数据被一起使用或不被使用时,才借助 Changes Sync API 来利用多种数据类型。
前台读取
应用只有在前台运行时才能读取来自 Health Connect 的数据。同步 Health Connect 中的数据时,对 Health Connect 的访问可能会随时中断。例如,从 Health Connect 读取大量数据时,您的应用必须在同步过程中处理中断,并在下次打开应用时继续。
后台读取
您可以请求让应用在后台运行并从“健康数据共享”读取数据。如果您请求 Background Read
权限,用户可以向您的应用授予在后台读取数据的权限。
数据导入时间
由于应用无法在有新数据时收到通知,因此需在以下两个时间点检查是否有新数据:
- 每当应用在前台进入活动状态时。在这种情况下,请使用生命周期事件。
- 应用持续在前台运行时。在这种情况下,应定期检查。在有新数据可用时通知用户,让对方更新界面以反映更改。