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

このガイドは、ヘルスコネクトのバージョン 1.1.0 以降に対応しています。

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

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

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

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

ヘルスコネクトを使用して、バイタルを包括的に追跡するエクスペリエンスを構築するには、次の主要な手順に沿って操作します。

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

このワークフローにより、他のヘルスコネクト アプリとの相互運用性が実現し、ユーザーが管理するデータアクセスが検証されます。

始める前に

バイタル機能を実装する前に、次のことを行ってください。

主なコンセプト

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

バイタルデータの種類

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

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

開発時の考慮事項

バイタルデータは機密性が高い場合があり、アプリはセンサーからの測定値やユーザー入力に応じてデータを書き込んだり、バックエンドからデータを同期したりする必要がある場合があります。権限は、バイタルデータの取り扱いに不可欠です。

権限

アプリは、バイタルデータの読み取りまたは書き込みを行う前に、関連するヘルスコネクトの権限をリクエストする必要があります。バイタルの一般的な権限には、血圧、心拍数、体温、血糖値、酸素飽和度、呼吸数などがあります。これには次のものが含まれます。

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

クライアント インスタンスを作成した後、アプリはユーザーに権限をリクエストする必要があります。ユーザーがいつでも権限を付与または拒否できるようにする必要があります。 そのためには、必要なデータ型の権限セットを作成します。まず、セット内の権限が Android マニフェストで宣言されていることを確認します。

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 を使用して権限をリクエストします。ヘルスコネクトの権限画面が表示されます。
val permissions = setOf(
        HealthPermission.getReadPermission(StepsRecord::class),
        HealthPermission.getWritePermission(StepsRecord::class),
        HealthPermission.getReadPermission(HeartRateRecord::class),
        HealthPermission.getWritePermission(HeartRateRecord::class)
    )

val requestPermissionsLauncher = rememberLauncherForActivityResult(
    contract = PermissionController.createRequestPermissionResultContract()
) { grantedPermissions ->
    if (grantedPermissions.containsAll(permissions)) {
        coroutineScope.launch { snackbarHostState.showSnackbar("Permissions granted!") }
    } else {
        coroutineScope.launch { snackbarHostState.showSnackbar("Permissions denied.") }
    }
}
ユーザーはいつでも権限を付与または取り消すことができるため、アプリは権限を使用する前に毎回権限をチェックし、権限が失われた状況に対応できるように設計する必要があります。

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

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

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

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

  • 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
    }
}

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

ベスト プラクティス

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

  • バッチ書き込みリクエスト: 入出力のオーバーヘッドを削減し、バッテリー駆動時間を節約するには、各ポイントを個別に書き込むのではなく、最大 1,000 件のレコードのバッチを含む単一の insertRecords 呼び出しにデータポイントをグループ化します。
  • ライブ トラッキング中に頻繁に書き込む: センサー(持続血糖測定器や心拍数モニターなど)から頻繁に更新される場合は、最大 15 分間隔でデータをバッチで書き込み、リアルタイムの更新とバッテリー効率のバランスを取ります。
  • バックグラウンド同期に WorkManager を使用する: コンパニオン デバイスやバックエンド サービスからのデータの同期など、遅延書き込みには WorkManager を使用します。バッチ書き込みの間隔は 15 分にすることを目指します。
  • 重複データの書き込みを回避する: クライアント ID を使用する: レコードを作成するときに、metadata.clientRecordId を設定します。ヘルスコネクトは、これを使用して一意のレコードを識別します。すでに存在する clientRecordId を持つレコードを書き込もうとすると、ヘルスコネクトは重複を無視するか、新しいレコードを作成するのではなく既存のレコードを更新します。metadata.clientRecordId を設定することは、同期の再試行中やアプリの再インストール中に重複を防ぐ最も効果的な方法です。
    val record = StepsRecord(
        count = 100,
        startTime = startTime,
        endTime = endTime,
        startZoneOffset = ZoneOffset.UTC,
        endZoneOffset = ZoneOffset.UTC,
        metadata = Metadata(
            // Use a unique ID from your own database
            clientRecordId = "daily_steps_2023_10_27_user_123"
        )
    )
  • 既存のデータを確認する: データを同期する前に、同期期間内のレコードをヘルスコネクトにクエリして、アプリのデータがすでに存在するかどうかを確認します。これにより、重複や新しいデータの上書きを回避できます。
  • 権限が必要な理由を明確に説明する: Permission.createIntent フローを使用して、アプリが健康に関するデータへのアクセスを必要とする理由を説明します(例: 「血管ストレスの傾向をモニタリングして分析情報を提供するため」)。
  • タイムスタンプと測定値を一致させる: 記録のタイムスタンプが、測定が行われた時刻を正確に反映していることを確認します。HeartRateRecord などの間隔データの場合は、startTime と endTime が正しいことを確認します。

テスト

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

検証ツール

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

品質チェックリスト

一般的なアーキテクチャ

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

コンポーネント 管理
バイタル コントローラ センサー/入力の読み取り
バッチ処理ロジック
リポジトリ レイヤ(ヘルスコネクトのオペレーションをラップ) バイタルサインの記録の挿入
バイタルサインの記録の読み取り
UI レイヤ(ディスプレイ): リアルタイムの測定値
過去のデータ
グラフと傾向

トラブルシューティング

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

一般的なデバッグ手順

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