データを書き込む

このガイドでは、ヘルスコネクトでデータの書き込みまたは更新を行うプロセスについて説明します。

データ構造を設定する

データを書き込む前に、まずレコードを設定する必要があります。50 を超えるデータ型があり、各データ型にそれぞれの構造があります。使用可能なデータ型について詳しくは、Jetpack リファレンスをご覧ください。

基本のレコード

ヘルスコネクトの Steps データ型には、各読み取りの間にユーザーが歩いた歩数が記録されます。歩数は、健康、フィットネス、ウェルネスのプラットフォームで共通の測定値を表します。

次の例は、歩数データを設定する方法を示しています。

val stepsRecord = StepsRecord(
    count = 120,
    startTime = START_TIME,
    endTime = END_TIME,
    startZoneOffset = START_ZONE_OFFSET,
    endZoneOffset = END_ZONE_OFFSET
)

測定単位を含むレコード

ヘルスコネクトでは、精度を高めるため、測定単位とともに値を格納できます。その一例が、広範囲を包括的にカバーする Nutrition データ型です。総炭水化物からビタミンまで、さまざまな栄養素項目が対象に含まれます。各データポイントは、食事または食品の一部として摂取された可能性のある栄養素を表します。

Nutrition データ型では、すべての栄養素が Mass の単位で表現され、energyEnergy の単位で表現されます。

次の例は、バナナを食べたユーザーの栄養データを設定する方法を示しています。

val banana = NutritionRecord(
    name = "banana",
    energy = 105.0.kilocalories,
    dietaryFiber = 3.1.grams,
    potassium = 0.422.grams,
    totalCarbohydrate = 27.0.grams,
    totalFat = 0.4.grams,
    saturatedFat = 0.1.grams,
    sodium = 0.001.grams,
    sugar = 14.0.grams,
    vitaminB6 = 0.0005.grams,
    vitaminC = 0.0103.grams,
    startTime = START_TIME,
    endTime = END_TIME,
    startZoneOffset = START_ZONE_OFFSET,
    endZoneOffset = END_ZONE_OFFSET
)

系列データを含むレコード

ヘルスコネクトでは系列データのリストを格納できます。その一例が、読み取り間に検出された一連の心拍数のサンプルをキャプチャする Heart Rate データ型です。

このデータ型では、パラメータ samples心拍数サンプルのリストで表されます。各サンプルには、beatsPerMinute 値と time 値が含まれています。

次の例は、心拍数の系列データを設定する方法を示しています。

val heartRateRecord = HeartRateRecord(
    startTime = START_TIME,
    startZoneOffset = START_ZONE_OFFSET,
    endTime = END_TIME,
    endZoneOffset = END_ZONE_OFFSET,
    // records 10 arbitrary data, to replace with actual data
    samples = List(10) { index ->
        HeartRateRecord.Sample(
            time = START_TIME + Duration.ofSeconds(index.toLong()),
            beatsPerMinute = 100 + index.toLong(),
        )
    }
)

データを書き込む

ヘルスコネクトの一般的なワークフローとして、データの書き込みがあります。レコードを追加するには、insertRecords を使用します。

次の例は、歩数を挿入するデータを書き込む方法を示しています。

suspend fun insertSteps(healthConnectClient: HealthConnectClient) {
    try {
        val stepsRecord = StepsRecord(
            count = 120,
            startTime = START_TIME,
            endTime = END_TIME,
            startZoneOffset = START_ZONE_OFFSET,
            endZoneOffset = END_ZONE_OFFSET
        )
        healthConnectClient.insertRecords(listOf(stepsRecord))
    } catch (e: Exception) {
        // Run error handling here
    }
}

データを更新する

1 つ以上のレコードを変更する必要がある場合、特にアプリのデータストアをヘルスコネクトのデータと同期する必要がある場合は、データを更新できます。既存のデータを更新するには、レコードの検索に使用される ID に応じて 2 つの方法があります。

メタデータ

データを更新するときに必要になるため、最初に Metadata クラスを確認することをおすすめします。作成時、ヘルスコネクトの各 Record には metadata フィールドがあります。同期に関連するプロパティは次のとおりです。

プロパティ 説明
id ヘルスコネクトの各 Record には一意の id 値があります。
ヘルスコネクトでは、 新しいレコードを挿入するときに、この値が自動的に設定されます。
lastModifiedTime Record にはレコードの最終更新日時も記録されます。
この値はヘルスコネクトによって自動的に入力されます。
clientRecordId Record に一意の ID を関連付けて、アプリのデータストアで参照として使用することができます。
この値はアプリが指定します。
clientRecordVersion レコードに clientRecordId がある場合は、clientRecordVersion を使用して、データをアプリ データストアのバージョンと同期させることができます。
この値はアプリが指定します。

レコード ID を介して更新する

データを更新するには、まず必要なレコードを用意します。必要に応じてレコードに変更を加えます。次に、updateRecords を呼び出して変更を行います。

次の例は、データを更新する方法を示しています。この目的のために、各レコードのゾーン オフセット値は PST に調整されます。

suspend fun updateSteps(
    healthConnectClient: HealthConnectClient,
    prevRecordStartTime: Instant,
    prevRecordEndTime: Instant
) {
    try {
        val request = healthConnectClient.readRecords(
            ReadRecordsRequest(
                recordType = StepsRecord::class,
                timeRangeFilter = TimeRangeFilter.between(
                    prevRecordStartTime,
                    prevRecordEndTime
                )
            )
        )

        val newStepsRecords = arrayListOf<StepsRecord>()
        for (record in request.records) {
            // Adjusted both offset values to reflect changes
            val sr = StepsRecord(
                count = record.count,
                startTime = record.startTime,
                startZoneOffset = record.startTime.atZone(ZoneId.of("PST")).offset,
                endTime = record.endTime,
                endZoneOffset = record.endTime.atZone(ZoneId.of("PST")).offset,
                metadata = record.metadata
            )
            newStepsRecords.add(sr)
        }

        client.updateRecords(newStepsRecords)
    } catch (e: Exception) {
        // Run error handling here
    }
}

クライアント レコード ID を介してアップサートする

省略可能なクライアント レコード ID とクライアント レコード バージョンの値を使用している場合は、updateRecords ではなく insertRecords を使用することをおすすめします。

insertRecords 関数を使用するとデータをアップサートできます。指定されたクライアント レコード ID のセットに基づくデータがヘルスコネクトに存在する場合、データは上書きされます。存在しない場合は、新しいデータとして書き込まれます。このシナリオは、アプリのデータストアからヘルスコネクトにデータを同期する必要がある場合に便利です。

次の例は、アプリのデータストアから取得されたデータに対してアップサートを実行する方法を示しています。

suspend fun pullStepsFromDatastore() : ArrayList<StepsRecord> {
    val appStepsRecords = arrayListOf<StepsRecord>()
    // Pull data from app datastore
    // ...
    // Make changes to data if necessary
    // ...
    // Store data in appStepsRecords
    // ...
    var sr = StepsRecord(
        // Assign parameters for this record
        metadata = Metadata(
            clientRecordId = cid
        )
    )
    appStepsRecords.add(sr)
    // ...
    return appStepsRecords
}

suspend fun upsertSteps(
    healthConnectClient: HealthConnectClient,
    newStepsRecords: ArrayList<StepsRecord>
) {
    try {
        healthConnectClient.insertRecords(newStepsRecords)
    } catch (e: Exception) {
        // Run error handling here
    }
}

その後、これらの関数をメインのスレッドで呼び出すことができます。

upsertSteps(healthConnectClient, pullStepsFromDatastore())

クライアント レコード バージョンの値のチェック

データをアップサートするプロセスにクライアント レコード バージョンが含まれている場合、ヘルスコネクトは clientRecordVersion 値の比較チェックを行います。挿入されるデータのバージョンが既存のデータのバージョンよりも高い場合は、アップサートが行われます。それ以外の場合は、この変更は無視され、値は同じままになります。

データにバージョニングを含めるには、バージョニングのロジックに基づいて Metadata.clientRecordVersionLong 値を指定する必要があります。

val sr = StepsRecord(
    count = count,
    startTime = startTime,
    startZoneOffset = startZoneOffset,
    endTime = endTime,
    endZoneOffset = endZoneOffset,
    metadata = Metadata(
        clientRecordId = cid,
        clientRecordVersion = version
    )
)

Upsert は、データが予期せず上書きされるのを防ぐため、変更が発生しても version を自動更新しません。そのため、今より大きな値を手動で指定する必要があります。

ベスト プラクティス

ロジックを構築したら、データの書き込みや更新を行う際にこちらのベスト プラクティスを検討してください。