使用bucketByTime按1天TimeUnit.DAYS分桶时步数同步错误问题咨询
问题1解答
Google Fit官方应用的步数统计逻辑和公开文档给出的基础聚合逻辑不完全一致。官方应用内部会自动拆分跨自然日的原始步数数据点,将步数按实际产生的时间段归属到对应日期,不会直接把跨天数据点的全量步数算到数据起始/结束时间所在的日期。2021年下半年Google Fit服务端同步逻辑做过未公开的算法调整,会生成少量跨天的长跨度com.google.step_count.delta数据点,这就是你之前没遇到过这类问题的原因。
问题2解答
不需要用按小时分桶的高成本方案,有两种更轻量的选择:
- 优先使用官方提供的每日步数专属读取接口
DailyTotalResult,这个接口内部已经做了跨天数据拆分,返回结果和Google Fit官方应用显示的数值完全一致,性能远高于分桶聚合的方案,不需要自行处理数据逻辑。 - 如果必须用自定义多指标聚合逻辑,可以在原有请求里新增跨桶拆分配置,不需要调整分桶粒度,就能自动拆分跨天数据点到对应日期的桶中。
优化代码示例
方案1:使用DailyTotalResult读取步数(和官方应用结果完全对齐)
private suspend fun getDailySteps(date: LocalDate): Long { val startTime = date.atStartOfDay(ZoneId.systemDefault()).toEpochSecond() val endTime = date.plusDays(1).atStartOfDay(ZoneId.systemDefault()).toEpochSecond() val request = DailyTotalRequest.Builder() .setDataType(DataType.AGGREGATE_STEP_COUNT_DELTA) .setTimeRange(startTime, endTime, TimeUnit.SECONDS) .build() return Fitness.getHistoryClient(context, GoogleSignIn.getLastSignedInAccount(context)!!) .readDailyTotal(request) .await() .total .getValue(Field.FIELD_STEPS) .asInt() .toLong() }
方案2:保留原有多指标聚合逻辑,仅新增拆分配置
val estimatedStepsDelta = DataSource.Builder() .setDataType(DataType.TYPE_STEP_COUNT_DELTA) .setType(DataSource.TYPE_DERIVED) .setStreamName("estimated_steps") .setAppPackageName("com.google.android.gms") .build() return DataReadRequest.Builder() .setTimeRange(startTimeEpochSeconds, endTimeEpochSeconds.coerceAtLeast(startTimeEpochSeconds + 1), TimeUnit.SECONDS) .aggregate(DataType.TYPE_DISTANCE_DELTA, DataType.AGGREGATE_DISTANCE_DELTA) .aggregate(estimatedStepsDelta, DataType.AGGREGATE_STEP_COUNT_DELTA) .aggregate(DataType.TYPE_MOVE_MINUTES, DataType.AGGREGATE_MOVE_MINUTES) .bucketByTime(1, TimeUnit.DAYS) // 新增该配置,自动拆分跨天数据点到对应日期桶 .setEnableCrossBucketSplitting(true) .enableServerQueries() .build()
内容的提问来源于stack exchange,提问作者xiankun zhu
相关产品推荐
相关产品推荐

