このガイドでは、ヘルスコネクトでデータの書き込みまたは更新を行うプロセスについて説明します。
データ構造を設定する
データを書き込む前に、まずレコードを設定する必要があります。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
の単位で表現され、energy
は Energy
の単位で表現されます。
次の例は、バナナを食べたユーザーの栄養データを設定する方法を示しています。
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.clientRecordVersion
に Long
値を指定する必要があります。
val sr = StepsRecord(
count = count,
startTime = startTime,
startZoneOffset = startZoneOffset,
endTime = endTime,
endZoneOffset = endZoneOffset,
metadata = Metadata(
clientRecordId = cid,
clientRecordVersion = version
)
)
Upsert は、データが予期せず上書きされるのを防ぐため、変更が発生しても version
を自動更新しません。そのため、今より大きな値を手動で指定する必要があります。
データ書き込みのベスト プラクティス
アプリは、独自のソースのデータのみをヘルスコネクトに書き込む必要があります。
アプリのデータが別のアプリからインポートされたものである場合、そのデータをヘルスコネクトに書き込む役割はインポート元のアプリが担います。
また、境界外のデータや内部システムエラーなどの書き込み例外を処理するロジックを実装することもおすすめします。バックオフと再試行の戦略は、ジョブ スケジューリング メカニズムに適用できます。ヘルスコネクトへの書き込みが最終的に失敗した場合でも、アプリは必要な処理を引き続き行える状態でなければなりません。診断に役立てるため、必ずエラーをログに記録して報告してください。
データをトラッキングする場合、アプリがデータを書き込む方法に応じて、いくつかの推奨事項があります。
パッシブ トラッキング
これには、受動的なフィットネス管理または健康管理を行うアプリ(たとえば、バックグラウンドで歩数や心拍数を継続的に記録するアプリ)が含まれます。
アプリは以下の方式でヘルスコネクトに定期的にデータを書き込む必要があります。
- 同期のたびに、新規データと更新データのうち、それ以降に変更されたデータのみを書き込みます。 表示されます。
- 1 回の書き込みリクエストのレコード数を最大 1,000 個にしてリクエストをチャンクします。
WorkManager
を使用して、定期的なバックグラウンド タスクを少なくとも 15 分の期間にスケジュール設定します。デバイスがアイドル状態でバッテリー残量が十分にある場合にのみタスクを実行するよう制限します。
val constraints = Constraints.Builder() .requiresBatteryNotLow() .requiresDeviceIdle(true) .build() val writeDataWork = PeriodicWorkRequestBuilder<WriteDataToHealthConnectWorker>( 15, TimeUnit.MINUTES, 5, TimeUnit.MINUTES ) .setConstraints(constraints) .build()
アクティブ トラッキング
これには、エクササイズや睡眠などのイベントベースのトラッキングを行うアプリや、栄養などの手動のユーザー入力を行うアプリが含まれます。これらのレコードは、アプリがフォアグラウンドにある場合、または 1 日に数回使用されるまれなイベントの場合に作成されます。
イベント期間全体を通じて、アプリでヘルスコネクトの実行が維持されないようにします。
データは、次の 2 つの方法のいずれかを使って、ヘルスコネクトに書き込む必要があります。
- イベントの完了後にデータをヘルスコネクトに同期します。たとえば、トラッキング対象のエクササイズ セッションが終了したときにデータを同期します。
WorkManager
を使用して、1 回限りのタスクのデータを後で同期するようにスケジュール設定します。
書き込みの粒度と頻度に関するベスト プラクティス
ヘルスコネクトにデータを書き込むときは、適切な解像度を使用します。 適切な解決策により、ストレージの負荷を軽減しながら、 収集します。データ解決には 2 つのものが含まれます。
- 書き込み頻度: アプリケーションが新しいデータを push する頻度 ヘルスコネクト。たとえば、15 分ごとに新しいデータを書き込みます。
- 書き込まれるデータの粒度: 取り込まれたデータが サンプリングされます。たとえば、5 秒ごとに心拍数のサンプルを書き込むことができます。データ型によっては 同じサンプルレートが必要です。歩数を更新してもメリットはほとんどありません より頻度の低い頻度(60 時間ごとなど)とは対照的に、 秒です。ただし、サンプルレートが高いほど、ユーザーはより詳細で 健康とフィットネスに関するきめ細かいデータを確認できます。サンプルレートの頻度 ディテールとパフォーマンスのバランスを取る必要があります
1 日を通じてモニタリングされるデータを書き込む
ステップなど、継続的に収集されるデータについては、 1 日を通して少なくとも 15 分ごとにヘルスコネクトに書き込む。
データ型 |
単位 |
予定 |
例 |
手順 |
手順 |
1 分ごと |
23:14 ~ 23:15 - 5 ステップ 23:16 ~ 23:17 - 22 ステップ 23:17 ~ 23:18 - 8 ステップ |
歩数のケイデンス |
歩/分 |
1 分ごと |
23:14 ~ 23:15 ~ 5 spm 23:16 ~ 23:17 ~ 22 spm 23:17 ~ 23:18 ~ 8 秒 |
車椅子を押した回数 |
プッシュ |
1 分ごと |
23:14 ~ 23:15 - 5 回 23:16 ~ 23:17 - 22 プッシュ 23:17 ~ 23:18 - 8 回 |
アクティブな消費カロリー |
カロリー |
15分毎 |
23:15 - 23:30 - 2 カロリー 23:30 - 23:45 - 25 カロリー 23:45 - 00:00 - 5 カロリー |
総消費カロリー |
カロリー |
15分毎 |
23:15 - 23:30 - 16 カロリー 23:30 - 23:45 - 16 カロリー 23:45 - 00:00 - 16 カロリー |
距離 |
km/分 |
1 分ごと |
23:14 ~ 23:15 ~ 0.008 km 23:16 ~ 23:16 - 0.021 km 23:17 ~ 23:18 - 0.012 km |
獲得標高 |
m |
1 分ごと |
20:36 ~ 20:37 - 3.048 分 20:39 ~ 20:40 ~ 3.048 分 23:23 ~ 23:24 - 9.144 分 |
上った階数 |
階 |
1 分ごと |
23:14 - 23:15 - 5 階 23:16 - 23:16 - 22 階 23:17 - 23:18 - 8 階 |
心拍数 |
bpm |
1 分ごと |
午前 6:11 - 55 bpm |
心拍変動 Rmssd |
ミリ秒 |
1 分ごと |
午前 6:11 ~ 23 ミリ秒 |
呼吸数 |
呼吸/分 |
1 分ごと |
23:14 - 23:15 - 60 呼吸/分 23:16 - 23:16 - 62 呼吸/分 23:17 - 23:18 - 64 呼吸/分 |
血中酸素ウェルネス |
% |
1 時間ごと |
6:11 ~ 95.208% |
セッションを書き込む
ワークアウトや睡眠の終了時に、データをヘルスコネクトに書き込む必要がある あります。
ベストプラクティスとして、睡眠セッションやエクササイズセッションは、
レコーダー デバイスと適切なメタデータ(
RecordingMethod
。
少なくとも、アプリケーションは「想定される」ご覧ください。説明 「ベスト プラクティス」をガイダンスを提供します。
エクササイズ中に記録されたデータ
データ型 |
単位 |
予定 |
今後ともどうぞよろしくお願いいたします。 |
例 |
手順 |
手順 |
1 分ごと |
1 秒ごと |
23:14 ~ 23:15 - 5 ステップ 23:16 ~ 23:17 - 22 ステップ 23:17 ~ 23:18 - 8 ステップ |
歩数のケイデンス |
歩/分 |
1 分ごと |
1 秒ごと |
23:14 ~ 23:15 ~ 35 秒 23:16 ~ 23:17 ~ 37 spm 23:17 ~ 23:18 ~ 40 spm |
車椅子を押した回数 |
プッシュ |
1 分ごと |
1 秒ごと |
23:14 ~ 23:15 - 5 回 23:16 ~ 23:17 - 22 プッシュ 23:17 ~ 23:18 - 8 回 |
サイクリングペダリングケイデンス |
RPM |
1 分ごと |
1 秒ごと |
23:14 ~ 23:15 ~ 65 rpm 23:16 ~ 23:17 ~ 70 rpm 23:17 ~ 23:18 ~ 68 rpm |
電源 |
ワット |
1 分ごと |
1 秒ごと |
23:14 ~ 23:15 - 250 ワット 23:16 ~ 23:17 - 255 ワット 23:17 ~ 23:18 - 245 ワット |
速度 |
km/分 |
1 分ごと |
1 秒ごと |
23:14 ~ 23:15 - 0.3 km/分 23:16 ~ 23:17 - 0.4 km/分 23:17 ~ 23:18 -0.4 km/分 |
距離 |
km/m |
1 分ごと |
1 秒ごと |
23:14 ~ 23:15 ~ 0.008 km 23:16 ~ 23:16 - 0.021 km 23:17 ~ 23:18 - 0.012 km |
アクティブな消費カロリー |
カロリー |
1 分ごと |
1 秒ごと |
23:14-23:15 - 20 カロリー 23:16 - 23:17 - 20 カロリー 23:17 - 23:18 - 25 カロリー |
総消費カロリー |
カロリー |
1 分ごと |
1 秒ごと |
23:14-23:15 - 36 カロリー 23:16 - 23:17 - 36 カロリー 23:17 - 23:18 - 41 カロリー |
獲得標高 |
m |
1 分ごと |
1 秒ごと |
20:36 ~ 20:37 - 3.048 分 20:39 ~ 20:40 ~ 3.048 分 23:23 ~ 23:24 - 9.144 分 |
ExerciseRoutes |
緯度/経度/Alt |
3 ~ 5 秒ごと |
1 秒ごと |
|
心拍数 |
bpm |
1 分ごと |
1 秒ごと |
23:14 ~ 23:15 ~ 150 bpm 23:16 ~ 23:17 -152 bpm 23:17 ~ 23:18 ~ 155 bpm |
睡眠中に記録されたデータ
データ型 |
単位 |
想定されるサンプル |
例 |
睡眠段階 |
ステージ |
睡眠ステージごとの詳細な期間 |
23:46 ~ 23:50 - 覚醒 23:50 ~ 23:56 - 浅い睡眠 23:56 ~ 00:16 - 深い睡眠 |
安静時の心拍数 |
bpm |
1 日の 1 つの値(朝の最初に想定されるもの) |
午前 6:11 - 60 bpm |
血中酸素ウェルネス |
% |
1 日の 1 つの値(朝の最初に想定されるもの) |
6:11 ~ 95.208% |