ヘルスコネクトでバイタル エクスペリエンスを開発する

ユーザーの主な指標を管理するアプリを構築する場合は、ヘルスコネクトを使用して次のようなことができます。

  • 他のアプリから血圧、心拍数、体温などのバイタルデータを読み取る
  • アプリや接続されたデバイスで記録されたバイタルデータを書き込む
  • バイタルデータに基づいて傾向をモニタリングし、健康に関する分析情報を提供する

このガイドでは、バイタル データ型の使用方法について説明します。権限、読み取りと書き込みのワークフロー、ベスト プラクティスについて説明します。

概要: 包括的なバイタル トラッカーの構築

ヘルスコネクトを使用して包括的な主な指標トラッキング エクスペリエンスを構築するには、次のコアステップに沿って操作します。

  • バイタル データ型に対する適切な権限をリクエストする。
  • BloodPressureRecordHeartRateRecord などのレコードやその他の主な指標レコードを使用して主な指標データを書き込みます。
  • 表示、分析、同期のための主な指標データの読み取り。
  • バッチ処理を使用して、データの書き込みと読み取りを効率的に行います。

このワークフローにより、他のヘルスコネクト アプリとの相互運用が可能になり、ユーザーが制御するデータアクセスが検証されます。

始める前に

バイタル機能の実装前:

主な概念

ヘルスコネクトの主な指標データは、さまざまなレコードタイプで表されます。各レコードタイプは、特定の生理学的測定に対応しています。ワークアウト セッションとは異なり、主な指標は多くの場合、特定の時点のデータまたは間隔ベースのデータとして記録されます。

主な指標のデータ型

主な指標データは、個々のレコードタイプで表されます。一般的なタイプは次のとおりです。

データ型の一覧については、ヘルスコネクトのデータ型をご覧ください。

開発時の考慮事項

主な指標データは機密情報である可能性があり、アプリはセンサーの測定値やユーザー入力に応じてデータを書き込むか、バックエンドからデータを同期する必要があります。健康指標データを扱うには権限が重要です。

権限

アプリは、主な指標データを読み書きする前に、関連するヘルスコネクトの権限をリクエストする必要があります。バイタルの一般的な権限には、血圧、心拍数、体温、血糖値、酸素飽和度、呼吸数などがあります。以下のようなデータが収集されます。

次の例は、血圧、心拍数、体温の権限をリクエストする方法を示しています。

クライアント インスタンスを作成した後、アプリはユーザーに権限をリクエストする必要があります。ユーザーがいつでも権限を付与または拒否できるようにする必要があります。

そのためには、必要なデータ型の権限セットを作成します。まず、セット内の権限が Android マニフェストで宣言されていることを確認します。

// Create a set of permissions for required data types
val PERMISSIONS =
    setOf(
  HealthPermission.getReadPermission(BloodPressureRecord::class),
  HealthPermission.getWritePermission(BloodPressureRecord::class),
  HealthPermission.getReadPermission(HeartRateRecord::class),
  HealthPermission.getWritePermission(HeartRateRecord::class),
  HealthPermission.getReadPermission(BodyTemperatureRecord::class),
  HealthPermission.getWritePermission(BodyTemperatureRecord::class)
)

getGrantedPermissions を使用して、アプリが必要な権限をすでに持っているかどうかを確認します。持っていない場合は、createRequestPermissionResultContract を使用して権限をリクエストします。ヘルスコネクトの権限画面が表示されます。

// Create the permissions launcher
val requestPermissionActivityContract = PermissionController.createRequestPermissionResultContract()

val requestPermissions = registerForActivityResult(requestPermissionActivityContract) { granted ->
  if (granted.containsAll(PERMISSIONS)) {
    // Permissions successfully granted
  } else {
    // Lack of required permissions
  }
}

suspend fun checkPermissionsAndRun(healthConnectClient: HealthConnectClient) {
  val granted = healthConnectClient.permissionController.getGrantedPermissions()
  if (granted.containsAll(PERMISSIONS)) {
    // Permissions already granted; proceed with inserting or reading data
  } else {
    requestPermissions.launch(PERMISSIONS)
  }
}

ユーザーはいつでも権限を付与または取り消すことができるため、アプリは権限を使用するたびに権限をチェックし、権限が失われた状況に対応できるように設計する必要があります。

権限をリクエストするには、checkPermissionsAndRun 関数を呼び出します。

if (!granted.containsAll(PERMISSIONS)) {
    requestPermissions.launch(PERMISSIONS)
    // Check if required permissions are not granted, and return
  }
// Permissions already granted; proceed with inserting or reading data

血圧など、単一のデータ型の権限のみをリクエストする必要がある場合は、権限セットにそのデータ型のみを含めます。

血圧へのアクセスは、次の権限によって保護されています。

  • android.permission.health.READ_BLOOD_PRESSURE
  • android.permission.health.WRITE_BLOOD_PRESSURE

血圧機能をアプリに追加するには、まず BloodPressureRecord データ型の権限をリクエストします。

血圧を書き込むために宣言する必要がある権限は次のとおりです。

<application>
  <uses-permission
android:name="android.permission.health.WRITE_BLOOD_PRESSURE" />
...
</application>

血圧を読み取るには、次の権限をリクエストする必要があります。

<application>
  <uses-permission
android:name="android.permission.health.READ_BLOOD_PRESSURE" />
...
</application>

主な指標データを書き込む

このセクションでは、主な指標データをヘルスコネクトに書き込む方法について説明します。主な指標データは通常、個々のレコードとして書き込まれます。センサーやバックエンドからの同期など、複数のレコードを一度に書き込む場合は、バッチ処理を使用します。

BloodPressureRecord の記述例:

suspend fun writeBloodPressureRecord(healthConnectClient: HealthConnectClient) {
    val record = BloodPressureRecord(
        time = Instant.now(),
        zoneOffset = ZoneOffset.UTC,
        systolic = Pressure.millimetersOfMercury(120.0),
        diastolic = Pressure.millimetersOfMercury(80.0),
        bodyPosition = BloodPressureRecord.BODY_POSITION_SITTING_DOWN,
        measurementLocation = BloodPressureRecord.MEASUREMENT_LOCATION_LEFT_WRIST
    )
    healthConnectClient.insertRecords(listOf(record))
}

バッチ書き込み

接続されたデバイスやバックエンド サービスからデータを同期するなど、アプリが複数のデータポイントを書き込む必要がある場合は、効率を高め、バッテリー消費を抑えるために、書き込みをバッチ処理する必要があります。ヘルスコネクトは、1 回の書き込みリクエストで最大 1,000 件のレコードを処理できます。

次のコードは、複数のレコードを一度にバッチ書き込みする方法を示しています。

suspend fun writeBatchRecords(healthConnectClient: HealthConnectClient) {
    val bloodPressureRecord = BloodPressureRecord(
        time = Instant.now(),
        zoneOffset = ZoneOffset.UTC,
        systolic = Pressure.millimetersOfMercury(120.0),
        diastolic = Pressure.millimetersOfMercury(80.0),
        bodyPosition = BloodPressureRecord.BODY_POSITION_SITTING_DOWN,
        measurementLocation = BloodPressureRecord.MEASUREMENT_LOCATION_LEFT_WRIST
    )
    val heartRateRecord = HeartRateRecord(
        startTime = Instant.now().minusSeconds(60),
        startZoneOffset = ZoneOffset.UTC,
        endTime = Instant.now(),
        endZoneOffset = ZoneOffset.UTC,
        samples = listOf(HeartRateRecord.Sample(time = Instant.now().minusSeconds(30), beatsPerMinute = 80))
    )
    healthConnectClient.insertRecords(listOf(bloodPressureRecord, heartRateRecord))
}

健康指標データの読み取り

アプリは、バイタル データから測定値を読み取って表示したり、傾向を分析したり、データを外部サーバーと同期したりできます。主な指標を読み取るには、特定のレコードタイプで ReadRecordsRequest を使用し、期間でフィルタします。

BloodPressureRecord データの読み取りの例:

suspend fun readBloodPressureRecords(
    healthConnectClient: HealthConnectClient,
    startTime: Instant,
    endTime: Instant
) {
    val response = healthConnectClient.readRecords(
        ReadRecordsRequest(
            recordType = BloodPressureRecord::class,
            timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
        )
    )

    for (record in response.records) {
        // Process each blood pressure record
        val systolic = record.systolic
        val diastolic = record.diastolic
    }
}

バイタルデータをバックエンド サーバーと同期する必要がある場合や、アプリのデータストアをヘルスコネクトで最新の状態に保つ必要がある場合は、ChangeLog を使用します。これにより、特定の時点以降に挿入、更新、削除されたレコードのリストを取得できます。これは、変更を手動で追跡したり、すべてのデータを繰り返し読み取ったりするよりも効率的です。詳しくは、ヘルスコネクトとデータを同期するをご覧ください。

ベスト プラクティス

以下のガイドラインに沿って、データの信頼性とユーザー エクスペリエンスを向上させてください。

  • 書き込み頻度とバッチ処理: 入出力のオーバーヘッドを減らし、バッテリー駆動時間を維持するため、各ポイントを個別に書き込むのではなく、最大 1,000 件のレコードのバッチで 1 回の insertRecords 呼び出しにデータポイントをグループ化します。
    • ライブ トラッキング: センサー(持続血糖モニターや心拍数モニターなど)から頻繁に更新されるデータについては、リアルタイム更新とバッテリー効率のバランスを取るため、最大 15 分間隔でバッチでデータを書き込みます。
    • バックグラウンド同期: コンパニオン デバイスやバックエンド サービスからのデータの同期など、遅延書き込みには WorkManager を使用します。バッチ書き込みの間隔は 15 分に設定します。
  • 重複データの書き込みを避ける: クライアント ID を使用する レコードを作成するときに、metadata.clientRecordId を設定します。ヘルスコネクトはこれを使用して一意のレコードを識別します。すでに存在する clientRecordId を含むレコードを書き込もうとすると、ヘルスコネクトは重複を無視するか、新しいレコードを作成するのではなく既存のレコードを更新します。metadata.clientRecordId を設定することは、同期の再試行やアプリの再インストール時に重複を防ぐ最も効果的な方法です。

    val record = BloodPressureRecord(
        time = Instant.now(),
        zoneOffset = ZoneOffset.UTC,
        systolic = Pressure.millimetersOfMercury(120.0),
        diastolic = Pressure.millimetersOfMercury(80.0),
        bodyPosition = BloodPressureRecord.BODY_POSITION_SITTING_DOWN,
        measurementLocation = BloodPressureRecord.MEASUREMENT_LOCATION_LEFT_WRIST,
        metadata = Metadata(
            // Use a unique ID from your own database
            clientRecordId = "bp_20240101_user123"
        )
    )
  • 既存のデータを確認する: データを同期する前に、同期期間内のレコードをヘルスコネクトにクエリして、アプリのデータがすでに存在するかどうかを確認し、重複や新しいデータの上書きを回避します。

  • 権限の明確な理由を提示する: Permission.createIntent フローを使用して、アプリが健康データにアクセスする必要がある理由を説明します(例: 「血圧の傾向をモニタリングして分析情報を提供するため」)。

  • タイムスタンプを測定値と一致させる: 測定が行われた日時が記録のタイムスタンプに正確に反映されていることを確認します。HeartRateRecord などの間隔データの場合は、startTimeendTime が正しいことを確認します。

テスト

データの正確性と高品質のユーザー エクスペリエンスを確認するには、次のテスト戦略に沿って、公式のテストの主なユースケースのドキュメントを参照してください。

確認ツール

  • ヘルスコネクト ツールボックス: このコンパニオン アプリを使用して、レコードを手動で検査したり、テストデータを削除したり、データベースの変更をシミュレートしたりします。これは、レコードが正しく保存されていることを確認する最良の方法です。
  • FakeHealthConnectClient を使用した単体テスト: テスト ライブラリを使用して、**実機**を必要とせずに、権限の取り消しや API 例外などのエッジケースをアプリがどのように処理するかを確認します。

品質チェックリスト

一般的なアーキテクチャ

主な指標の実装には通常、次のものが含まれます。

コンポーネント 管理
Vitals コントローラ センサー/入力読み取り
バッチ処理ロジック
リポジトリ レイヤ(ヘルスコネクト オペレーションをラップします): 健康指標レコードを挿入する
健康指標レコードを読み取る
UI レイヤ(ディスプレイ): ライブの測定値
過去のデータ
グラフと傾向

トラブルシューティング

内容 考えられる原因 解像度
データ型がない(血圧など) 書き込み権限がないか、時間フィルタが正しくありません。 特定のデータタイプの権限をリクエストし、ユーザーが付与していることを確認します。ReadRecordsRequest が測定時間をカバーする TimeRangeFilter を使用していることを確認します。権限をご覧ください。
重複するレコードが表示される clientRecordId がありません。 各レコードの Metadata で一意の clientRecordId を割り当てます。これにより、同期の再試行中に同じデータが 2 回書き込まれた場合に、ヘルスコネクトで重複除去を実行できます。ベスト プラクティスをご覧ください。
レコードの書き込みに失敗する 単位が正しくないか、値が有効な範囲外です。 ヘルスコネクトはレコード値を検証します。たとえば、血圧の値は生理学的に妥当な範囲内である必要があります。有効な範囲と単位については、データ型のドキュメントをご覧ください。

一般的なデバッグ手順

権限の状態を確認します。 読み取りまたは書き込みオペレーションを試みる前に、必ず getPermissionStatus() を呼び出してください。ユーザーはシステム設定でいつでも権限を取り消すことができます。