自 Google Fit App 更新以来,Google Fit 数据模式发生了变化,实施显然已中断

Cpt*_*ric 5 java android kotlin google-fit-sdk google-fit

我们已经在我们的用户群中发现,自上次 google fit 应用程序更新以来,数据急剧下降,自开始以来,我们一直试图找出代码中的问题。给出时间,我们认为我们使用的版本(当时是 18.0)是问题所在。升级到 SDK 20.0 并没有改善结果,但阻止了数据停滞。目前我们可以假设 50-60% 通过 SDK 连接到 google fit 的用户不再根据(以前工作的)实现正确检索数据。它们并没有丢失,它们仍然在这里和那里发送一些比特,但它不再是以前的样子。

这张图表展示了事件的时间线,这些事件让我们得出结论,一方一定做错了什么。

谷歌拟合数据丢失图

为了便于阅读,下面的代码示例已经去除了大多数数据处理代码,但它仍然存在。

我们的 Fitness 客户端请求FitnessOptions.ACCESS_READ下面提到的所有类型,以及取决于应用程序的其他类型,每次初始化时,无论是在前台还是后台,确保我们只请求用户接受的那些。

我们可以确认下一个数据类型在请求每日总计或本地设备每日总计时不再返回任何值,但在非聚合读取中请求时确实返回同一时期的数据块:

DataType.TYPE_STEP_COUNT_DELTA
DataType.TYPE_CALORIES_EXPENDED
DataType.TYPE_HEART_RATE_BPM
Run Code Online (Sandbox Code Playgroud)

我们还尝试将那些可能的更改为它们的聚合对应项,但无济于事:

DataType.AGGREGATE_CALORIES_EXPENDED
DataType.AGGREGATE_STEP_COUNT_DELTA
Run Code Online (Sandbox Code Playgroud)

这是我们当前的 getDailyTotal 实现,在更新之前工作,并且直接写成开发人员站点上的示例显示:

DataType.TYPE_STEP_COUNT_DELTA
DataType.TYPE_CALORIES_EXPENDED
DataType.TYPE_HEART_RATE_BPM
Run Code Online (Sandbox Code Playgroud)

无论一天中的哪个时间被询问,这当前都返回 0。

然后我们有我们的补充代码,它模拟 getDailyTotal 在内部所做的事情,也根据开发人员站点示例:从:天开始于 00 : 00 : 00,UTC+1到:天结束于 23:59 : 59,UTC+ 1 类型:任何数据类型。

DataType.AGGREGATE_CALORIES_EXPENDED
DataType.AGGREGATE_STEP_COUNT_DELTA
Run Code Online (Sandbox Code Playgroud)

这里的常见结果是 1) 一个 null 或空结果,2) 实际得到结果(在DataType.TYPE_STEP_COUNT_DELTA 有时发生的情况下)或 3) APIExceptioncode 5012, this datatype can't be aggregated.

我们正在使用单聚合,因为双聚合(type, type.aggregate)已经被弃用,因为一些版本已经被弃用了,尽管一些开发者站点的例子仍然使用它。

的使用(或不使用).enableServerQueries()不会修改最终结果。

最后,我们假设最坏的情况,无论如何我们都会要求当天的任何内容,然后我们手动聚合。这通常会报告结果,而其他人则没有。遗憾的是,这些结果从来都不足以让人感到舒服。

    Fitness.getHistoryClient(context, account)
                .readDailyTotal(type)
                .addOnSuccessListener {
                    Logger.i("${type.name}::DailyTotal::Success")
                    onResponse(it)
                }
Run Code Online (Sandbox Code Playgroud)

这往往可行,但鉴于数据集、存储桶和整个数据集结构的复杂嵌套性质,数据的手动处理很复杂。

我们也注意到了在获取fit app上清晰可见但SDK没有出现的数据时出现的问题,例如华为健康活动出现在app上,而SDK只返回其中的一个子集,反之亦然周围,​​SDK 向我们返回数据(例如,一整晚的睡眠会话(轻度、快速、深度...),而 fit 应用程序显示与没有任何会话的单个 Sleep 块相同的睡眠。

第三方应用程序中显示的睡眠会话,使用 SDK 返回给我们的相同数据: 第三方睡眠会话

Google 健身应用中显示的相同睡眠会话: 谷歌适合睡眠会议

至于文档说:

对于Android API,按数据类型读取,Fit平台默认返回合并流。这会自动包括您的应用程序可用的所有数据,包括其他应用程序写入的数据。您将无法通过 Android API 查看数据来自哪些应用或设备的列表。

我们认为合并的流行为不正常,不是实时的(这可以通过应用程序直接从后端显示数据和 SDK 尚未写入数据之间的延迟来解释),但也不是问题数分钟或数小时的差异,有时从未出现。

为了理解我们如何检索这些数据,我们有一个背景WorkerManager CouroutineJob,每隔一段时间(当系统允许时,给予打盹模式权限,但我们更喜欢(并通过 WorkerManager 配置询问)是每小时一次或几次小时,为了使数据与健身应用程序中显示的数据保持同步),我们请求从上次更新到最后一天结束的数据或/和我们请求今天的每日总数(或截至当前时间,取决于多远我们去的“不起作用”漏斗,以及上次更新的日期)。

  • 我们的实现有什么问题吗?
  • google fit 是否改变了向连接的应用程序报告数据的方式?
  • 我们能以某种方式获得更真实的数据吗?
  • 有什么方法可以更有效地以不同方式请求相同的数据?我们最感兴趣的是获取每日摘要、总数和平均值,而不是时间段/会话。我们请求两者,但它们会进入涵盖不同用例的不同数据渠道。

Cpt*_*ric 1

目前还没有答案。

我们的解决方案最终对数据进行了一系列的粗暴检查,每次失败时我们都会尝试不同的方法。