データを同期する

ヘルスコネクトと統合されるアプリのほとんどには、信頼できる情報源として機能する独自のデータストアがあります。ヘルスコネクトは、アプリを同期させる方法を提供します。

アプリに対する要件には次のようなものがあります。

  • 新規データまたは更新データをアプリのデータストアからヘルスコネクトにフィードする。
  • ヘルスコネクトからデータ変更を取得し、アプリのデータストアに反映する。
  • アプリのデータストアでデータが削除された場合、ヘルスコネクトからデータを削除する。

いずれの場合も、同期プロセスではヘルスコネクトとアプリのデータストアの整合性が保たれている必要があります。

ヘルスコネクトにデータをフィードする

同期プロセスの最初の手順は、アプリのデータストアからヘルスコネクト データストアにデータをフィードすることです。

データを準備する

通常、アプリのデータストア内のレコードには、次の詳細情報が含まれます。

  • 一意のキー(UUID など)。
  • バージョンまたはタイムスタンプ。

ヘルスコネクトにフィードされたデータを追跡するようにアプリのデータストアを設計します。これを実現するには、次のロジックを適用します。

  • 変更のリストと、最後のトークンの発行以降に更新があったレコードの取得に使用できるトークンを指定します。
  • エクスポートされたデータが最後に変更された日時を追跡します。

この手順は、新規データまたは更新データのみがヘルスコネクトにフィードされるようにするために不可欠です。

ヘルスコネクトへのデータの書き込み

ヘルスコネクトにデータをフィードする手順は次のとおりです。

  1. アプリのデータストアから新規エントリまたは更新エントリのリストを取得します。
  2. エントリごとに、そのデータ型に適した Record オブジェクトを作成します。たとえば、体重に関するデータには WeightRecord オブジェクトを作成します。
  3. アプリのデータストアから取得できる一意のキーとバージョンの詳細を使用して、Record ごとに Metadata オブジェクトを指定します。データがバージョニングされていない場合は、代わりに現在のタイムスタンプの Long 値を使用できます。

    val record = WeightRecord(
        metadata = Metadata(
            clientRecordId = "<Your record's Client ID>",
            clientRecordVersion = <Your record's version>
        ),
        weight = weight,
        time = time,
        zoneOffset = zoneOffset
    )
    
  4. insertRecords を使用して、ヘルスコネクトにデータを upsert します。データを upsert すると、clientRecordId 値がヘルスコネクト データストアに存在し、clientRecordVersion が既存の値より大きい場合、ヘルスコネクトの既存のデータが上書きされます。それ以外の場合、upsert されたデータは新しいデータとして書き込まれます。

    healthConnectClient.insertRecords(arrayListOf(record))
    

データのフィードについての実践的な考慮事項については、データの書き込みのベスト プラクティスをご覧ください。

ヘルスコネクト ID を保存する

ヘルスコネクトにレコードを upsert した後、アプリのデータストアでレコードごとにヘルスコネクト id を保存する必要があります。これにより、データを取得した後、受信する各変更で新しいレコードを作成すべきか、あるいは既存のレコードを更新すべきなのかを確認できます。

insertRecords 関数は、id 値のリストを含む InsertRecordsResponse を返します。レスポンスを使用してレコード ID を取得し、保存します。

val response = healthConnectClient.insertRecords(arrayListOf(record))

for (recordId in response.recordIdsList) {
    // Store recordId to your app's datastore
}

ヘルスコネクトからデータを取得する

同期プロセスの手順の 2 番目では、ヘルスコネクトからアプリのデータストアへのデータ変更を取得します。データ変更には、更新と削除が含まれます。

変更トークンを取得する

ヘルスコネクトから取得する変更のリストを取得するには、アプリで変更トークンを追跡する必要があります。これらは、変更をリクエストして、データ変更のリストと、次回使用される変更トークンの両方を返すときに使用できます。

変更トークンを取得するには、getChangesToken を呼び出して、必要なデータ型を指定します。

val changesToken = healthConnectClient.getChangesToken(
    ChangesTokenRequest(recordTypes = setOf(WeightRecord::class))
)

データ変更の確認

変更トークンを取得すると、そのトークンを使用してすべての変更を取得できます。すべての変更を取得するループを作成し、利用可能なデータ変更があるかどうかを確認することをおすすめします。手順は次のとおりです。

  1. トークンを使用して getChanges を呼び出し、変更のリストを取得します。
  2. 変更の種類が UpsertionChangeDeletionChange かを確認し、必要な操作を行います。
    • UpsertionChange では、データを再インポートしないように、呼び出し元アプリからのものではない変更のみを適用します。
  3. 次の変更トークンを新しいトークンとして割り当てます。
  4. 変更がなくなるまで、手順 1~3 を繰り返します。
  5. 次のトークンを保存し、将来のインポート用に予約します。
suspend fun processChanges(token: String): String {
    var nextChangesToken = token
    do {
        val response = healthConnectClient.getChanges(nextChangesToken)
        response.changes.forEach { change ->
            when (change) {
                is UpsertionChange ->
                    if (change.record.metadata.dataOrigin.packageName != context.packageName) {
                        processUpsertionChange(change)
                    }
                is DeletionChange -> processDeletionChange(change)
            }
        }
        nextChangesToken = response.nextChangesToken
    } while (response.hasMore)
    // Return and store the changes token for use next time.
    return nextChangesToken
}

データを取得するための実践的な考慮事項については、データの同期に関するベスト プラクティスをご覧ください。

データ変更を処理する

アプリのデータストアへの変更を反映します。UpsertionChange については、metadataidlastModifiedTime を使用してレコードを upsert します。DeletionChange については、提供される id を使用してレコードを削除します。

ヘルスコネクトからデータを削除する

ユーザーがアプリから自分のデータを削除するときは、ヘルスコネクトからもそのデータが削除されるようにしてください。そのために、deleteRecords を使用します。レコードタイプと id 値と clientRecordId 値のリストを取得するため、複数のデータを一括で削除するのに便利です。timeRangeFilter を受け取る別の deleteRecords も使用できます。

データの同期に関するベスト プラクティス

同期プロセスに影響する要因には、次のものがあります。

トークンの有効期限

未使用の変更トークンは 30 日以内に期限切れになるため、そのような場合に情報が失われることのない同期戦略を採用する必要があります。同期戦略には次のようなアプローチがあります。

  • アプリのデータストアで、ヘルスコネクトの id が付与されている、最近使用されたレコードを検索します。
  • 特定のタイムスタンプで始まるレコードをヘルスコネクトにリクエストし、アプリのデータストアで挿入または更新します。
  • 変更トークンをリクエストし、次回必要なときに使用できるように確保します。

推奨されるチェンジ マネジメント戦略

アプリが無効になった場合や変更トークンが期限切れになった場合に備えて、ロジックへの適用方法に応じて次のマネジメント戦略をおすすめします。

  • すべてのデータを読み取って重複を排除する。これが最も理想的な戦略です。
    • 最後にヘルスコネクトからデータを読み込んだときのタイムスタンプを保存します。
    • トークンの有効期限が切れたときに、最新のタイムスタンプまたは過去 30 日間のすべてのデータを再読み取りする。次に、識別子を使用して、以前に読み取ったデータとの重複を排除する。
    • データの更新にはクライアント ID が必要なため、できる限りクライアント ID を実装する。
  • 前回の読み取りのタイムスタンプ以降のデータのみを読み取る。その結果、変更トークンの有効期限が切れるタイミングでデータの不一致が発生するものの、その期間は数時間から数日の短い期間になります。
    • 最後にヘルスコネクトからデータを読み込んだときのタイムスタンプを保存します。
    • トークンの期限が切れたときに、このタイムスタンプ以降のすべてのデータを読み取ります。
  • データを削除して、過去 30 日間のデータを読み取る。これは最初の統合で行われることと非常に似ています。
    • 過去 30 日間にヘルスコネクトからアプリが読み取ったデータをすべて削除します。
    • 削除後にこのデータをすべて再度読み取ります。
  • 重複を排除することなく過去 30 日間のデータを読み取る。これは最もおすすめしない方法で、ユーザーに重複するデータが表示されることになります。
    • 過去 30 日間にヘルスコネクトからアプリが読み取ったデータをすべて削除します。
    • 重複しているエントリを許可します。

データ型の変更トークン

アプリが複数のデータ型を個別に使用する場合は、データ型ごとに個別の変更トークンを使用します。Changes Sync API で複数のデータ型のリストを使用できるのは、それらのデータ型が一緒に使用される場合、またはいずれも使用されない場合のみです。

フォアグラウンドでの読み取り

アプリがフォアグラウンドにある間のみ、ヘルスコネクトからデータを読み取れます。ヘルスコネクトからデータを同期するときに、ヘルスコネクトへのアクセスが予期せず中断される場合があります。たとえば、ヘルスコネクトから大量のデータを読み取るときの同期途中の中断に対応し、次回アプリが開かれたときに続行する必要があります。

インポートのタイミング

アプリは新規データについて通知されないため、次の 2 つのタイミングで新規データがあるかどうかを確認する必要があります。

  • アプリがフォアグラウンドでアクティブになったときに確認します。この場合は、ライフサイクル イベントを使用します。
  • アプリがフォアグラウンドにある間は定期的に確認します。新しいデータが利用可能になったらユーザーに通知して、画面を更新して変更を反映できるようにします。