Monitorar passos

A Conexão Saúde oferece um tipo de dados passos para registrar contagens de passos usando o StepsRecord. Os passos são uma medida fundamental no monitoramento de saúde e condicionamento físico.

Ler passos no dispositivo móvel

Com o Android 14 (nível 34 da API) e a extensão do SDK versão 20 ou mais recente, a Conexão Saúde oferece a contagem de passos no dispositivo. Se algum app tiver recebido a permissão READ_STEPS, a Conexão Saúde vai começar a capturar passos do dispositivo Android, e os usuários vão ver os dados de passos adicionados automaticamente às entradas de Passos da Conexão Saúde.

Para verificar se a contagem de passos no dispositivo está disponível, confira se o dispositivo está executando o Android 14 (nível 34 da API) e tem pelo menos a extensão do SDK versão 20:

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

Se o app lê contagens de passos agregadas usando aggregate e não filtra por DataOrigin, os passos no dispositivo são incluídos automaticamente no total, e nenhuma mudança é necessária para a atualização de junho de 2026.

Mudança de atribuição para passos no dispositivo

A partir da atualização de junho de 2026, os passos monitorados nativamente pela Conexão Saúde serão atribuídos a um nome de pacote sintético (SPN), como com.android.healthconnect.phone.jd5bdd37e1a8d3667a05d0abebfc4a89e.

Anteriormente, os passos integrados eram atribuídos ao nome do pacote android. Os dados históricos de passos registrados antes de junho de 2026 mantêm o nome do pacote android.

Os SPNs são específicos do dispositivo e têm escopo por aplicativo para proteger a privacidade do usuário:

  • Estável:o SPN do dispositivo atual é estável para seu aplicativo.
  • Com escopo do aplicativo:aplicativos diferentes no mesmo dispositivo mostram SPNs diferentes para dados de passos no dispositivo.

Consultar passos no dispositivo

Como os SPNs têm escopo e são específicos do dispositivo, não codifique valores de SPN. Em vez disso, use a API getCurrentDeviceDataSource() para recuperar o SPN do dispositivo atual.

Embora a contagem de passos no dispositivo exija a extensão do SDK versão 20 ou mais recente, a API getCurrentDeviceDataSource() está disponível no Android 14 (nível 34 da API) com a extensão do SDK versão 11 ou mais recente.

A API getCurrentDeviceDataSource() ainda não está disponível na biblioteca do Jetpack da Conexão Saúde. Os exemplos a seguir usam a API do framework do Android:

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

Se o app precisar ler passos no dispositivo ou mostrar dados de passos detalhados por aplicativo ou dispositivo de origem, consulte os registros em que o DataOrigin é android ou corresponde ao SPN do dispositivo. Se o app mostrar a atribuição de dados de passos, use metadata.device para identificar o dispositivo de origem de registros individuais. Para passos no dispositivo identificados por um SPN em dados agregados, você pode usar metadados do dispositivo, como model ou manufacturer de DeviceDataSource para atribuição, ou usar um rótulo genérico como "Seu smartphone" para passos no dispositivo.

O exemplo a seguir mostra como ler dados agregados de contagem de passos no dispositivo filtrando por android e pelo SPN do dispositivo atual:

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

Contagem de passos no dispositivo

  • Uso do sensor: a Conexão Saúde usa o sensor TYPE_STEP_COUNTER de SensorManager. Esse sensor é otimizado para baixo consumo de energia, o que o torna ideal para o monitoramento contínuo de passos em segundo plano.
  • Granularidade dos dados: para conservar a duração da bateria, os dados de passos são normalmente agrupados e gravados no banco de dados da Conexão Saúde com uma frequência máxima de uma vez por minuto.
  • Atribuição: os passos registrados por esse recurso antes de junho de 2026 são atribuídos ao nome do pacote android no DataOrigin. Após essa data, eles são atribuídos a um SPN específico do dispositivo. Consulte Mudança de atribuição para passos no dispositivo.
  • Ativação: o mecanismo de contagem de passos no dispositivo só fica ativo quando pelo menos um aplicativo no dispositivo recebe a READ_STEPS permissão na Conexão Saúde.

Verificar a disponibilidade da Conexão Saúde

Antes de tentar usar a Conexão Saúde, o app precisa verificar se ela está disponível no dispositivo do usuário. A Conexão Saúde pode não estar pré-instalada em todos os dispositivos ou pode estar desativada. Você pode verificar a disponibilidade usando o método HealthConnectClient.getSdkStatus().

Como verificar a disponibilidade da Conexão Saúde

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
}

Dependendo do status retornado por getSdkStatus(), você pode orientar o usuário a instalar ou atualizar a Conexão Saúde na Google Play Store, se necessário.

Permissões necessárias

O acesso aos passos é protegido pelas seguintes permissões:

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

Para adicionar a capability de passos ao app, comece solicitando permissões para o tipo de dados Steps.

Confira a permissão necessária para poder gravar passos:

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

Para ler passos, é necessário solicitar as seguintes permissões:

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

Solicitar permissões do usuário

Depois de criar uma instância de cliente, seu app precisa solicitar permissões aos usuários. Eles precisam concedê-las ou negá-las a qualquer momento. Os usuários precisam ter permissão para conceder ou negar permissões a qualquer momento.

Para fazer isso, crie um conjunto de permissões para os tipos de dados necessários. Verifique se as permissões no conjunto foram declaradas no manifesto do Android.

// Create a set of permissions for required data types
val PERMISSIONS =
    setOf(
  HealthPermission.getReadPermission(StepsRecord::class),
  HealthPermission.getWritePermission(StepsRecord::class)
)

Use getGrantedPermissions para verificar se o app já tem as permissões necessárias concedidas. Caso contrário, use createRequestPermissionResultContract para solicitá-las. Isso mostra a tela de permissões da Conexão Saúde.

// Create the permissions launcher
val requestPermissionActivityContract = PermissionController.createRequestPermissionResultContract()

val requestPermissions = registerForActivityResult(requestPermissionActivityContract) { granted ->
  if (granted.containsAll(PERMISSIONS)) {
    // Permissions successfully granted
  } else {
    // Lack of required permissions
  }
}

suspend fun checkPermissionsAndRun(healthConnectClient: HealthConnectClient) {
  val granted = healthConnectClient.permissionController.getGrantedPermissions()
  if (granted.containsAll(PERMISSIONS)) {
    // Permissions already granted; proceed with inserting or reading data
  } else {
    requestPermissions.launch(PERMISSIONS)
  }
}

Como os usuários podem conceder ou revogar permissões a qualquer momento, seu app precisa verificar as permissões sempre antes de usá-las e lidar com situações em que elas são perdidas.

Informações incluídas em um registro de passos

Cada StepsRecord contém as seguintes informações:

  • count: o número de passos dados no intervalo de tempo, como um Long.
  • startTime: a hora de início do intervalo de medição.
  • endTime: a hora de término do intervalo de medição.
  • startZoneOffset: o deslocamento de zona para a hora de início.
  • endZoneOffset: o deslocamento de zona para a hora de término.

Agregações aceitas

Os seguintes valores agregados estão disponíveis para StepsRecord:

Os seguintes valores agregados estão disponíveis para StepsCadenceRecord:

Exemplo de uso

As seções a seguir mostram como ler e gravar dados StepsRecord.

Gravar dados de passos

O app pode gravar dados de contagem de passos inserindo StepsRecord instâncias. O exemplo a seguir mostra como registrar 1.000 passos dados por um usuário:

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

Ler dados agregados

A maneira mais comum de ler dados de passos é agregar o total de passos em um período. O exemplo a seguir mostra como ler a contagem total de passos de um usuário em um determinado período:

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
}

Ler dados brutos

O exemplo a seguir mostra como ler dados brutos de StepsRecord dados entre um horário de início e término:

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