初めてのヘルスコネクト統合アプリ

1. はじめに

e4a4985ad1cdae8b.png

ヘルスコネクトとは

ヘルスコネクトは、Android アプリ デベロッパー向けの健康データ プラットフォームです。ユーザーの健康とフィットネスのデータにアクセスできる一元化されたインターフェースと、デバイスに依存しない一貫した機能動作を実現できます。ヘルスコネクトでは、健康とフィットネスに関するデータがデバイスに安全に保存されるほか、アクセスを詳細に制御して透明性を確保できます。

ヘルスコネクトの仕組み

ヘルスコネクトは、アクティビティ、睡眠、栄養、身体測定、心拍数や血圧などの指標を含む、50 を超える一般的な健康とフィットネスに関するデータ型とカテゴリをサポートしています。

ヘルスコネクトの仕組み

デベロッパーはユーザー権限で、標準化されたスキーマと API の動作を使用して、ヘルスコネクトに対する読み取りや書き込みを安全に行えます。ユーザーは、プライバシー設定を詳細に制御し、どのアプリがデータへのアクセスをリクエストしているかをいつでも細かく管理できます。ヘルスコネクトのデータはデバイス上に保存され、暗号化されます。ユーザーは、アクセスを遮断したり、デバイス上で不要なデータを削除したりできるほか、複数のアプリを使用する場合に、複数のデータソースで優先順位を付けることもできます。

ヘルスコネクトのアーキテクチャ

アーキテクチャ

ヘルスコネクトの主な要素とアーキテクチャのコンポーネントは次のとおりです。

  • クライアント アプリ: ヘルスコネクトと統合するために、クライアント アプリが SDK を健康&フィットネス アプリにリンクします。これにより、ヘルスコネクト API とやり取りするための API サーフェスが提供されます。
  • ソフトウェア開発キット: この SDK で、クライアント アプリがヘルスコネクト APK と通信できるようになります。
  • ヘルスコネクト APK: ヘルスコネクトを実装する APK です。権限管理コンポーネントとデータ管理コンポーネントの両方が含まれています。ヘルスコネクト APK はユーザーのデバイスで直接利用できるようになるため、ヘルスコネクトはアカウント中心ではなくデバイス中心になります。
  • 権限の管理: ヘルスコネクトには、アプリがデータを表示する権限をユーザーにリクエストするためのユーザー インターフェースがあります。既存のユーザー権限のリストも表示されます。これにより、ユーザーはさまざまなアプリに対して付与または拒否したアクセス権を、簡単に管理できます。
  • データの管理: ヘルスコネクトは、ユーザーの歩数、サイクリング速度、心拍数など、サポートされているデータの種類について、記録されたデータの概要をユーザー インターフェースに表示します。

作成するアプリの概要

この Codelab では、ヘルスコネクトと統合されたシンプルな健康&フィットネス アプリを作成します。このアプリでは次の処理を行います。

  • データアクセスに関するユーザー権限の取得と確認。
  • ヘルスコネクトへのデータの書き込み。
  • ヘルスコネクトからの集計データの読み取り。

学習内容

  • ヘルスコネクトの統合開発をサポートする環境を設定する方法。
  • 権限を取得して権限チェックを実行する方法。
  • ヘルスコネクト プラットフォームに健康やフィットネスに関するデータを提供する方法。
  • デバイス上のデータ ストレージを活用する方法。
  • Google が提供するデベロッパー ツールを使用してアプリを検証する方法。

必要なもの

  • Android Studio の最新の安定版。
  • Android SDK バージョン 28(Pie)以降を搭載した Android モバイル デバイス。

2. セットアップする

ヘルスコネクト アプリを準備する

ヘルスコネクト アプリは、アプリがヘルスコネクト SDK を介して送信するすべてのリクエストを処理します。リクエストには、データの保存や読み取り / 書き込みアクセス権の管理などがあります。

ヘルスコネクトへのアクセスは、スマートフォンにインストールされている Android のバージョンによって異なります。以下のセクションでは、Android の最近のバージョンを処理する方法の概要を示します。

Android 14

Android 14(API レベル 34)以降、ヘルスコネクトは Android フレームワークの一部になっています。このバージョンのヘルスコネクトはフレームワーク モジュールであるため、セットアップは不要です。

Android 13 以前

Android 13(API レベル 33)以前のバージョンでは、ヘルスコネクトは Android フレームワークの一部ではありません。そのため、Google Play ストアからヘルスコネクト アプリをインストールする必要があります。QR コードをスキャンして、ヘルスコネクトをインストールします。

633ed0490a74595d.png

サンプルコードを取得する

まず、GitHub からソースコードのクローンを作成します。

git clone https://github.com/android/android-health-connect-codelab.git

サンプル ディレクトリには、この Codelab の start コードと finished コードが含まれています。Android Studio の [Project] ビューに、次の 2 つのモジュールが表示されます。

  • start: このプロジェクトのスターター コード。これを変更して Codelab を完成します。
  • finished: この Codelab の完成したコード。作業のチェックに使用します。

「start」コードを確認する

Codelab サンプルアプリには Jetpack Compose によって構築された基本的な UI があり、次の画面が用意されています。

  • WelcomeScreen: アプリのランディング ページです。このページに、ヘルスコネクトの状態(インストール済み、未インストール、サポート対象外)に応じたメッセージが表示されます。
  • PrivacyPolicyScreen: アプリでの権限の使用方法を説明します。ユーザーがヘルスコネクトの権限ダイアログでプライバシー ポリシーのリンクをクリックすると表示されます。
  • InputReadingsScreen: シンプルな体重のレコードの読み取りと書き込みを行います。
  • ExerciseSessionScreen: ここにユーザーがエクササイズ セッションを挿入して一覧表示します。レコードをクリックすると、ExerciseSessionDetailScreen が表示され、そのセッションに関連するデータが表示されます。
  • DifferentialChangesScreen: 変更トークンの取得と、ヘルスコネクトからの新しい変更の取得を行います。

HealthConnectManager: ヘルスコネクトとのやり取りを行うすべての関数が格納されます。この Codelab では、基本的な機能を完成させるための手順を詳細に説明します。start ビルド内の <!-- TODO: 文字列には、この Codelab 内の対応するセクションがあり、プロジェクトに挿入するためのサンプルコードが提供されています。

まず、ヘルスコネクトをプロジェクトに追加します。

ヘルスコネクト クライアント SDK を追加する

ヘルスコネクト SDK の使用を開始するには、build.gradle ファイルに依存関係を追加する必要があります。ヘルスコネクトの最新バージョンを確認するには、Jetpack ライブラリのリリースをご覧ください。

dependencies {
    // Add a dependency of Health Connect SDK
    implementation "androidx.health.connect:connect-client:1.1.0-alpha10"
}

ヘルスコネクトの公開設定を宣言する

アプリ内で Health Connect とやり取りするには、AndroidManifest.xml でヘルスコネクト パッケージ名を宣言します。

<!-- TODO: declare Health Connect visibility -->
<queries>
   <package android:name="com.google.android.apps.healthdata" />
</queries>

start プロジェクトを実行する

すべての設定を終えたら、start プロジェクトを実行します。この時点で、「ヘルスコネクトはこのデバイスにインストールされています」と表示されるウェルカム画面とメニュー ドロワーが表示されるはずです。ヘルスコネクトとやり取りする機能については、後のセクションで追加します。

8f063e5b305189.png fd39f325f5c19e5d.png

3. 権限の管理

ヘルスコネクトでは、権限のリクエストをアプリで使用されるデータ型に制限することがデベロッパーに推奨されます。権限を包括的にリクエストすると、アプリに対するユーザーの信頼度が低下し、ユーザーの信用を損なう可能性があります。権限リクエストが 3 回以上拒否されると、アプリがロックアウトされます。その結果、権限のリクエストが表示されなくなります。

この Codelab では、次の権限のみが必要です。

  • エクササイズ セッション
  • 心拍数
  • 歩数
  • 総消費カロリー
  • 体重

権限を宣言する

アプリが読み書きするデータ型はすべて、AndroidManifest.xml 内で権限を使用して宣言する必要があります。バージョン 1.0.0-alpha10 以降のヘルスコネクトでは、標準的な Android 権限の宣言形式を使用します。

必要なデータ型の権限を宣言するには、<uses-permission> 要素を使用して権限にそれぞれの名前を割り当てます。<manifest> タグ内にネストします。権限とそれに対応するデータ型の一覧については、データ型のリストをご覧ください。

<!-- TODO: Required to specify which Health Connect permissions the app can request -->
  <uses-permission android:name="android.permission.health.READ_HEART_RATE"/>
  <uses-permission android:name="android.permission.health.WRITE_HEART_RATE"/>
  <uses-permission android:name="android.permission.health.READ_STEPS"/>
  <uses-permission android:name="android.permission.health.WRITE_STEPS"/>
  <uses-permission android:name="android.permission.health.READ_EXERCISE"/>
  <uses-permission android:name="android.permission.health.WRITE_EXERCISE"/>
  <uses-permission android:name="android.permission.health.READ_TOTAL_CALORIES_BURNED"/>
  <uses-permission android:name="android.permission.health.WRITE_TOTAL_CALORIES_BURNED"/>
  <uses-permission android:name="android.permission.health.READ_WEIGHT"/>
  <uses-permission android:name="android.permission.health.WRITE_WEIGHT"/>

AndroidManifest.xml でインテント フィルタを宣言して、そうした権限をアプリでどのように使用するかを説明するインテントを処理します。アプリはこのインテントを処理して、ユーザーデータの使用方法と処理方法を説明したプライバシー ポリシーを表示する必要があります。ユーザーがヘルスコネクトの権限ダイアログでプライバシー ポリシーのリンクをタップすると、このインテントがアプリに送信されます。

<!-- TODO: Add intent filter to handle permission rationale intent -->
<!-- Permission handling for Android 13 and before -->
<intent-filter>
  <action android:name="androidx.health.ACTION_SHOW_PERMISSIONS_RATIONALE" />
</intent-filter>

<!-- Permission handling for Android 14 and later -->
<intent-filter>
  <action android:name="android.intent.action.VIEW_PERMISSION_USAGE"/>
  <category android:name="android.intent.category.HEALTH_PERMISSIONS"/>
</intent-filter>

次にアプリを再度開いて、宣言された権限を確認します。メニュー ドロワーの [Settings] をクリックして、[Health Connect Settings] 画面に移動します。次に、[App permissions] をクリックすると、リストに [Health Connect Codelab] が表示されます。[Health Connect Codelab] をクリックして、対象のアプリの読み取り / 書き込みアクセス権のデータ型のリストを表示します。

fbed69d871f92178.png 1b9c7764c1dbdfac.png

権限をリクエストする

権限を管理する際は、ユーザーをヘルスコネクトの設定に直接誘導するほかに、Health Connect API を介してアプリから権限をリクエストすることもできます。ユーザーはいつでも権限を変更する可能性があるため、必要な権限が利用できるかどうかをアプリでチェックしてください。この Codelab プロジェクトでは、データの読み取りまたは書き込みの前にチェックを行い、権限リクエストを送信します。

HealthConnectClient が Health Connect API のエントリ ポイントです。HealthConnectManager.kt で、HealthConnectClient インスタンスを取得します。

private val healthConnectClient by lazy { HealthConnectClient.getOrCreate(context) }

アプリ内で権限リクエスト ダイアログを開始するには、まず、必要なデータ型の権限セットを作成します。使用するデータ型に対する権限のみをリクエストする必要があります。

たとえば、[Record weight] 画面では、体重の読み取り / 書き込み権限のみを付与する必要があります。次のコードのように、InputReadingsViewModel.kt に権限セットを作成しました。

  val permissions = setOf(
    HealthPermission.getReadPermission(WeightRecord::class),
    HealthPermission.getWritePermission(WeightRecord::class),
  )

次に、権限のリクエストを実行する前に、権限が付与されているかどうかを確認します。HealthConnectManager.kt で、getGrantedPermissions を使用して、必要なデータ型の権限が付与されているかどうかを確認します。権限リクエストを実行するには、PermissionController.createRequestPermissionResultContract() を使用して ActivityResultContract を作成する必要があります。このコードは、必要な権限が付与されていない場合に実行する必要があります。

  suspend fun hasAllPermissions(permissions: Set<String>): Boolean {
    return healthConnectClient.permissionController.getGrantedPermissions().containsAll(permissions)
  }

  fun requestPermissionsActivityContract(): ActivityResultContract<Set<String>, Set<String>> {
    return PermissionController.createRequestPermissionResultContract()
  }

Codelab サンプルアプリで、必要なデータ型に権限を付与していない場合、画面に [Request permissions] ボタンが表示されることがあります。[Request permissions] をクリックして、ヘルスコネクトの権限ダイアログを開きます。必要な権限を許可して、Codelab アプリに戻ります。

a0eb27cea376e56f.png 4752973f6b0b8d56.png

4. データを書き込む

ヘルスコネクトへのレコードの書き込みを開始します。体重のレコードを書き込むには、体重の入力値を含む WeightRecord オブジェクトを作成します。ヘルスコネクト SDK はさまざまな単位クラスをサポートしています。たとえば、Mass.kilograms(weightInput) を使用すると、ユーザーの体重をキログラム単位で設定できます。

基本的に、ヘルスコネクトに書き込むデータには常にゾーン オフセット情報を指定するようにします。データの書き込み時にゾーン オフセット情報を指定すると、ヘルスコネクトのデータを読み取った際にタイムゾーン情報が提供されます。

体重レコードを作成したら、healthConnectClient.insertRecords を使ってヘルスコネクトにデータを書き込みます。

/**
* TODO: Writes [WeightRecord] to Health Connect.
*/
suspend fun writeWeightInput(weightInput: Double) {
   val time = ZonedDateTime.now().withNano(0)
   val weightRecord = WeightRecord(
       weight = Mass.kilograms(weightInput),
       time = time.toInstant(),
       zoneOffset = time.offset
   )
   val records = listOf(weightRecord)
   try {
      healthConnectClient.insertRecords(records)
      Toast.makeText(context, "Successfully insert records", Toast.LENGTH_SHORT).show()
   } catch (e: Exception) {
      Toast.makeText(context, e.message.toString(), Toast.LENGTH_SHORT).show()
   }
}

次に、アプリを実行します。[Record weight] をクリックし、新しい体重レコードをキログラム単位で入力します。体重レコードがヘルスコネクトに正常に書き込まれたかどうかを確認するには、ヘルスコネクト アプリの設定を開き、[データとアクセス] > [身体測定] > [体重] > [すべてのエントリを表示] をクリックします。ヘルスコネクト Codelab から書き込まれた新しい体重レコードが表示されます。

エクササイズ セッションを書き込む

セッションとは、ユーザーがアクティビティを実施する期間です。ヘルスコネクトのエクササイズ セッションには、ランニングからバドミントンまで、さまざまなものがあります。セッションにより、ユーザーは時間ベースのパフォーマンスを測定できます。このデータには、一定期間にわたって測定された一連の瞬間的なサンプル(アクティビティ中の連続的な心拍数や位置情報のサンプルなど)が記録されます。

次の例は、エクササイズ セッションを書き込む方法を示しています。healthConnectClient.insertRecords を使用して、セッションに関連付けられた複数のデータレコードを挿入します。この例の挿入リクエストには、ExerciseType を含む ExerciseSessionRecord、歩数を含む StepsRecordEnergy を含む TotalCaloriesBurnedRecord、および一連の HeartRateRecord サンプルが含まれます。

  /**
   * TODO: Writes an [ExerciseSessionRecord] to Health Connect.
   */
  suspend fun writeExerciseSession(start: ZonedDateTime, end: ZonedDateTime) {
    healthConnectClient.insertRecords(
      listOf(
        ExerciseSessionRecord(
          startTime = start.toInstant(),
          startZoneOffset = start.offset,
          endTime = end.toInstant(),
          endZoneOffset = end.offset,
          exerciseType = ExerciseSessionRecord.EXERCISE_TYPE_RUNNING,
          title = "My Run #${Random.nextInt(0, 60)}"
        ),
        StepsRecord(
          startTime = start.toInstant(),
          startZoneOffset = start.offset,
          endTime = end.toInstant(),
          endZoneOffset = end.offset,
          count = (1000 + 1000 * Random.nextInt(3)).toLong()
        ),
        TotalCaloriesBurnedRecord(
          startTime = start.toInstant(),
          startZoneOffset = start.offset,
          endTime = end.toInstant(),
          endZoneOffset = end.offset,
          energy = Energy.calories((140 + Random.nextInt(20)) * 0.01)
        )
      ) + buildHeartRateSeries(start, end)
    )
  }

  /**
   * TODO: Build [HeartRateRecord].
   */
  private fun buildHeartRateSeries(
    sessionStartTime: ZonedDateTime,
    sessionEndTime: ZonedDateTime,
  ): HeartRateRecord {
    val samples = mutableListOf<HeartRateRecord.Sample>()
    var time = sessionStartTime
    while (time.isBefore(sessionEndTime)) {
      samples.add(
        HeartRateRecord.Sample(
          time = time.toInstant(),
          beatsPerMinute = (80 + Random.nextInt(80)).toLong()
        )
      )
      time = time.plusSeconds(30)
    }
    return HeartRateRecord(
      startTime = sessionStartTime.toInstant(),
      startZoneOffset = sessionStartTime.offset,
      endTime = sessionEndTime.toInstant(),
      endZoneOffset = sessionEndTime.offset,
      samples = samples
    )
  }

5. データを読み取る

これで、Codelab サンプルアプリとツールボックス アプリの両方で、体重とエクササイズ セッションのレコードを書き込めました。Health Connect API を使用してこれらのレコードを読み取りましょう。まず ReadRecordsRequest を作成し、読み取るレコードタイプと期間を指定します。ReadRecordsRequest で、dataOriginFilter を設定して、読み取り元のレコードのソースアプリを指定することもできます。

    /**
     * TODO: Reads in existing [WeightRecord]s.
     */
    suspend fun readWeightInputs(start: Instant, end: Instant): List<WeightRecord> {
        val request = ReadRecordsRequest(
            recordType = WeightRecord::class,
            timeRangeFilter = TimeRangeFilter.between(start, end)
        )
        val response = healthConnectClient.readRecords(request)
        return response.records
    }
  /**
   * TODO: Obtains a list of [ExerciseSessionRecord]s in a specified time frame.
   */
  suspend fun readExerciseSessions(start: Instant, end: Instant): List<ExerciseSessionRecord> {
    val request = ReadRecordsRequest(
      recordType = ExerciseSessionRecord::class,
      timeRangeFilter = TimeRangeFilter.between(start, end)
    )
    val response = healthConnectClient.readRecords(request)
    return response.records
  }

アプリを実行して、体重のレコードとエクササイズ セッションのリストが表示されるかどうかを確認しましょう。

a08af54eef6bc832.png 3b0781389f1094a1.png

6. バックグラウンドでデータを読み取る

権限を宣言する

バックグラウンドで健康に関するデータにアクセスするには、AndroidManifest.xml ファイルで READ_HEALTH_DATA_IN_BACKGROUND 権限を宣言します。

<!-- TODO: Required to specify which Health Connect permissions the app can request -->
...
<uses-permission android:name="android.permission.health.READ_HEALTH_DATA_IN_BACKGROUND" />

機能が使用できることを確認する

ヘルスコネクトの最新バージョンを使用していないユーザーもいるため、まず機能が使用できるかどうか確認することをおすすめします。HealthConnectManager.kt では、getFeatureStatus メソッドを使用してこれを行います。

fun isFeatureAvailable(feature: Int): Boolean{
    return healthConnectClient
      .features
      .getFeatureStatus(feature) == HealthConnectFeatures.FEATURE_STATUS_AVAILABLE
  }

ExerciseSessionViewModel.kt のバックグラウンドでの読み取り機能は、FEATURE_READ_HEALTH_DATA_IN_BACKGROUND 定数を使用して確認できます。

backgroundReadAvailable.value = healthConnectManager.isFeatureAvailable(
      HealthConnectFeatures.FEATURE_READ_HEALTH_DATA_IN_BACKGROUND
    )

権限をリクエストする

バックグラウンドでの読み取り機能が使用できることを確認したら、[Exercise sessions] 画面で [Request Background Read] をクリックして、PERMISSION_READ_HEALTH_DATA_IN_BACKGROUND 権限をリクエストできます。

ユーザーには次のプロンプトが表示されます。

18796e03ae3941b1.png

ユーザーは、システム設定で [ヘルスコネクト] > [アプリの権限] > [Health Connect Codelab] > [アクセス権の追加] に移動して、バックグラウンドでの読み取り権限を付与することもできます。

958081eb9b1fecb3.png

バックグラウンドでデータを読み取る

WorkManager を使用してバックグラウンド タスクのスケジュールを設定します。[Read Steps In Background] ボタンをタップすると、10 秒の遅延後にアプリが ReadStepWorker を開始します。この Worker は、過去 24 時間の総歩数をヘルスコネクトから取得します。その後、この情報の詳細を示す同様のログエントリが Logcat に表示されます。

There are 4000 steps in Health Connect in the last 24 hours.

7. 差分データを読み取る

ヘルスコネクトの Differential Changes API は、一連のデータ型について、特定の時点からの変更を追跡するのに役立ちます。たとえば、ユーザーがアプリの外部で既存のレコードを更新または削除したかどうかを把握し、それに応じてデータベースを更新できます。

ヘルスコネクトでのデータの読み取りは、フォアグラウンドで実行されているアプリに制限されています。この制限は、ユーザーのプライバシー保護を強化するために設けられたものです。ヘルスコネクトにはデータのバックグラウンドでの読み取りアクセス権がなく、データの読み取りとアクセスはフォアグラウンドでのみ行えることがユーザーに通知され、保証されます。アプリがフォアグラウンドにあるとき、Differential Changes API を使用すると、デベロッパーは変更トークンをデプロイして、ヘルスコネクトに加えられた変更を取得できます。

HealthConnectManager.kt には getChangesToken()getChanges() の 2 つの関数があります。これらの関数に Differential Changes API を追加して、データの変更を取得します。

最初の変更トークンの設定

ヘルスコネクトからデータの変更が取得されるのは、アプリが変更トークンでリクエストした場合のみです。変更トークンは、差分データの取得元となる commit 履歴内のポイントを表します。

変更トークンを取得するには、データの変更を追跡する一連のデータ型を指定して ChangesTokenRequest を送信します。このトークンを保管しておき、ヘルスコネクトからアップデートを取得するときに使用します。

  /**
   * TODO: Obtains a Changes token for the specified record types.
   */
  suspend fun getChangesToken(): String {
    return healthConnectClient.getChangesToken(
      ChangesTokenRequest(
        setOf(
          ExerciseSessionRecord::class
        )
      )
    )
  }

変更トークンによるデータ更新

アプリがヘルスコネクトと最後に同期したときからの変更を取得するには、以前に取得した変更トークンを使用し、そのトークンを含む getChanges 呼び出しを送信します。ChangesResponse は、ヘルスコネクトで検出された変更(UpsertionChangeDeletionChange など)のリストを返します。

  /**
   * TODO: Retrieve changes from a Changes token.
   */
  suspend fun getChanges(token: String): Flow<ChangesMessage> = flow {
    var nextChangesToken = token
    do {
      val response = healthConnectClient.getChanges(nextChangesToken)
      if (response.changesTokenExpired) {
        throw IOException("Changes token has expired")
      }
      emit(ChangesMessage.ChangeList(response.changes))
      nextChangesToken = response.nextChangesToken
    } while (response.hasMore)
    emit(ChangesMessage.NoMoreChanges(nextChangesToken))
  }

次に、アプリを実行し、[Changes] 画面に移動します。まず、[Track changes] を有効にして、変更トークンを取得します。次に、ツールボックスまたは Codelab アプリから、体重またはエクササイズ セッションを挿入します。[Changes] 画面に戻り、[Get new changes] を選択します。アップサートの変更が表示されます。

f3aded8ae5487e9c.png 437d69e3e000ce81.png

8. データを集計する

ヘルスコネクトは、集計 API を介して集計データも提供します。次の例は、ヘルスコネクトから累積データと統計データを取得する方法を示しています。

healthConnectClient.aggregate を使用して AggregateRequest を送信します。集計リクエストで、一連の集計指標と取得する時間範囲を指定します。たとえば、ExerciseSessionRecord.EXERCISE_DURATION_TOTALStepsRecord.COUNT_TOTAL は累積データ、WeightRecord.WEIGHT_AVGHeartRateRecord.BPM_MAXHeartRateRecord.BPM_MIN は統計データを提供します。

    /**
     * TODO: Returns the weekly average of [WeightRecord]s.
     */
    suspend fun computeWeeklyAverage(start: Instant, end: Instant): Mass? {
        val request = AggregateRequest(
            metrics = setOf(WeightRecord.WEIGHT_AVG),
            timeRangeFilter = TimeRangeFilter.between(start, end)
        )
        val response = healthConnectClient.aggregate(request)
        return response[WeightRecord.WEIGHT_AVG]
    }

この例では、特定のエクササイズ セッションの関連集計データを取得する方法を示します。まず、uidhealthConnectClient.readRecord を使用してレコードを読み取ります。次に、エクササイズ セッションの startTimeendTime を時間範囲、dataOrigin をフィルタとして使用し、関連集計データを読み取ります。

  /**
   * TODO: Reads aggregated data and raw data for selected data types, for a given [ExerciseSessionRecord].
   */
  suspend fun readAssociatedSessionData(
      uid: String,
  ): ExerciseSessionData {
    val exerciseSession = healthConnectClient.readRecord(ExerciseSessionRecord::class, uid)
    // Use the start time and end time from the session, for reading raw and aggregate data.
    val timeRangeFilter = TimeRangeFilter.between(
      startTime = exerciseSession.record.startTime,
      endTime = exerciseSession.record.endTime
    )
    val aggregateDataTypes = setOf(
      ExerciseSessionRecord.EXERCISE_DURATION_TOTAL,
      StepsRecord.COUNT_TOTAL,
      TotalCaloriesBurnedRecord.ENERGY_TOTAL,
      HeartRateRecord.BPM_AVG,
      HeartRateRecord.BPM_MAX,
      HeartRateRecord.BPM_MIN,
    )
    // Limit the data read to just the application that wrote the session. This may or may not
    // be desirable depending on the use case: In some cases, it may be useful to combine with
    // data written by other apps.
    val dataOriginFilter = setOf(exerciseSession.record.metadata.dataOrigin)
    val aggregateRequest = AggregateRequest(
      metrics = aggregateDataTypes,
      timeRangeFilter = timeRangeFilter,
      dataOriginFilter = dataOriginFilter
    )
    val aggregateData = healthConnectClient.aggregate(aggregateRequest)
    val heartRateData = readData<HeartRateRecord>(timeRangeFilter, dataOriginFilter)

    return ExerciseSessionData(
      uid = uid,
      totalActiveTime = aggregateData[ExerciseSessionRecord.EXERCISE_DURATION_TOTAL],
      totalSteps = aggregateData[StepsRecord.COUNT_TOTAL],
      totalEnergyBurned = aggregateData[TotalCaloriesBurnedRecord.ENERGY_TOTAL],
      minHeartRate = aggregateData[HeartRateRecord.BPM_MIN],
      maxHeartRate = aggregateData[HeartRateRecord.BPM_MAX],
      avgHeartRate = aggregateData[HeartRateRecord.BPM_AVG],
      heartRateSeries = heartRateData,
    )
  }

次に、アプリを実行して、[Record weight] 画面に平均体重が表示されるかどうかを確認します。また、エクササイズ セッションの詳細なデータを表示するには、[Exercise sessions] 画面を開き、エクササイズ セッションのレコードのいずれかを選択します。

af1fe646159d6a60.png

9. 完了

これで、ヘルスコネクトと統合された健康&フィットネス アプリを初めて構築できました。

アプリは、権限を宣言し、アプリで使用されているデータ型に関するユーザー権限をリクエストできます。ヘルスコネクトのデータ ストレージに対して、データの読み取りと書き込みを行うこともできます。また、ヘルスコネクト ツールボックスを使用して、ヘルスコネクトのデータ ストレージにモックデータを作成し、アプリ開発をサポートする方法も学びました。

これで、健康&フィットネス アプリをヘルスコネクト エコシステムに組み込むために必要な主な手順を学習できました。

参考資料