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

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

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

このガイドでは、健康指標データ型を操作する方法について説明します。権限、読み取りと書き込みのワークフロー、ベスト プラクティスについて解説します。

概要: 包括的な主な指標トラッカーの構築

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

  • 健康指標データ型に対する適切な権限をリクエストする。
  • 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

血圧など、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 件のレコードのバッチでデータポイントを 1 回の 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 などの間隔データの場合は、startTimeendTime が正しいことを確認します。

テスト

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

確認ツール

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

品質チェックリスト

一般的なアーキテクチャ

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

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

トラブルシューティング

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

一般的なデバッグ手順

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