Google Health API 中的数据管理

在 Google Health API 中处理数据,其核心是在云端的 Google Health API 数据存储区与您自己的应用或后端数据存储区之间同步数据。不过,此周期可能会因各种因素而采取不同的形式:

  • 您是否正在向 Google Health API 写入数据?只是阅读?还是两者兼顾?
  • 您的数据存储区是位于应用或设备本地吗?还是在您自己的云端?
  • 您是否需要在用户的应用和穿戴式设备之间同步 Google Health API 数据?您多久同步一次设备?
  • 您要处理的是什么类型的数据?基本计数?度量单位? 采样率不同的序列?
  • 您是否打算在应用处于后台时读取数据?
  • 您是否打算使用在应用获得用户权限之前记录的历史数据?

如需了解这些组件如何协同工作,请查看 Google Health API 同步生命周期。此生命周期有两个版本:标准(读写)和只读。

标准同步生命周期

Google Health API 中的标准同步生命周期
图 1:Google Health API 中的标准同步生命周期

与 Google Health API 集成意味着将数据复制到应用或后端数据存储区。为便于在本文档中使用,我们将此数据存储区称为开发者数据存储区。

此处的“复制”可以代替任何离散活动,例如从 Google Health API 读取数据(复制到开发者数据存储区)或写入 Google Health API(复制到 Google Health API)。按特定顺序重复执行这些操作即为同步生命周期。

图 1 说明了涉及读取和写入操作的标准同步生命周期,不考虑前面提到的任何因素。

写入

  1. 准备要写入的新数据 - 从外部设备或应用传输数据,并将数据点格式化为与 Google Health API 数据类型兼容的 JSON 表示法。请注意,Health API 目前不支持为写入操作分配自定义客户端 ID。此类 ID 可以在 POST 中提供,但会被忽略。
  2. Upsert 记录 - 使用 REST 端点向 Google Health API 提交数据点。使用 POST 创建记录,使用 PATCH 插入和更新现有记录。PATCH 操作所需的 ID 将来自之前的 POST 操作(上一个周期中的下一步)。
  3. 处理返回的资源 ID - 使用服务器生成的 ID 时,请在开发者数据存储区中提取并持久保存服务器返回的资源 name 或 ID,以便将来进行更新 (PATCH) 或删除 (DELETE)。如需详细了解这两种类型,请参阅标识策略。

读取

  1. 读取记录 - 使用 REST 端点(GET,带有 filter 查询参数和 pageToken 分页,或聚合端点,例如 rollUp 和 dailyRollUp)从 Google Health API 中提取新数据和对现有数据的更改,或使用 Webhook 订阅 (projects.subscribers) 接收通知。通知仅表示有新数据可用,而不表示实际数据是什么。
  2. 协调开发者数据存储区 - 将新增和更新的数据协调到开发者数据存储区。已连接的设备在同步期间可能会产生重叠的时间间隔。如需了解 Google Health API 如何解决这些问题,请参阅时间间隔时间戳和已连接的设备同步。

然后,根据外部设备或应用的具体需求,以适当的时间间隔重复此周期。通常,我们建议您按照此顺序在自己的数据存储区和 Google Health API 之间同步数据。

识别策略

如果您打算将数据写入 Google Health API,则在构建与 Google Health API 的集成之前,您必须在创建数据点(数据的基本单位)时选择资源标识策略。

Health API 目前不支持客户端分配的写入 ID。 此类 ID 可以在 POST 中提供,但会被忽略。此处提供了有关此选项的详细信息,仅供参考。

  1. 服务器生成的 ID(默认选项):客户端提交不带 ID 的数据,Google Health API 后端会生成并返回一个唯一的系统标识符。
  2. 客户端分配的自定义 ID(根据 AIP-133,尚不支持):客户端应用生成唯一标识符(例如 UUID 或本地数据库主键),并在创建时在资源路径中提供该标识符。

下表比较了这两种标识策略,可帮助您选择适合集成的策略:

功能 服务器生成的 ID 客户端分配的自定义 ID
ID 生成 服务器在执行 POST 期间生成随机系统 ID。 客户端在写入之前在本地生成稳定 ID(UUID v4/内部 PK)。
资源路径 .../dataPoints/{server_id}(在响应中返回) .../dataPoints/{custom_id}
写入后本地步骤 必需。必须将返回的 server_id 存储在本地数据库中,以便将来进行更新/删除。 否。应用已拥有该 ID。
ID 映射表 必需。客户端必须维护双向映射 (local_id ↔ server_id)。 不需要。客户端直接使用自己的主键。
重试行为(网络信号弱) 重复风险。重试超时的 POST 会创建一个具有新服务器 ID 的重复记录。 安全且幂等。使用相同的 custom_id 重试 POST 可防止重复创建(返回 409 ALREADY_EXISTS)。
离线同步支持 受限。必须等待服务器响应以获取官方资源 ID,然后才能引用它们。 完整。您可以在离线状态下使用稳定 ID 创建和更改实体,然后在重新连接后无缝同步。
有广告格式限制 完全由服务器处理。 必须遵循 ^[a-z0-9-]{4,63}$(4-63 个小写字母数字和连字符)。
适用场景

在以下情况下,请选择服务器生成的 ID:

  • 您的应用是只写/仅附加应用(例如,发送遥测数据或步数,这些数据之后绝不会更新或删除)。
  • 您的应用不会维护各个数据点的本地永久性数据库。
  • 您更喜欢简单性,而无需管理字符串验证限制条件(例如 4-63 个字符)。

在以下情况下,请选择自定义 ID:

  • 您运营着一款双向同步应用,该应用可在设备之间读取、写入和更新健康记录。
  • 您的应用有一个本地数据库(例如 Room 或 SQLite),用于存储具有本地主键的记录。
  • 您的用户在离线或间歇性移动连接(需要安全重试)的情况下记录数据。
  • 您希望消除后端数据库和 API 之间的 ID 映射表。

只读同步生命周期

Google Health API 中的只读同步生命周期
图 2:Google Health API 中的只读同步生命周期

如果应用仅打算从 Google Health API 读取数据,则必须将数据复制到其开发者数据存储区,并处理生命周期的协调部分。

读取部分中介绍的任务同样适用于此处。

图 2 说明了只读生命周期。

间隔时间戳和已连接的设备同步

间隔数据表示在一段时间内收集的测量值,例如步数、心率或锻炼时段。相比之下,时间点测量包括手动条目,例如食物日志或体重秤读数。间隔数据通常来自同步的已连接设备,例如智能手表和运动手环。

在处理时间间隔数据时,时间间隔时间戳(REST JSON 载荷中的 startTime 和 endTime,或过滤表达式和 gRPC 中的 start_time 和 end_time)会引入独特的行为。本部分将说明重叠间隔发生的原因,并比较 list 和 reconcile 端点。

已连接的设备中的重叠时间间隔

Fitbit 智能手环和 Google Pixel Watch 等已连接的设备会在佩戴期间持续收集高频生物识别读数。设备将数据点同步到 Google Health 后,不会追溯性地更改这些现有记录。 其存储的时间间隔时间戳保持不变。

不过,在后续同步周期之前,设备端算法通常会重新解读原始传感器遥测数据。设备会重新对过去几个小时内收集的读数进行分桶。当设备再次同步时,它会上传新的数据点。其开始和结束边界可以与之前存储的时间间隔重叠。

例如,假设用户佩戴智能手表,其活动数据分两个连续批次同步:

  1. 在首次同步期间,设备会上传涵盖 10:00:00Z 到 10:14:59Z 的数据点。
  2. 在设备端重新计算后,第二次同步会上传另一个涵盖 10:14:00Z 到 10:28:59Z 的数据点。

这两条记录会分别存储在 Google Health 后端。因此,这两个数据点都涵盖从 10:14:00Z 到 10:14:59Z 的时间间隔。这会在查询原始记录时产生 59 秒的重叠。

比较列表和对账端点

您可以使用 list 或 reconcile 端点处理这些重叠的时间间隔。选择符合您应用要求的端点:

功能 list 个端点 reconcile 个端点
HTTP 方法 GET https://health.googleapis.com/v4/users/me/dataTypes/dataType/dataPoints GET https://health.googleapis.com/v4/users/me/dataTypes/dataType/dataPoints:reconcile
重叠行为 返回所有已存储的记录(按上传时的状态),不进行去重。如果时间间隔重叠,则系统会返回两条记录。 解决冲突,并对跨设备和同步会话的重叠记录进行去重,将其整合到单个连续的数据流中。
优点 提供每个设备和同步批次上传的每条记录的完整、未经修改的审核跟踪记录。 通过自动处理重叠的时间间隔和多设备冲突,简化时间轴渲染和时长计算。
缺点 您的应用负责检测和解决重叠的时间间隔、多设备冲突和未佩戴时段。 响应中会省略从属重叠记录,因此无法单独审核各个设备同步批次。

reconcile 端点旨在绘制界面、呈现活动时间轴以及计算不重叠的总时长。它会解决重新分桶的同步会话中的冲突间隔。它还会协调在多部设备(例如手表和手机)上同时记录的活动。

协调功能通过选择权威记录来解决冲突的会话,而不是合成人工时间并集。例如,它不会将 11:00:00Z 到 11:30:00Z 以及 11:20:00Z 到 11:50:00Z 合并为 11:00:00Z 到 11:50:00Z。协调后的响应会返回胜出的数据点及其原始记录间隔。这样可以保留该会话测量的遥测和指标的完整性。

图 3 说明了 reconcile 端点如何处理重叠会话。 它会选择权威记录,而不是创建人工时间并集。

解决重叠间隔:协调端点去重与人工时间并集
图 3:冲突会话协调与人工时间联合合并

Endpoints 指南提供了完整的请求和响应示例。如需将原始 list 记录与 reconcile 输出进行比较,请参阅获取间隔数据的对账视图。

list 端点专为设备诊断和数据审核而设计。如果您的工作流需要检查每个设备上传的未修改记录,请使用此模式。使用 list 进行查询时,您的客户端逻辑必须处理原始数据中的任何时间间隔重叠。

时间戳可变性和所有者更新

在正常同步周期内,已连接的设备不会追溯性地修改存储的时间戳。不过,间隔时间戳(REST JSON 载荷中的 startTime 和 endTime,或过滤表达式和 gRPC 中的 start_time 和 end_time)在所有数据源中并非普遍不可变。只有记录的原始创建者或所有者才能修改其字段。其他应用无法修改并非由其创建的数据点。

所有者应用可以使用 patch 端点更新其现有记录。这包括修改开始或结束时间戳,这会同时更新服务器上的世界协调时间(startTime 和 endTime)和民用时间(civilStartTime 和 civilEndTime)字段。如需查看使用 PATCH 更新时间戳的示例,请参阅 Endpoints 指南中的更新现有数据的时间间隔时间戳。

同样,从外部平台(例如健康数据共享或合作伙伴应用)同步的数据点会继承原始来源的更新。如果健康数据共享随后收到来自原始第三方应用的已同步记录的更新,这些更改会传播并覆盖现有记录。