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: Normalmente, 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 pongan 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 de lectura en segundo plano completo.
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órmalo cuando llames a readRecords.
En el siguiente ejemplo, se muestra cómo leer los datos del recuento de pasos para un usuario en un período determinado. Para ver un ejemplo extendido con SensorManager, consulta la guía de datos de recuento de pasos.
suspend fun readStepsByTimeRange(
healthConnectClient: HealthConnectClient,
startTime: Instant,
endTime: Instant
) {
try {
val response = healthConnectClient.readRecords(
ReadRecordsRequest(
StepsRecord::class,
timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
)
)
for (record in response.records) {
// Process each record
}
} catch (e: Exception) {
// Run error handling here
}
}
También puedes leer tus datos de forma agregada con aggregate.
suspend fun readStepsByTimeRange(
healthConnectClient: HealthConnectClient,
startTime: Instant,
endTime: Instant
) {
try {
val response = healthConnectClient.aggregate(
AggregateRequest(
metrics = setOf(StepsRecord.COUNT_TOTAL),
timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
)
)
// The result may be null if no data is available in the time range
val stepCount = response[StepsRecord.COUNT_TOTAL]
} catch (e: Exception) {
// Run error handling here
}
}
Leer los pasos en dispositivos móviles
Con Android 14 (nivel de API 34) y la versión 20 o posterior de la extensión del SDK, Health Connect proporciona el recuento de pasos en el dispositivo. Si alguna app tiene el permiso de READ_STEPS, Health Connect comenzará a capturar los pasos del dispositivo Android y los usuarios verán los datos de pasos agregados automáticamente a las entradas de Pasos de Health Connect.
Para verificar si el recuento de pasos en el dispositivo está disponible, debes comprobar que el dispositivo ejecute Android 14 (nivel de API 34) y tenga al menos la versión 20 de la extensión del SDK. Puedes usar el siguiente código:
val isStepTrackingAvailable =
Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE &&
SdkExtensions.getExtensionVersion(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) >= 20
Los pasos de actividad capturados por Health Connect tienen su DataOrigin establecido en el nombre del paquete android. Si tu app simplemente lee los recuentos de pasos agregados con aggregate y no filtra por DataOrigin, los pasos registrados en el dispositivo se incluyen automáticamente en el total.
Si tu app necesita leer los pasos registrados en el dispositivo o si muestra datos de pasos desglosados por aplicación o dispositivo fuente, puedes consultar los registros en los que DataOrigin es android. Si tu app muestra la atribución de los datos de pasos, debes atribuir los datos del paquete de Android al dispositivo actual.
Para ello, puedes usar una etiqueta como "Tu teléfono", recuperar el nombre del dispositivo con Settings.Global.getString(resolver, Settings.Global.DEVICE_NAME) o inspeccionar el campo Device en los metadatos del registro.
En el siguiente ejemplo, se muestra cómo leer los datos agregados del recuento de pasos en dispositivos móviles filtrando el origen de datos android:
suspend fun readStepsByTimeRange(
healthConnectClient: HealthConnectClient,
startTime: Instant,
endTime: Instant
) {
try {
val response = healthConnectClient.aggregate(
AggregateRequest(
metrics = setOf(StepsRecord.COUNT_TOTAL),
timeRangeFilter = TimeRangeFilter.between(startTime, endTime),
dataOriginFilter = setOf(DataOrigin("android"))
)
)
// The result may be null if no data is available in the time range
val stepCount = response[StepsRecord.COUNT_TOTAL]
} catch (e: Exception) {
// Run error handling here
}
}
Recuento de pasos en el dispositivo
Análisis más detallado de la función de recuento de pasos en el dispositivo:
- Uso del sensor: Health Connect utiliza el sensor
TYPE_STEP_COUNTERdeSensorManager. 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 mayor a una vez por minuto.
- Atribución: Como se mencionó anteriormente, todos los pasos que registra esta función integrada en el dispositivo se atribuyen al nombre del paquete
androidenDataOrigin. - Activación: El mecanismo de conteo de pasos en el dispositivo solo está activo cuando al menos una aplicación del dispositivo tiene el permiso
READ_STEPSen 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 para un usuario en un período determinado con WorkManager:
class ScheduleWorker(private val appContext: Context, workerParams: WorkerParameters):
CoroutineWorker(appContext, workerParams) {
override suspend fun doWork(): Result {
// Read data and process it.
...
// Return success indicating successful data retrieval
return Result.success()
}
}
if (healthConnectClient
.features
.getFeatureStatus(
HealthConnectFeatures.FEATURE_READ_HEALTH_DATA_IN_BACKGROUND
) == HealthConnectFeatures.FEATURE_STATUS_AVAILABLE) {
// Check if necessary permission is granted
val grantedPermissions = healthConnectClient.permissionController.getGrantedPermissions()
if (PERMISSION_READ_HEALTH_DATA_IN_BACKGROUND !in grantedPermissions) {
// Perform read in foreground
...
} else {
// Schedule the periodic work request in background
val periodicWorkRequest = PeriodicWorkRequestBuilder<ScheduleWorker>(1, TimeUnit.HOURS)
.build()
WorkManager.getInstance(context).enqueueUniquePeriodicWork(
"read_health_connect",
ExistingPeriodicWorkPolicy.KEEP,
periodicWorkRequest
)
}
} else {
// Background reading is not available, perform read in foreground
...
}
El parámetro ReadRecordsRequest tiene un valor predeterminado pageSize de 1,000.
Si la cantidad de registros en un solo readResponse supera el pageSize de la solicitud, debes iterar todas las páginas de la respuesta para recuperar todos los registros con pageToken.
Sin embargo, ten cuidado para evitar problemas relacionados con la 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 lea datos históricos. 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 solicitando un permiso de lectura.
Para leer los datos históricos, debes indicar el nombre del paquete como un objeto DataOrigin en el parámetro dataOriginFilter 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 el PERMISSION_READ_HEALTH_DATA_HISTORY.
De lo contrario, sin este permiso, cualquier intento de leer registros con una antigüedad superior a 30 días generará 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 tu 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. Ahora, la fecha más antigua de la que tu app puede leer datos de forma predeterminada es el 15 de abril de 2023.
Cómo controlar 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:
| Excepción | Descripción | Práctica recomendada |
|---|---|---|
IllegalStateException
| Se produjo una de las siguientes situaciones:
| 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:
|
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:
|
SecurityException
| Se producen problemas cuando las solicitudes requieren permisos que no se otorgan. | Para evitar esto, asegúrate de haber declarado el uso de los 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. |