Cómo leer datos sin procesar

En el siguiente ejemplo, se muestra cómo leer datos sin procesar como parte de un flujo de trabajo común.

Lee datos

Health Connect permite que las apps lean datos del almacén de datos cuando la app está en primer plano y en segundo plano:

  • Lecturas en primer plano: Por lo general, puedes leer datos de Health Connect cuando tu app está en primer plano. En estos casos, puedes considerar usar un servicio en primer plano para ejecutar esta operación en caso de que el usuario o el sistema coloquen tu app en segundo plano durante una operación de lectura.

  • Lecturas en segundo plano: Si solicitas un permiso adicional al usuario, puedes leer datos después de que el usuario o el sistema coloquen tu app en segundo plano. Consulta el ejemplo completo de lectura en segundo plano.

El tipo de datos de Pasos en Health Connect captura la cantidad de pasos que dio un usuario entre cada medición. El recuento de pasos representa una medición común en todas las plataformas de salud, actividad física y bienestar. Health Connect te permite leer y escribir datos de recuento de pasos.

Para leer registros, crea un ReadRecordsRequest e infórma lo cuando llames a readRecords.

En el siguiente ejemplo, se muestra cómo leer los datos del recuento de pasos de un usuario en un período determinado. Para ver un ejemplo extendido con SensorManager, consulta la guía de datos del recuento de pasos.

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

También puedes leer tus datos de forma agregada con aggregate.

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
}

Leer pasos móviles

Con Android 14 (nivel de API 34) y la extensión del SDK versión 20 o posterior, Health Connect proporciona el recuento de pasos integrado en el dispositivo. Si alguna app tiene el permiso READ_STEPS, Health Connect comienza a capturar pasos desde el dispositivo con tecnología Android, y los usuarios ven los datos de pasos agregados automáticamente a las entradas de Pasos de Health Connect.

Para verificar si el recuento de pasos integrado en el dispositivo está disponible, verifica que el dispositivo ejecute Android 14 (nivel de API 34) y tenga al menos la extensión del SDK versión 20:

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

Si tu app lee recuentos de pasos agregados con aggregate y no filtra por DataOrigin, los pasos integrados en el dispositivo se incluyen automáticamente en el total, y no se requieren cambios para la actualización de junio de 2026.

Cambio de atribución para los pasos integrados en el dispositivo

A partir de la actualización de junio de 2026, los pasos que Health Connect rastrea de forma nativa se atribuyen a un nombre de paquete sintético (SPN), como com.android.healthconnect.phone.jd5bdd37e1a8d3667a05d0abebfc4a89e.

Anteriormente, los pasos integrados se atribuían al nombre del paquete android. Los datos históricos de pasos registrados antes de junio de 2026 conservan el nombre del paquete android.

Los SPN son específicos del dispositivo y tienen un alcance por aplicación para proteger la privacidad del usuario:

  • Estable: El SPN del dispositivo actual es estable para tu aplicación.
  • Alcance de la aplicación: Las diferentes aplicaciones en el mismo dispositivo ven diferentes SPN para los datos de pasos integrados en el dispositivo.

Consulta de pasos integrado en el dispositivo

Debido a que los SPN tienen un alcance y son específicos del dispositivo, no debes codificar de forma rígida los valores de SPN. En su lugar, usa la API de getCurrentDeviceDataSource() para recuperar el SPN del dispositivo actual.

Si bien el recuento de pasos integrado en el dispositivo requiere la extensión del SDK versión 20 o posterior, la API de getCurrentDeviceDataSource() está disponible en Android 14 (nivel de API 34) con la extensión del SDK versión 11 o posterior.

La API de getCurrentDeviceDataSource() aún no está disponible en la biblioteca de Health Connect Jetpack. En su lugar, los siguientes ejemplos usan la API del framework de 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

Si tu app necesita leer pasos integrados en el dispositivo o si muestra datos de pasos desglosados por aplicación o dispositivo de origen, debes consultar los registros en los que DataOrigin es android o coincide con el SPN del dispositivo. Si tu app muestra la atribución de los datos de pasos, usa metadata.device para identificar el dispositivo de origen de los registros individuales. Para los pasos integrados en el dispositivo identificados por un SPN en datos agregados, puedes usar metadatos del dispositivo, como model o manufacturer de DeviceDataSource para la atribución, o usar una etiqueta genérica como "Tu teléfono" para los pasos integrados en el dispositivo.

En el siguiente ejemplo, se muestra cómo leer datos agregados del recuento de pasos integrado en el dispositivo filtrando por android y el SPN del dispositivo actual:

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

Recuento de pasos en el dispositivo

  • Uso del sensor: Health Connect utiliza el TYPE_STEP_COUNTER sensor de SensorManager. Este sensor está optimizado para un bajo consumo de energía, lo que lo hace ideal para el seguimiento continuo de pasos en segundo plano.
  • Granularidad de los datos: Para conservar la duración de la batería, los datos de pasos suelen agruparse y escribirse en la base de datos de Health Connect con una frecuencia no superior a una vez por minuto.
  • Atribución: Los pasos registrados por esta función antes de junio de 2026 se atribuyen al nombre del paquete android en DataOrigin. Después de esta fecha, se atribuyen a un SPN específico del dispositivo. Consulta Cambio de atribución para los pasos integrado en el dispositivo.
  • Activación: El mecanismo de recuento de pasos integrado en el dispositivo solo está activo cuando al menos una aplicación del dispositivo tiene el permiso READ_STEPS en Health Connect.

Ejemplo de lectura en segundo plano

Para leer datos en segundo plano, declara el siguiente permiso en tu archivo de manifiesto:

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

En el siguiente ejemplo, se muestra cómo leer los datos del recuento de pasos en segundo plano de un usuario en un período determinado con WorkManager:

class ScheduleWorker(appContext: Context, workerParams: WorkerParameters) :
    CoroutineWorker(appContext, workerParams) {

    override suspend fun doWork(): Result {
        val healthConnectClient = HealthConnectClient.getOrCreate(applicationContext)
        // Perform background read logic here
        return Result.success()
    }
}
@OptIn(ExperimentalFeatureAvailabilityApi::class)
fun enqueueBackgroundReadWorker(context: Context, healthConnectClient: HealthConnectClient) {
    if (healthConnectClient
            .features
            .getFeatureStatus(
                HealthConnectFeatures.FEATURE_READ_HEALTH_DATA_IN_BACKGROUND
            ) == HealthConnectFeatures.FEATURE_STATUS_AVAILABLE
    ) {

        val periodicWorkRequest = PeriodicWorkRequestBuilder<ScheduleWorker>(1, TimeUnit.HOURS)
            .build()

        WorkManager.getInstance(context).enqueueUniquePeriodicWork(
            "read_health_connect",
            ExistingPeriodicWorkPolicy.KEEP,
            periodicWorkRequest
        )
    }
}

El parámetro ReadRecordsRequest tiene un valor pageSize predeterminado de 1,000. Si la cantidad de registros en una sola readResponse supera el pageSize de la solicitud, debes iterar en todas las páginas de la respuesta para recuperar todos los registros con pageToken. Sin embargo, ten cuidado para evitar problemas de limitación de frecuencia.

Ejemplo de lectura de pageToken

Se recomienda usar pageToken para leer registros y recuperar todos los datos disponibles del período solicitado.

En el siguiente ejemplo, se muestra cómo leer todos los registros hasta que se agoten todos los tokens de página:

val type = HeartRateRecord::class
val endTime = Instant.now()
val startTime = endTime.minus(Duration.ofDays(7))

try {
    var pageToken: String? = null
    do {
        val readResponse =
            healthConnectClient.readRecords(
                ReadRecordsRequest(
                    recordType = type,
                    timeRangeFilter = TimeRangeFilter.between(
                        startTime,
                        endTime
                    ),
                    pageToken = pageToken
                )
            )
        val records = readResponse.records
        // Do something with records
        pageToken = readResponse.pageToken
    } while (pageToken != null)
} catch (quotaError: IllegalStateException) {
    // Backoff
}
Para obtener información sobre las prácticas recomendadas cuando se leen conjuntos de datos grandes, consulta Planifica para evitar la limitación de frecuencia.

Lectura de datos pasados

Si una app escribió registros en Health Connect anteriormente, es posible que la app vuelva a leerlos. Esto se aplica a situaciones en las que la app necesita volver a sincronizarse con Health Connect cuando el usuario la reinstala.

Se aplican algunas restricciones de lectura:

  • Para Android 14 y versiones posteriores

    • No hay límite histórico para que una app lea sus propios datos.
    • Límite de 30 días para que una app lea otros datos.
  • Para Android 13 y versiones anteriores

    • Límite de 30 días para que la app lea cualquier dato.

Las restricciones se pueden quitar si se solicita un permiso de lectura.

Para leer datos históricos, debes indicar el nombre del paquete como un DataOrigin objeto en el dataOriginFilter parámetro de tu ReadRecordsRequest.

En el siguiente ejemplo, se muestra cómo indicar un nombre de paquete cuando se leen los registros de frecuencia cardíaca:

try {
    val response =  healthConnectClient.readRecords(
        ReadRecordsRequest(
            recordType = HeartRateRecord::class,
            timeRangeFilter = TimeRangeFilter.between(startTime, endTime),
            dataOriginFilter = setOf(DataOrigin("com.my.package.name"))
        )
    )
    for (record in response.records) {
        // Process each record
    }
} catch (e: Exception) {
    // Run error handling here
}

Cómo leer datos anteriores a 30 días

De forma predeterminada, todas las aplicaciones pueden leer datos de Health Connect hasta 30 días antes del otorgamiento de cualquier permiso.

Si necesitas extender los permisos de lectura más allá de cualquiera de las restricciones predeterminadas, solicita PERMISSION_READ_HEALTH_DATA_HISTORY. De lo contrario, sin este permiso, un intento de leer registros anteriores a 30 días genera un error.

Historial de permisos de una app borrada

Si un usuario borra tu app, se revocarán todos los permisos, incluido el permiso de historial. Si el usuario vuelve a instalar tu app y le otorga permiso de nuevo, se aplicarán las mismas restricciones predeterminadas, y la app podrá leer datos de Health Connect hasta 30 días antes de esa fecha nueva.

Por ejemplo, supongamos que el usuario borra tu app el 10 de mayo de 2023 y, luego, la reinstala el 15 de mayo de 2023 y otorga permisos de lectura. De forma predeterminada, la fecha más antigua de la que puede leer datos es el 15 de abril de 2023.

Controla excepciones

Health Connect genera excepciones estándar para las operaciones de CRUD cuando se produce un problema. Tu app debe detectar y controlar cada una de estas excepciones según corresponda.

Cada método de HealthConnectClient enumera las excepciones que se pueden generar. En general, tu app debe controlar las siguientes excepciones:

Tabla 1: Excepciones de Health Connect y prácticas recomendadas
Excepción Descripción Práctica recomendada
IllegalStateException Se produjo una de las siguientes situaciones:

  • El servicio de Health Connect no está disponible.
  • La solicitud no es una construcción válida. Por ejemplo, una solicitud agregada en buckets periódicos en la que se usa un objeto Instant para el timeRangeFilter.

Controla posibles problemas con las entradas antes de realizar una solicitud. Preferentemente, asigna valores a las variables o úsalos como parámetros dentro de una función personalizada en lugar de usarlos de forma directa en tus solicitudes para que puedas aplicar estrategias de manejo de errores.
IOException Se producen problemas al leer y escribir datos del disco. Para evitar este problema, estas son algunas sugerencias:

  • Crea una copia de seguridad de las entradas del usuario.
  • Ten la capacidad de controlar los problemas que ocurran durante las operaciones de escritura masiva. Por ejemplo, asegúrate de que el proceso pase el problema y lleve a cabo las operaciones restantes.
  • Aplica reintentos y estrategias de retirada para controlar los problemas de las solicitudes.

RemoteException Se produjeron errores en el servicio subyacente al que se conecta el SDK o en la comunicación con él.

Por ejemplo, tu app intenta borrar un registro con una uid determinada. Sin embargo, se arroja la excepción una vez que la app detecta que no existe el registro cuando se verifica en el servicio subyacente.
Para evitar este problema, estas son algunas sugerencias:

  • Realiza sincronizaciones frecuentes entre el almacén de datos de tu app y Health Connect.
  • Aplica reintentos y estrategias de retirada para controlar los problemas de las solicitudes.

SecurityException Se producen problemas cuando las solicitudes requieren permisos que no se otorgan. Para evitar esto, asegúrate de haber declarado el uso de tipos de datos de Health Connect para tu app publicada. Además, debes declarar los permisos de Health Connect en el archivo de manifiesto y en tu actividad.