次の例は、一般的なワークフローの一環として元データを読み取る方法を示しています。
データを読み取る
ヘルスコネクトを使用すると、アプリがフォアグラウンドとバックグラウンドにあるときに、アプリがデータストアからデータを読み取ることができます。
フォアグラウンドの読み取り: 通常、 アプリがフォアグラウンドにあるときにヘルスコネクトからデータを読み取ることができます。このような場合、読み取りオペレーション中にユーザーまたはシステムによってアプリがバックグラウンドに配置された場合に、フォアグラウンド サービスを使用してこのオペレーションを実行することを検討してください。
バックグラウンドの読み取り: ユーザーに追加の権限をリクエストすることで、ユーザーまたはシステムによってアプリがバックグラウンドに配置された後にデータを読み取ることができます。バックグラウンドでの読み取りの完全な例をご覧ください。
ヘルスコネクトのデータの種類「歩数」では、各読み取りの間にユーザーが歩いた歩数が記録されます。歩数は、健康、フィットネス、ウェルネスのプラットフォームで共通の測定値を表します。ヘルスコネクトでは、歩数データの読み取りと書き込みができます。
レコードを読み取るには、ReadRecordsRequest を作成し、
を readRecords の呼び出し時に指定します。
次の例は、特定期間内のユーザーの歩数データを読み取る方法を示しています。SensorManager を使用した拡張例については、歩数データのガイドをご覧ください。
val response = healthConnectClient.readRecords( ReadRecordsRequest( HeartRateRecord::class, timeRangeFilter = TimeRangeFilter.between(startTime, endTime) ) ) response.records.forEach { record -> /* Process records */ }
また、
aggregateを使用して、データを集計して読み取ることもできます。
suspend fun readStepsAggregate(startTime: Instant, endTime: Instant): Long { val response = healthConnectClient.aggregate( AggregateRequest( metrics = setOf(StepsRecord.COUNT_TOTAL), timeRangeFilter = TimeRangeFilter.between(startTime, endTime) ) ) return response[StepsRecord.COUNT_TOTAL] ?: 0L }
モバイルの歩数を読み取る
Android 14(API レベル 34)と SDK 拡張機能バージョン 20 以降では、ヘルスコネクトでオンデバイスの歩数カウントが提供されます。アプリに READ_STEPS 権限が付与されている場合、ヘルスコネクトは Android 搭載デバイスから歩数のキャプチャを開始し、ユーザーにはヘルスコネクトの [歩数] エントリに歩数データが自動的に追加されます。
オンデバイスの歩数カウントが利用可能かどうかを確認するには、デバイスが Android 14(API レベル 34)を実行しており、SDK 拡張機能バージョン 20 以降が搭載されていることを確認します。
val isStepTrackingAvailable =
Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE &&
SdkExtensions.getExtensionVersion(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) >= 20
アプリが
aggregateを使用して集計された歩数を読み取り、DataOriginでフィルタリングしない場合、オンデバイスの
歩数は合計に自動的に含まれるため、
2026 年 6 月のアップデートで変更する必要はありません。
オンデバイスの歩数のアトリビューションの変更
2026 年 6 月のアップデート以降、ヘルスコネクトでネイティブにトラッキングされた歩数は、合成パッケージ名(SPN) に帰属します。com.android.healthconnect.phone.jd5bdd37e1a8d3667a05d0abebfc4a89e
以前は、組み込みの歩数はパッケージ名 android に帰属していました。
2026 年 6 月より前に記録された過去の歩数データは、android パッケージ名を保持します。
SPN はデバイス固有であり、ユーザーのプライバシーを保護するためにアプリごとにスコープが設定されます。
- 安定性: 現在のデバイスの SPN は、アプリに対して安定しています。
- アプリのスコープ: 同じデバイス上のアプリごとに、オンデバイスの歩数データの SPN が異なります。
オンデバイスの歩数のクエリ
SPN はスコープが設定され、デバイス固有であるため、SPN 値をハードコードしないでください 。代わりに、getCurrentDeviceDataSource() API を使用して、現在のデバイスの SPN を取得します。
オンデバイスの歩数カウントには SDK 拡張機能バージョン 20 以降が必要ですが、getCurrentDeviceDataSource() API は SDK 拡張機能バージョン 11 以降を搭載した Android 14(API レベル 34)で利用できます。
getCurrentDeviceDataSource() API は、ヘルスコネクト Jetpack ライブラリではまだ利用できません。次の例では、代わりに Android フレームワーク API を使用しています。
import android.content.Context
import android.health.connect.HealthConnectManager
val healthConnectManager = context.getSystemService(HealthConnectManager::class.java)
val deviceDataSource = healthConnectManager?.getCurrentDeviceDataSource()
val currentDeviceSpn = deviceDataSource?.deviceDataOrigin?.packageName
アプリがオンデバイスの歩数を読み取る必要がある場合、またはソースアプリやデバイスごとに歩数データを表示する場合は、DataOrigin が android または デバイスの SPN と一致するレコードをクエリする必要があります。アプリで歩数データのアトリビューションを表示する場合は、metadata.deviceを使用して個々のレコードのソースデバイスを特定します。集計データ内の SPN で識別されるオンデバイスの歩数については、アトリビューションに DeviceDataSource の model や manufacturer などのデバイス メタデータを使用するか、オンデバイスの歩数に「スマートフォン」などの汎用ラベルを使用できます。
次の例は、android と現在のデバイスの SPN の両方でフィルタリングして、集計されたオンデバイスの歩数データを読み取る方法を示しています。
import android.content.Context
import android.health.connect.HealthConnectManager
import android.os.Build
import android.os.ext.SdkExtensions
import androidx.health.connect.client.HealthConnectClient
import androidx.health.connect.client.records.StepsRecord
import androidx.health.connect.client.records.metadata.DataOrigin
import androidx.health.connect.client.request.AggregateRequest
import androidx.health.connect.client.time.TimeRangeFilter
import java.time.Instant
suspend fun readDeviceStepsByTimeRange(
healthConnectClient: HealthConnectClient,
context: Context,
startTime: Instant,
endTime: Instant
) {
// 1. Check if SDK Extension 11+ is available for getCurrentDeviceDataSource()
val isDataSourceApiAvailable = Build.VERSION.SDK_INT >= Build.VERSION_CODES.U &&
SdkExtensions.getExtensionVersion(Build.VERSION_CODES.U) >= 11
try {
val healthConnectManager = context.getSystemService(HealthConnectManager::class.java)
// 2. Safely fetch the package name only if API is available and data exists
val currentDeviceSpn = if (isDataSourceApiAvailable) {
healthConnectManager?.getCurrentDeviceDataSource()?.deviceDataOrigin?.packageName
} else {
null
}
val dataOriginFilters = mutableSetOf(DataOrigin("android"))
// 3. Explicit null-safety check using .let
currentDeviceSpn?.let {
dataOriginFilters.add(DataOrigin(it))
}
val response = healthConnectClient.aggregate(
AggregateRequest(
metrics = setOf(StepsRecord.COUNT_TOTAL),
timeRangeFilter = TimeRangeFilter.between(startTime, endTime),
dataOriginFilter = dataOriginFilters
)
)
val stepCount = response[StepsRecord.COUNT_TOTAL]
} catch (e: Exception) {
// Now this catch block only handles actual runtime exceptions,
// rather than Errors from missing methods.
}
}
オンデバイスの歩数カウント
- センサーの使用: ヘルスコネクトは、
TYPE_STEP_COUNTERセンサーをSensorManagerから利用します。このセンサーは消費電力を抑えるように最適化されているため、バックグラウンドでの継続的な歩数トラッキングに最適です。 - データの粒度: バッテリーの寿命を維持するため、歩数データは通常、 バッチ処理され、 1 分に 1 回以下の頻度でヘルスコネクト データベースに書き込まれます。
- アトリビューション: 2026 年 6 月より前にこの機能で記録された歩数は、
androidパッケージ名にDataOrigin帰属します。この日付以降は、デバイス固有の SPN に帰属します。オンデバイスの歩数の アトリビューションの変更をご覧ください。 - 有効化: オンデバイスの歩数カウント メカニズムは、デバイス上の少なくとも 1 つのアプリにヘルスコネクト内で
READ_STEPS権限が付与されている場合にのみ有効になります。
バックグラウンドでの読み取りの例
バックグラウンドでデータを読み取るには、マニフェスト ファイルで次の権限を宣言します。
<application>
<uses-permission android:name="android.permission.health.READ_HEALTH_DATA_IN_BACKGROUND" />
...
</application>
次の例は、WorkManager を使用して、特定期間内のユーザーの歩数データをバックグラウンドで読み取る方法を示しています。
class ScheduleWorker(appContext: Context, workerParams: WorkerParameters) : CoroutineWorker(appContext, workerParams) { override suspend fun doWork(): Result { val healthConnectClient = HealthConnectClient.getOrCreate(applicationContext) // Perform background read logic here return Result.success() } }
fun enqueueBackgroundReadWorker(context: Context, healthConnectClient: HealthConnectClient) { if (healthConnectClient .features .getFeatureStatus( HealthConnectFeatures.FEATURE_READ_HEALTH_DATA_IN_BACKGROUND ) == HealthConnectFeatures.FEATURE_STATUS_AVAILABLE ) { val periodicWorkRequest = PeriodicWorkRequestBuilder<ScheduleWorker>(1, TimeUnit.HOURS) .build() WorkManager.getInstance(context).enqueueUniquePeriodicWork( "read_health_connect", ExistingPeriodicWorkPolicy.KEEP, periodicWorkRequest ) } }
ReadRecordsRequest パラメータのデフォルトの pageSize 値は 1,000 です。
1 つの readResponse のレコード数がリクエストの pageSize を超える場合は、pageToken を使用してレスポンスのすべてのページを反復処理し、すべてのレコードを取得する必要があります。
ただし、レート制限に注意してください。
pageToken の読み取りの例
レコードを読み取るには pageToken を使用して、リクエストされた期間の利用可能なデータをすべて取得することをおすすめします。
次の例は、すべてのページトークンが使い果たされるまですべてのレコードを読み取る方法を示しています。
val type = HeartRateRecord::class val endTime = Instant.now() val startTime = endTime.minus(Duration.ofDays(7)) try { var pageToken: String? = null do { val readResponse = healthConnectClient.readRecords( ReadRecordsRequest( recordType = type, timeRangeFilter = TimeRangeFilter.between( startTime, endTime ), pageToken = pageToken ) ) val records = readResponse.records // Do something with records pageToken = readResponse.pageToken } while (pageToken != null) } catch (quotaError: IllegalStateException) { // Backoff }
以前に書き込まれたデータを読み取る
アプリが以前にヘルスコネクトにレコードを書き込んでいた場合は、そのレコードをアプリで読み戻すことができます。これは、ユーザーによるインストール後にヘルスコネクトと再同期する必要があるシナリオに該当します。
読み取りにはいくつかの制限があります。
Android 14 以降の場合
- アプリが自身のデータを読み取る場合、過去のデータの上限はありません。
- アプリが他のデータを読み取る場合、30 日間の上限があります。
Android 13 以前の場合
- アプリがデータを読み取る場合、30 日間の上限があります。
読み取り権限をリクエストすることで、制限を解除できます。
過去のデータを読み取るには、パッケージ名を
DataOrigin オブジェクトとして、dataOriginFilter パラメータで
ReadRecordsRequestを指定する必要があります。
次の例は、心拍数レコードを読み取るときにパッケージ名を指定する方法を示しています。
try { val response = healthConnectClient.readRecords( ReadRecordsRequest( recordType = HeartRateRecord::class, timeRangeFilter = TimeRangeFilter.between(startTime, endTime), dataOriginFilter = setOf(DataOrigin("com.my.package.name")) ) ) for (record in response.records) { // Process each record } } catch (e: Exception) { // Run error handling here }
30 日より前のデータを読み取る
デフォルトでは、すべてのアプリは、最初に権限が付与された日の 30 日前までのデータをヘルスコネクトから読み取ることができます。
デフォルトの制限を超えて読み取り権限を拡張する必要がある場合は、
PERMISSION_READ_HEALTH_DATA_HISTORY をリクエストします。
この権限がない場合、30 日より前のレコードを読み取ろうとするとエラーが発生します。
削除されたアプリの権限履歴
ユーザーがアプリを削除すると、履歴権限を含むすべての権限が取り消されます。ユーザーがアプリを再インストールして権限を再度付与すると、 同じデフォルトの制限が適用され、 アプリは新しく権限が付与された日付から最大 30 日間遡ってヘルスコネクトからデータを読み取ることができます。
たとえば、ユーザーが 2023 年 5 月 10 日にアプリを削除し、2023 年 5 月 15 日にアプリを再インストールして読み取り権限を付与したとします。この場合、アプリはデフォルトで 2023 年 4 月 15 日 以降のデータを読み取ることができます。
例外の処理
ヘルスコネクトは、問題が発生した場合に CRUD 操作について標準的な例外をスローします。すべてのアプリで、これらを適切にキャッチして処理する必要があります。
HealthConnectClient の各メソッドは、スローされる可能性のある例外をリストしますが、一般に次のような処理が必要です。
| 例外 | 説明 | 推奨されるベスト プラクティス |
|---|---|---|
IllegalStateException
| 次のいずれかの状況が発生した場合にスローされます。
| リクエストを処理する前に、入力に関する潜在的な問題に対処します。リクエストで値を直接使用する代わりに、カスタム関数内で変数に値を代入するか、パラメータとして使用することをおすすめします。そうすることで、エラー処理戦略を適用できます。 |
IOException
| ディスクのデータの読み取りと書き込みで問題が発生した場合にスローされます。 | この問題を回避するには、次の方法をお試しください。
|
RemoteException
| SDK が接続されている基となるサービスでエラーが発生したか、サービスとの通信中にエラーが発生した場合にスローされます。 たとえば、アプリが特定の uid を持つレコードを削除しようとした場合に、基となるサービスでチェックして初めてレコードが存在しないことが検出されると、例外がスローされます。 | この問題を回避するには、次の方法をお試しください。
|
SecurityException
| 現在付与されていない権限を必要とするリクエストの場合にスローされます。 | この問題を回避するには、公開したアプリのヘルスコネクトのデータタイプの使用を宣言していることを確認します。また、マニフェスト ファイルとアクティビティでヘルスコネクトの権限を宣言する必要があります。 |