Android Health Connect API聚合查询报错:Duration需用物理时间设置
Health Connect API聚合查询异常:Duration must be set with physical times 解决方法
我尝试通过Google的Health Connect API获取每日步数聚合统计,代码如下:
val request = AggregateGroupByPeriodRequest( setOf(StepsRecord.COUNT_TOTAL), TimeRangeFilter.between(Instant.now().minus(10, ChronoUnit.DAYS), Instant.now()), Period.ofDays(1), setOf<DataOrigin>()) val response = client.aggregateGroupByPeriod(request)
执行任何聚合查询都会抛出如下异常:
java.lang.IllegalStateException: Duration must be set with physical times at android.os.Parcel.createExceptionOrNull(Parcel.java:3019) at android.os.Parcel.createException(Parcel.java:2995) at android.os.Parcel.readException(Parcel.java:2978) at android.os.Parcel.readException(Parcel.java:2920) at androidx.health.platform.client.service.IHealthDataService$Stub$Proxy.aggregate(IHealthDataService.java:490) at androidx.health.platform.client.impl.ServiceBackedHealthDataClient.aggregate$lambda$9(ServiceBackedHealthDataClient.kt:162) at androidx.health.platform.client.impl.ServiceBackedHealthDataClient.$r8$lambda$sD3sEial4TRJZ0x1SNHmgqr5dxw(Unknown Source:0) at androidx.health.platform.client.impl.ServiceBackedHealthDataClient$$ExternalSyntheticLambda10.execute(Unknown Source:6) at androidx.health.platform.client.impl.ipc.Client$3.execute(Client.java:297) at androidx.health.platform.client.impl.ipc.internal.ServiceConnection.execute(ServiceConnection.java:286) at androidx.health.platform.client.impl.ipc.internal.ServiceConnection.enqueue(ServiceConnection.java:243) at androidx.health.platform.client.impl.ipc.internal.ConnectionManager.handleMessage(ConnectionManager.java:148) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loopOnce(Looper.java:201) at android.os.Looper.loop(Looper.java:288) at android.os.HandlerThread.run(HandlerThread.java:67) Suppressed: kotlinx.coroutines.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@850d063, Dispatchers.Main]
我使用client.readRecords()可以正常获取非聚合数据,以下是异常原因及解决方法:
异常原因
- 聚合查询要求时间范围必须基于物理时间(带时区的时间),因为按自然日(
Period.ofDays(1))分组需要对齐时区边界,而Instant是无时区的时间戳,无法满足该要求。 readRecords()无需按周期分组,仅依赖时间戳定位数据,因此无时区要求可以正常执行。
解决方法
将时间范围的Instant替换为带时区的ZonedDateTime,确保时间绑定到具体时区(比如系统默认时区),修改后的代码如下:
val zoneId = ZoneId.systemDefault() val endTime = ZonedDateTime.now(zoneId).toInstant() val startTime = ZonedDateTime.now(zoneId).minusDays(10).toInstant() val request = AggregateGroupByPeriodRequest( setOf(StepsRecord.COUNT_TOTAL), TimeRangeFilter.between(startTime, endTime), Period.ofDays(1), setOf<DataOrigin>()) val response = client.aggregateGroupByPeriod(request)
关键修改说明
- 使用
ZonedDateTime获取带时区的时间,确保按自然日分组时对齐当地的0点边界。 - 时间范围的起始和结束都基于同一时区转换,保证聚合的周期是符合物理时间的自然日。
内容的提问来源于stack exchange,提问作者leremjs
相关产品推荐
相关产品推荐

