ヘルスコネクトには、StepsRecord を使用して歩数を記録するための歩数データタイプが用意されています。歩数は、健康管理とフィットネスのトラッキングにおける基本的な測定値です。
このガイドは、ヘルスコネクトのバージョン 1.1.0-alpha12 以降に対応しています。
モバイルの歩数を読み取る
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 は Android 14(API レベル 34)で SDK 拡張機能バージョン 22 以降で使用できます。この API を使用するには、モジュール レベルの build.gradle.kts ファイルまたは build.gradle ファイルで compileSdkExtension を 22 以上に設定します。
Kotlin
android { compileSdk = 35 compileSdkExtension = 22 }
Groovy
android { compileSdk 35 compileSdkExtension 22 }
getCurrentDeviceDataSource() API は、ヘルスコネクト Jetpack ライブラリではまだ利用できません。次の例では、Android フレームワーク API を使用しています。この API には Executor コールバックと OutcomeReceiver コールバックが必要です。
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" 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.") } } }
歩数レコードに含まれる情報
各 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 */ }