Melacak langkah

Health Connect menyediakan jenis data langkah untuk mencatat jumlah langkah menggunakan StepsRecord. Langkah adalah pengukuran mendasar dalam pelacakan kesehatan dan kebugaran.

Membaca langkah seluler

Dengan Android 14 (level API 34) dan Ekstensi SDK versi 20 atau yang lebih tinggi, Health Connect menyediakan penghitungan langkah di perangkat. Jika aplikasi telah diberi izin READ_STEPS, Health Connect akan mulai merekam langkah dari perangkat yang didukung Android, dan pengguna akan melihat data langkah yang otomatis ditambahkan ke entri Langkah Health Connect.

Untuk memeriksa apakah penghitungan langkah di perangkat tersedia, pastikan perangkat menjalankan Android 14 (level API 34) dan memiliki setidaknya ekstensi SDK versi 20:

val isStepTrackingAvailable =
    Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE &&
        SdkExtensions.getExtensionVersion(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) >= 20

Jika aplikasi Anda membaca jumlah langkah gabungan menggunakan aggregate dan tidak memfilter berdasarkan DataOrigin, langkah di perangkat akan otomatis disertakan dalam total, dan tidak ada perubahan yang diperlukan untuk update Juni 2026.

Perubahan atribusi untuk langkah di perangkat

Mulai update Juni 2026, langkah yang dilacak secara native oleh Health Connect akan dikaitkan dengan Nama Paket Sintetis (SPN), seperti com.android.healthconnect.phone.jd5bdd37e1a8d3667a05d0abebfc4a89e.

Sebelumnya, langkah bawaan dikaitkan dengan nama paket android. Data langkah historis yang direkam sebelum Juni 2026 akan mempertahankan nama paket android.

SPN khusus perangkat dan dicakup berdasarkan per aplikasi untuk melindungi privasi pengguna:

  • Stabil: SPN untuk perangkat saat ini stabil untuk aplikasi Anda.
  • Cakupan Aplikasi: Aplikasi yang berbeda di perangkat yang sama akan melihat SPN yang berbeda untuk data langkah di perangkat.

Membuat kueri untuk langkah di perangkat

Karena SPN dicakup dan khusus perangkat, Anda tidak boleh meng-hardcode nilai SPN. Sebagai gantinya, gunakan getCurrentDeviceDataSource() API untuk mengambil SPN untuk perangkat saat ini.

Meskipun penghitungan langkah di perangkat memerlukan ekstensi SDK versi 20 atau yang lebih tinggi, getCurrentDeviceDataSource() API tersedia di Android 14 (level API 34) dengan ekstensi SDK versi 11 atau yang lebih tinggi.

getCurrentDeviceDataSource() API belum tersedia di library Jetpack Health Connect. Contoh berikut menggunakan Android framework API sebagai gantinya:

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

Jika aplikasi Anda perlu membaca langkah di perangkat, atau jika aplikasi menampilkan data langkah yang dipecah berdasarkan aplikasi atau perangkat sumber, Anda harus membuat kueri untuk data yang DataOrigin-nya adalah android atau cocok dengan SPN perangkat. Jika aplikasi Anda menampilkan atribusi untuk data langkah, gunakan metadata.device untuk mengidentifikasi perangkat sumber untuk setiap data. Untuk langkah di perangkat yang diidentifikasi oleh SPN dalam data gabungan, Anda dapat menggunakan metadata perangkat seperti model atau manufacturer dari DeviceDataSource untuk atribusi, atau menggunakan label generik seperti "Ponsel Anda" untuk langkah di perangkat.

Contoh berikut menunjukkan cara membaca data jumlah langkah gabungan di perangkat dengan memfilter android dan SPN perangkat saat ini:

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.
    }
}

Penghitungan Langkah di Perangkat

  • Penggunaan Sensor: Health Connect menggunakan sensor TYPE_STEP_COUNTER dari SensorManager. Sensor ini dioptimalkan untuk konsumsi daya rendah, sehingga ideal untuk pelacakan langkah latar belakang berkelanjutan.
  • Granularitas Data: Untuk menghemat masa pakai baterai, data langkah biasanya dikelompokkan dan ditulis ke database Health Connect tidak lebih sering dari sekali per menit.
  • Atribusi: Langkah yang direkam oleh fitur ini sebelum Juni 2026 dikaitkan dengan nama paket android di DataOrigin. Setelah tanggal ini, langkah tersebut dikaitkan dengan SPN khusus perangkat. Lihat Perubahan atribusi untuk langkah di perangkat.
  • Aktivasi: Mekanisme penghitungan langkah di perangkat hanya aktif jika setidaknya satu aplikasi di perangkat telah diberi izin READ_STEPS dalam Health Connect.

Memeriksa ketersediaan Health Connect

Sebelum mencoba menggunakan Health Connect, aplikasi Anda harus memverifikasi bahwa Health Connect tersedia di perangkat pengguna. Health Connect mungkin tidak diinstal secara default di semua perangkat atau dapat dinonaktifkan. Anda dapat memeriksa ketersediaan menggunakan metode HealthConnectClient.getSdkStatus().

Cara memeriksa ketersediaan Health Connect

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
}

Bergantung pada status yang ditampilkan oleh getSdkStatus(), Anda dapat memandu pengguna untuk menginstal atau mengupdate Health Connect dari Google Play Store jika diperlukan.

Izin yang diperlukan

Akses ke langkah dilindungi oleh izin berikut:

  • android.permission.health.READ_STEPS
  • android.permission.health.WRITE_STEPS

Untuk menambahkan kemampuan langkah ke aplikasi Anda, mulailah dengan meminta izin untuk jenis data Steps.

Berikut adalah izin yang harus Anda deklarasikan agar dapat menulis langkah:

<application>
  <uses-permission
android:name="android.permission.health.WRITE_STEPS" />
...
</application>

Untuk membaca langkah, Anda harus meminta izin berikut:

<application>
  <uses-permission
android:name="android.permission.health.READ_STEPS" />
...
</application>

Meminta izin dari pengguna

Setelah membuat instance klien, aplikasi Anda perlu meminta izin dari pengguna. Pengguna harus diizinkan untuk memberikan atau menolak izin kapan saja. Untuk melakukannya, buat kumpulan izin untuk jenis data yang diperlukan. Pastikan izin dalam kumpulan dideklarasikan dalam manifes Android Anda terlebih dahulu.

val permissions =
    setOf(
        HealthPermission.getReadPermission(StepsRecord::class),
        HealthPermission.getWritePermission(StepsRecord::class)
    )
Gunakan getGrantedPermissions untuk mengetahui apakah aplikasi Anda sudah mendapatkan izin yang diperlukan. Jika belum, gunakan createRequestPermissionResultContract untuk meminta izin tersebut. Tindakan ini akan menampilkan layar izin Health Connect.
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.") }
    }
}
Karena pengguna dapat memberikan atau mencabut izin kapan saja, aplikasi Anda perlu memeriksa izin setiap kali sebelum menggunakannya dan menangani skenario saat izin hilang.

Informasi yang disertakan dalam data Langkah

Setiap StepsRecord berisi informasi berikut:

  • count: Jumlah langkah yang diambil dalam interval waktu, sebagai Long.
  • startTime: Waktu mulai interval pengukuran.
  • endTime: Waktu berakhir interval pengukuran.
  • startZoneOffset: Offset zona untuk waktu mulai.
  • endZoneOffset: Offset zona untuk waktu berakhir.

Agregasi yang didukung

Nilai gabungan berikut tersedia untuk StepsRecord:

Nilai gabungan berikut tersedia untuk StepsCadenceRecord:

Contoh penggunaan

Bagian berikut menunjukkan cara membaca dan menulis data StepsRecord.

Menulis data langkah

Aplikasi Anda dapat menulis data jumlah langkah dengan menyisipkan StepsRecord instance. Contoh berikut menunjukkan cara merekam 1.000 langkah yang diambil oleh pengguna:

val zoneOffset = ZoneOffset.systemDefault().rules.getOffset(startTime)
val stepsRecord = StepsRecord(
    count = 120,
    startTime = startTime,
    endTime = endTime,
    startZoneOffset = zoneOffset,
    endZoneOffset = zoneOffset,
    metadata = Metadata(
        device = Device(type = Device.TYPE_WATCH),
        recordingMethod = Metadata.RECORDING_METHOD_AUTOMATICALLY_RECORDED
    )
)
healthConnectClient.insertRecords(listOf(stepsRecord))

Membaca data gabungan

Cara paling umum untuk membaca data langkah adalah dengan menggabungkan total langkah selama jangka waktu tertentu. Contoh berikut menunjukkan cara membaca total jumlah langkah untuk pengguna dalam rentang waktu tertentu:

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
}

Membaca data mentah

Contoh berikut menunjukkan cara membaca data StepsRecord mentah antara waktu mulai dan berakhir:

val response = healthConnectClient.readRecords(
    ReadRecordsRequest(
        StepsRecord::class,
        timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
    )
)
response.records.forEach { record ->
    /* Process records */
}