Suivre vos pas

Santé Connect fournit un type de données Pas pour enregistrer le nombre de pas à l'aide de StepsRecord. Les pas sont une mesure fondamentale pour le suivi de la santé et de la forme physique.

Lire les pas sur mobile

Avec Android 14 (niveau d'API 34) et la version 20 ou ultérieure de SDK Extension, Santé Connect fournit un compteur de pas sur l'appareil. Si une application a reçu l'autorisation READ_STEPS, Santé Connect commence à enregistrer les pas effectués sur l'appareil Android. Les utilisateurs voient alors les données de pas ajoutées automatiquement aux entrées Pas de Santé Connect.

Pour vérifier si le comptage de pas sur l'appareil est disponible, assurez-vous que l'appareil exécute Android 14 (niveau d'API 34) et dispose au moins de la version 20 de l'extension SDK :

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

Si votre application lit le nombre de pas agrégé à l'aide de aggregate et ne filtre pas par DataOrigin, les pas enregistrés sur l'appareil sont automatiquement inclus dans le total. Aucune modification n'est requise pour la mise à jour de juin 2026.

Modification de l'attribution pour les pas effectués sur l'appareil

À partir de la mise à jour de juin 2026, les pas suivis de manière native par Santé Connect sont attribués à un nom de package synthétique (SPN), tel que com.android.healthconnect.phone.jd5bdd37e1a8d3667a05d0abebfc4a89e.

Auparavant, les étapes intégrées étaient attribuées au nom de package android. Les données historiques sur les pas enregistrées avant juin 2026 conservent le nom du package android.

Les SPN sont spécifiques à l'appareil et sont limités à chaque application pour protéger la confidentialité des utilisateurs :

  • Stable : le SPN de l'appareil actuel est stable pour votre application.
  • Portée de l'application : différentes applications sur le même appareil voient différents SPN pour les données de pas sur l'appareil.

Requête pour les étapes sur l'appareil

Étant donné que les SPN sont spécifiques à un appareil et à une portée limitée, vous ne devez pas coder en dur les valeurs SPN. Utilisez plutôt l'API getCurrentDeviceDataSource pour récupérer le SPN de l'appareil actuel.

Bien que le comptage de pas sur l'appareil nécessite la version 20 ou ultérieure de SDK Extension, l'API getCurrentDeviceDataSource() est disponible sur Android 14 (niveau d'API 34) avec la version 22 ou ultérieure de SDK Extension. Pour utiliser cette API, définissez compileSdkExtension sur 22 ou une version ultérieure dans le fichier build.gradle.kts ou build.gradle au niveau du module :

Kotlin

android {
    compileSdk = 35
    compileSdkExtension = 22
}

Groovy

android {
    compileSdk 35
    compileSdkExtension 22
}

L'API getCurrentDeviceDataSource() n'est pas encore disponible dans la bibliothèque Jetpack Santé Connect. Les exemples suivants utilisent l'API du framework Android, qui nécessite un rappel Executor et un rappel 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
        }
    }
)

Si votre application doit lire les pas enregistrés sur l'appareil ou afficher des données de pas ventilées par application ou appareil source, vous devez interroger les enregistrements dont le DataOrigin est android ou correspond au SPN de l'appareil. Si votre application affiche l'attribution des données de pas, utilisez metadata.device pour identifier l'appareil source des enregistrements individuels. Pour les étapes sur l'appareil identifiées par un SPN dans les données globales, vous pouvez utiliser des métadonnées d'appareil telles que model ou manufacturer à partir de DeviceDataSource pour l'attribution, ou utiliser un libellé générique tel que "Votre téléphone" pour les étapes sur l'appareil.

L'exemple suivant montre comment lire les données agrégées sur le nombre de pas sur l'appareil en filtrant à la fois android et le SPN de l'appareil actuel :

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

Comptage des pas sur l'appareil

  • Utilisation des capteurs : Santé Connect utilise le capteur TYPE_STEP_COUNTER de SensorManager. Ce capteur est optimisé pour une faible consommation d'énergie, ce qui le rend idéal pour le suivi continu des pas en arrière-plan.
  • Granularité des données : pour préserver l'autonomie de la batterie, les données sur les pas sont généralement regroupées et écrites dans la base de données Santé Connect au maximum une fois par minute.
  • Attribution : les pas enregistrés par cette fonctionnalité avant juin 2026 sont attribués au nom de package android dans DataOrigin. Après cette date, ils sont attribués à un SPN spécifique à l'appareil. Consultez Modification de l'attribution pour les étapes sur l'appareil.
  • Activation : le mécanisme de comptage des pas sur l'appareil n'est actif que lorsqu'au moins une application sur l'appareil a reçu l'autorisation READ_STEPS dans Santé Connect.

Vérifier la disponibilité de Santé Connect

Avant de tenter d'utiliser Santé Connect, votre application doit vérifier que Santé Connect est disponible sur l'appareil de l'utilisateur. Il est possible que Health Connect ne soit pas préinstallé sur tous les appareils ou qu'il soit désactivé. Vous pouvez vérifier la disponibilité à l'aide de la méthode HealthConnectClient.getSdkStatus().

Vérifier la disponibilité de Santé 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
}

En fonction de l'état renvoyé par getSdkStatus(), vous pouvez inviter l'utilisateur à installer ou à mettre à jour Santé Connect depuis le Google Play Store si nécessaire.

Autorisations requises

L'accès aux pas est protégé par les autorisations suivantes :

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

Pour ajouter la fonctionnalité de suivi des pas à votre application, commencez par demander des autorisations pour le type de données Steps.

Voici l'autorisation que vous devez déclarer pour pouvoir écrire des étapes :

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

Pour lire les pas, vous devez demander les autorisations suivantes :

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

Demander les autorisations à l'utilisateur

Après avoir créé une instance de client, votre application doit demander des autorisations à l'utilisateur. Les utilisateurs doivent être autorisés à accorder ou à refuser des autorisations à tout moment. Pour ce faire, créez un ensemble d'autorisations pour les types de données requis. Assurez-vous d'abord que les autorisations de l'ensemble sont déclarées dans votre fichier manifeste Android.

val permissions =
    setOf(
        HealthPermission.getReadPermission(StepsRecord::class),
        HealthPermission.getWritePermission(StepsRecord::class)
    )
Utilisez getGrantedPermissions pour voir si votre application dispose déjà des autorisations requises accordées. Si ce n'est pas le cas, utilisez createRequestPermissionResultContract pour demander ces autorisations. L'écran des autorisations de Santé Connect s'affiche.
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.") }
    }
}
Étant donné que les utilisateurs peuvent accorder ou révoquer des autorisations à tout moment, votre application doit vérifier les autorisations à chaque fois avant de les utiliser et gérer les scénarios dans lesquels une autorisation est perdue.

Informations incluses dans un enregistrement "Pas"

Chaque StepsRecord contient les informations suivantes :

  • count : nombre de pas effectués dans l'intervalle de temps, sous la forme d'un Long.
  • startTime : heure de début de l'intervalle de mesure.
  • endTime : heure de fin de l'intervalle de mesure.
  • startZoneOffset : décalage de fuseau horaire pour l'heure de début.
  • endZoneOffset : décalage de fuseau horaire pour l'heure de fin.

Agrégations acceptées

Les valeurs agrégées suivantes sont disponibles pour StepsRecord :

Les valeurs agrégées suivantes sont disponibles pour StepsCadenceRecord :

Exemple d'utilisation

Les sections suivantes expliquent comment lire et écrire des données StepsRecord.

Écrire des données de pas

Votre application peut écrire des données sur le nombre de pas en insérant des instances StepsRecord. L'exemple suivant montre comment enregistrer 1 000 pas effectués par un utilisateur :

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))

Lire les données agrégées

La méthode la plus courante pour lire les données de pas consiste à agréger le nombre total de pas sur une période donnée. L'exemple suivant montre comment lire le nombre total de pas d'un utilisateur au cours d'une certaine période :

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
}

Lire des données brutes

L'exemple suivant montre comment lire les données StepsRecord brutes entre une heure de début et une heure de fin :

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