ヘルスコネクトの集計データには、基本的な集計とバケットへのデータの集計があります。以下のワークフローでは、この 2 つの集計を行う方法について説明します。
基本的な集計
データに対して基本的な集計を行うには、HealthConnectClient オブジェクトで aggregate 関数を使用します。これは、パラメータとして指標タイプと時間範囲を取る AggregateRequest オブジェクトを受け入れます。基本的な集計がどのように呼び出されるかは、使用する指標タイプによって異なります。
累積集計
累積集計は、合計値を計算します。
次の例は、特定のデータ型のデータを集計する方法を示しています。
suspend fun readDistanceAggregate(startTime: Instant, endTime: Instant): Number { val response = healthConnectClient.aggregate( AggregateRequest( metrics = setOf(DistanceRecord.DISTANCE_TOTAL), timeRangeFilter = TimeRangeFilter.between(startTime, endTime) ) ) return response[DistanceRecord.DISTANCE_TOTAL]?.inMeters ?: 0L }
データの出所によるフィルタ
集計データをその配信元でフィルタすることもできます。たとえば、特定のアプリによって書き込まれたデータのみを含めることができます。
次の例は、dataOriginFilter と AggregateRequest を使用して特定のアプリの歩数を集計する方法を示しています。
suspend fun aggregateStepsFromSpecificApp( healthConnectClient: HealthConnectClient, startTime: Instant, endTime: Instant, appPackageName: String ) { try { val response = healthConnectClient.aggregate( AggregateRequest( metrics = setOf(StepsRecord.COUNT_TOTAL), timeRangeFilter = TimeRangeFilter.between(startTime, endTime), dataOriginFilter = setOf(DataOrigin(appPackageName)) ) ) // The result may be null if no data is available in the time range val totalSteps = response[StepsRecord.COUNT_TOTAL] ?: 0L } catch (e: Exception) { // Run error handling here } }
統計集計
統計集計では、サンプルを含むレコードの最小値、最大値、平均値を計算します。
次の例は、統計集計を使用する方法を示しています。
suspend fun readHeartRateAggregate(startTime: Instant, endTime: Instant): Pair<Long, Long> { val response = healthConnectClient.aggregate( AggregateRequest( metrics = setOf(HeartRateRecord.BPM_MAX, HeartRateRecord.BPM_MIN), timeRangeFilter = TimeRangeFilter.between(startTime, endTime) ) ) val minimumHeartRate = response[HeartRateRecord.BPM_MIN] ?: 0L val maximumHeartRate = response[HeartRateRecord.BPM_MAX] ?: 0L return maximumHeartRate to minimumHeartRate }
バケット
ヘルスコネクトでは、データをバケットに集計することもできます。使用できるバケットには、duration と period の 2 種類があります。
呼び出されると、バケットのリストが返されます。リストがスパースになる可能性があるため、バケットにデータが含まれていない場合、バケットはリストに含まれません。
Duration
この場合、集計されたデータは一定の時間内(1 分、1 時間など)でバケットに分割されます。データをバケットに集約するには、aggregateGroupByDuration を使用します。これは、指標タイプ、時間範囲、Duration をパラメータとして取る AggregateGroupByDurationRequest オブジェクトを受け入れます。TimeRangeFilter の startTime と endTime には、Instant オブジェクトまたは LocalDateTime オブジェクトのペアを使用できます。
ステップを分ごとのバケットで集計する例を以下に示します。
suspend fun aggregateStepsIntoMinutes( healthConnectClient: HealthConnectClient, startTime: LocalDateTime, endTime: LocalDateTime ) { try { val response = healthConnectClient.aggregateGroupByDuration( AggregateGroupByDurationRequest( metrics = setOf(StepsRecord.COUNT_TOTAL), timeRangeFilter = TimeRangeFilter.between(startTime, endTime), timeRangeSlicer = Duration.ofMinutes(1L) ) ) for (durationResult in response) { // The result may be null if no data is available in the time range val totalSteps = durationResult.result[StepsRecord.COUNT_TOTAL] ?: 0L } } catch (e: Exception) { // Run error handling here } }
Period
この場合、集計されたデータは日付ベースの期間内(1 週間、1 か月など)でバケットに分割されます。データをバケットに集約するには、aggregateGroupByPeriod を使用します。これは、指標タイプ、時間範囲、Period をパラメータとして取る AggregateGroupByPeriodRequest オブジェクトを受け入れます。
ステップを月ごとのバケットで集計する例を以下に示します。
suspend fun aggregateStepsIntoMonths( healthConnectClient: HealthConnectClient, startTime: LocalDateTime, endTime: LocalDateTime ) { try { val response = healthConnectClient.aggregateGroupByPeriod( AggregateGroupByPeriodRequest( metrics = setOf(StepsRecord.COUNT_TOTAL), timeRangeFilter = TimeRangeFilter.between(startTime, endTime), timeRangeSlicer = Period.ofMonths(1) ) ) for (monthlyResult in response) { // The result may be null if no data is available in the time range val totalSteps = monthlyResult.result[StepsRecord.COUNT_TOTAL] ?: 0L } } catch (e: Exception) { // Run error handling here } }
読み取りの制限
デフォルトでは、すべてのアプリは、最初に権限が付与された日の 30 日前までのデータをヘルスコネクトから読み取ることができます。
デフォルトの制限を超えて読み取り権限を拡張する必要がある場合は、PERMISSION_READ_HEALTH_DATA_HISTORY をリクエストします。この権限がない場合、30 日より古いレコードを読み取ろうとするとエラーが発生します。
削除されたアプリの権限の履歴
ユーザーがアプリを削除すると、履歴権限を含むすべての権限が取り消されます。ユーザーがアプリを再インストールして権限を再度付与すると、同じデフォルトの制限が適用され、アプリは新しい日付から最大 30 日間遡ってヘルスコネクトからデータを読み取ることができます。
たとえば、ユーザーが 2023 年 5 月 10 日にアプリを削除し、2023 年 5 月 15 日にアプリを再インストールして読み取り権限を付与したとします。この場合、アプリはデフォルトで 2023 年 4 月 15 日以降のデータを読み取れます。
ユーザーが選択したアプリの優先度によって影響を受けるデータを集計する
エンドユーザーは、ヘルスコネクトと統合した睡眠アプリとアクティビティ アプリの優先度を設定できます。これらの優先度リストを変更できるのはエンドユーザーのみです。集計読み取りを行うと、Aggregate API は重複するデータを考慮し、優先度が最も高いアプリのデータのみを保持します。ユーザーが同じ種類のデータ(歩数や移動距離など)を同時に書き込む複数のアプリを使用している場合、重複したデータが存在する可能性があります。
エンドユーザーがアプリの優先順位を設定する方法については、ヘルスコネクトのデータを管理するをご覧ください。
ユーザーはアプリを追加または削除したり、優先度を変更したりできます。ユーザーは、重複したデータを書き込むアプリを削除して、ヘルスコネクトの画面に表示されるデータの合計が、優先順位を最も高く設定したアプリのデータと一致するようにしたい場合があります。データの合計はリアルタイムで更新されます。
Aggregate API は、ユーザーが優先度を設定した方法に従ってデータを重複除去することで、アクティビティ アプリと睡眠アプリのデータを計算しますが、データを書き込むアプリごとにデータを個別に計算する独自のロジックを構築することもできます。
ヘルスコネクトで重複除去されるのは、アクティビティと睡眠のデータ型のみです。表示されるデータ合計は、Aggregate API で重複除去が実行された後の値です。これらの合計は、歩数と距離のデータが存在する直近の 1 日の合計を示しています。他の種類のデータの場合、集計結果には、データを書き込んだすべてのアプリのヘルスコネクトにあるその種類のすべてのデータがまとめられます。
バックグラウンドでの読み取り
アプリがバックグラウンドで実行され、ヘルスコネクトからデータを読み取るようにリクエストできます。バックグラウンドでの読み取り権限をリクエストすると、ユーザーはアプリにバックグラウンドでのデータ読み取りアクセス権を付与できます。
レコード別にサポートされている集計データ型
この表は、ヘルスコネクトのレコードでサポートされているすべての集計データ型を示しています。