Search code examples
androidhealthconnect

How to do an aggregate search in the Android Health Connect API


I’m trying to get a daily aggregate step count from Google's new 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)

But any aggregate queries that I execute result in this exception:

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]

Any ideas what’s causing this or how to work around it? I can get non-aggregated data without a problem using client.readRecords().


Solution

  • https://developer.android.com/guide/health-and-fitness/health-connect/common-workflows/aggregate-data#buckets

    The sample code used Instant, but you need to use LocalDateTime.

    val startTime = LocalDateTime.now().minusMonths(1)
    val endTime = LocalDateTime.now()
    
    val response =
      healthConnectClient.aggregateGroupByPeriod(
        AggregateGroupByPeriodRequest(
          metrics = setOf(StepsRecord.COUNT_TOTAL),
          timeRangeFilter = TimeRangeFilter.between(startTime, endTime),
          timeRangeSlicer = Period.ofDays(1)
        )
      )