ヘルスコネクトは、StepsRecord を使用して歩数を記録するための歩数データ型を提供します。歩数は、健康とフィットネスのトラッキングにおける基本的な測定値です。
モバイルの歩数を読み取る
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 月のアップデートより、ヘルスコネクトでネイティブにトラッキングされた歩数は、com.android.healthconnect.phone.jd5bdd37e1a8d3667a05d0abebfc4a89e などの合成パッケージ名(SPN)に帰属します。
以前は、組み込みステップはパッケージ名 android に関連付けられていました。2026 年 6 月より前に記録された過去の歩数データは、android パッケージ名を保持します。
SPN はデバイス固有であり、ユーザーのプライバシーを保護するためにアプリケーションごとにスコープが設定されます。
- 安定: 現在のデバイスの SPN は、アプリにとって安定しています。
- アプリケーション スコープ: 同じデバイス上の異なるアプリケーションは、デバイス上の歩数データに対して異なる SPN を認識します。
オンデバイスの歩数をクエリする
SPN はスコープ設定され、デバイス固有であるため、SPN 値をハードコードしてはなりません。代わりに、getCurrentDeviceDataSource API を使用して、現在のデバイスの SPN を取得します。
デバイス上の歩数計には SDK 拡張機能バージョン 20 以上が必要ですが、getCurrentDeviceDataSource() API は SDK 拡張機能バージョン 22 以上を搭載した Android 14(API レベル 34)で利用できます。この API を使用するには、モジュール レベルの build.gradle.kts ファイルまたは build.gradle ファイルで compileSdkExtension を 22 以上に設定します。
Kotlin
android { compileSdk = 35 compileSdkExtension = 22 }
Groovy
android { compileSdk 35 compileSdkExtension 22 }
getCurrentDeviceDataSource() API は、ヘルスコネクト Jetpack ライブラリではまだ利用できません。次の例では、Executor と OutcomeReceiver コールバックを必要とする Android フレームワーク API を使用しています。
import android.content.Context
import android.health.connect.DeviceDataSource
import android.health.connect.HealthConnectException
import android.health.connect.HealthConnectManager
import android.os.OutcomeReceiver
val healthConnectManager = context.getSystemService(HealthConnectManager::class.java)
healthConnectManager?.getCurrentDeviceDataSource(
context.mainExecutor,
object : OutcomeReceiver<DeviceDataSource, HealthConnectException> {
override fun onResult(result: DeviceDataSource) {
val currentDeviceSpn = result.deviceDataOrigin.packageName
}
override fun onError(error: HealthConnectException) {
// Handle error
}
}
)
アプリでデバイス上の歩数を読み取る必要がある場合や、ソースアプリまたはデバイスごとに歩数データを表示する場合は、DataOrigin が android または デバイスの SPN と一致するレコードをクエリする必要があります。アプリで歩数データの帰属を表示する場合は、metadata.device を使用して個々のレコードのソースデバイスを特定します。集計データ内の SPN で識別されるオンデバイスの手順については、アトリビューションに DeviceDataSource の model や manufacturer などのデバイス メタデータを使用するか、オンデバイスの手順に「スマートフォン」などの一般的なラベルを使用できます。
次の例は、android と現在のデバイス SPN の両方でフィルタリングして、デバイス上の集計された歩数データを読み取る方法を示しています。
import android.content.Context
import android.health.connect.DeviceDataSource
import android.health.connect.HealthConnectException
import android.health.connect.HealthConnectManager
import android.os.Build
import android.os.OutcomeReceiver
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
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlinx.coroutines.suspendCancellableCoroutine
suspend fun readDeviceStepsByTimeRange(
healthConnectClient: HealthConnectClient,
context: Context,
startTime: Instant,
endTime: Instant
) {
// 1. Check if SDK Extension 22+ is available for getCurrentDeviceDataSource()
val isDataSourceApiAvailable =
Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE &&
SdkExtensions.getExtensionVersion(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) >= 22
try {
val healthConnectManager = context.getSystemService(HealthConnectManager::class.java)
// 2. Safely fetch the package name only if the API is available
val currentDeviceSpn = if (isDataSourceApiAvailable && healthConnectManager != null) {
suspendCancellableCoroutine { continuation ->
healthConnectManager.getCurrentDeviceDataSource(
context.mainExecutor,
object : OutcomeReceiver<DeviceDataSource, HealthConnectException> {
override fun onResult(result: DeviceDataSource) {
continuation.resume(result.deviceDataOrigin.packageName)
}
override fun onError(error: HealthConnectException) {
continuation.resumeWithException(error)
}
}
)
}
} 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.
}
}
オンデバイスの歩数計
- センサーの使用状況: ヘルスコネクトは
SensorManagerのTYPE_STEP_COUNTERセンサーを使用します。このセンサーは消費電力を抑えるように最適化されているため、バックグラウンドでの継続的な歩数トラッキングに最適です。 - データの粒度: バッテリーを節約するため、歩数データは通常、バッチ処理され、1 分に 1 回以下の頻度でヘルスコネクト データベースに書き込まれます。
- アトリビューション: 2026 年 6 月より前にこの機能で記録されたステップは、
DataOriginのandroidパッケージ名に帰属します。この日以降は、デバイス固有の SPN に関連付けられます。オンデバイスの手順のアトリビューションの変更を参照してください。 - 有効化: デバイス上の歩数カウント メカニズムは、デバイス上の少なくとも 1 つのアプリにヘルスコネクト内で
READ_STEPS権限が付与されている場合にのみ有効になります。
ヘルスコネクトを利用できるか確認する
ヘルスコネクト アプリを使用する前に、ユーザーのデバイスでヘルスコネクトが利用可能であることを確認する必要があります。ヘルスコネクトは一部のデバイスにおいて、プリインストールされていない場合や、無効になっている場合があります。HealthConnectClient.getSdkStatus() メソッドを使用して、利用可能かどうかを確認できます。
ヘルスコネクトを利用できるか確認する方法
fun checkHealthConnectAvailability(context: Context) { val providerPackageName = "com.google.android.apps.healthdata" // Or get from HealthConnectClient.DEFAULT_PROVIDER_PACKAGE_NAME val availabilityStatus = HealthConnectClient.getSdkStatus(context, providerPackageName) if (availabilityStatus == HealthConnectClient.SDK_UNAVAILABLE) { // Health Connect is not available. Guide the user to install/enable it. // For example, show a dialog. return // early return as there is no viable integration } if (availabilityStatus == HealthConnectClient.SDK_UNAVAILABLE_PROVIDER_UPDATE_REQUIRED) { // Health Connect is available but requires an update. // Optionally redirect to package installer to find a provider, for example: val uriString = "market://details?id=$providerPackageName&url=healthconnect%3A%2F%2Fonboarding" context.startActivity( Intent(Intent.ACTION_VIEW).apply { setPackage("com.android.vending") data = Uri.parse(uriString) putExtra("overlay", true) putExtra("callerId", context.packageName) } ) return } // Health Connect is available, obtain a HealthConnectClient instance val healthConnectClient = HealthConnectClient.getOrCreate(context) // Issue operations with healthConnectClient }
getSdkStatus() から返されたステータスに応じて、必要に応じて Google Play ストアからヘルスコネクトをインストールまたは更新するようユーザーに案内できます。
必要な権限
歩数へのアクセスは、次の権限によって保護されています。
android.permission.health.READ_STEPSandroid.permission.health.WRITE_STEPS
歩数機能をアプリに追加するには、まず、Steps データ型の権限をリクエストします。
歩数を書き込むために宣言する必要がある権限は次のとおりです。
<application>
<uses-permission
android:name="android.permission.health.WRITE_STEPS" />
...
</application>
歩数を読み取るには、次の権限をリクエストする必要があります。
<application>
<uses-permission
android:name="android.permission.health.READ_STEPS" />
...
</application>
ユーザーに権限をリクエストする
クライアント インスタンスを作成した後、アプリはユーザーに権限をリクエストする必要があります。ユーザーがいつでも権限を付与または拒否できるようにする必要があります。そのためには、必要なデータ型の権限セットを作成します。まず、セット内の権限が Android マニフェストで宣言されていることを確認します。
val permissions = setOf( HealthPermission.getReadPermission(StepsRecord::class), HealthPermission.getWritePermission(StepsRecord::class) )
getGrantedPermissions を使用して、アプリに必要な権限がすでに付与されているかどうかを確認します。持っていない場合は、createRequestPermissionResultContract を使用して権限をリクエストします。ヘルスコネクトの権限画面が表示されます。
val permissions = setOf( HealthPermission.getReadPermission(StepsRecord::class), HealthPermission.getWritePermission(StepsRecord::class), HealthPermission.getReadPermission(HeartRateRecord::class), HealthPermission.getWritePermission(HeartRateRecord::class) ) val requestPermissionsLauncher = rememberLauncherForActivityResult( contract = PermissionController.createRequestPermissionResultContract() ) { grantedPermissions -> if (grantedPermissions.containsAll(permissions)) { coroutineScope.launch { snackbarHostState.showSnackbar("Permissions granted!") } } else { coroutineScope.launch { snackbarHostState.showSnackbar("Permissions denied.") } } }
Steps レコードに含まれる情報
各 StepsRecord には次の情報が含まれています。
count: 時間間隔内の歩数(Long)。startTime: 測定間隔の開始時刻。endTime: 測定間隔の終了時刻。startZoneOffset: 開始時間のゾーン オフセット。endZoneOffset: 終了時間のゾーン オフセット。
サポートされている集計
StepsRecord で使用できる集計値は次のとおりです。
StepsCadenceRecord で使用できる集計値は次のとおりです。
使用例
以降のセクションでは、StepsRecord データの読み取りと書き込みの方法について説明します。
歩数のデータを書き込む
アプリは、StepsRecord インスタンスを挿入することで歩数データを書き込むことができます。次の例は、ユーザーが歩いた 1,000 歩を記録する方法を示しています。
val zoneOffset = ZoneOffset.systemDefault().rules.getOffset(startTime) val stepsRecord = StepsRecord( count = 120, startTime = startTime, endTime = endTime, startZoneOffset = zoneOffset, endZoneOffset = zoneOffset, metadata = Metadata.autoRecorded( device = Device(type = Device.TYPE_WATCH) ) ) healthConnectClient.insertRecords(listOf(stepsRecord))
集計データを読み取る
歩数データを読み取る最も一般的な方法は、一定期間の合計歩数を集計することです。次の例は、特定の期間内のユーザーの総歩数を読み取る方法を示しています。
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 }
元データを読み取る
次の例は、開始時刻と終了時刻の間の未加工の StepsRecord データを読み取る方法を示しています。
val response = healthConnectClient.readRecords( ReadRecordsRequest( StepsRecord::class, timeRangeFilter = TimeRangeFilter.between(startTime, endTime) ) ) response.records.forEach { record -> /* Process records */ }