Esta guía es compatible con la versión 1.1.0 o posterior de Health Connect.
Si quieres crear una experiencia de seguimiento del sueño en tu app, puedes usar Health Connect para hacer lo siguiente:
- Cómo escribir sesiones de sueño
- Cómo escribir datos de fases del sueño
- Escribir datos de sueño, como la frecuencia cardíaca, la saturación de oxígeno y la frecuencia respiratoria
- Leer datos de sueño de otras apps
En esta guía, se describe cómo compilar estas funciones de sueño, incluidos los tipos de datos, la ejecución en segundo plano, los permisos, los flujos de trabajo recomendados y las prácticas recomendadas.
Descripción general: Cómo crear un monitor de sueño integral
Puedes crear una experiencia integral de seguimiento del sueño con Health Connect siguiendo estos pasos principales:
- Implementar correctamente los permisos según los permisos de salud
- Graba sesiones con
SleepSessionRecord. - Escribir tipos de datos, como fases del sueño, frecuencia cardíaca y saturación de oxígeno, de forma coherente durante la sesión
- Administrar correctamente la ejecución en segundo plano para verificar la captura continua de datos durante la noche
- Lectura de datos de sesiones para obtener resúmenes de sueño y análisis posteriores al sueño
Este flujo de trabajo habilita la interoperabilidad con otras apps de Health Connect y verifica el acceso a los datos controlado por el usuario.
Antes de comenzar
Antes de implementar las funciones de sueño, haz lo siguiente:
- Integra Health Connect con la dependencia adecuada.
- Crea una instancia de
HealthConnectClient. - Verifica que tu app implemente flujos de permisos de tiempo de ejecución basados en los permisos de salud.
Conceptos clave
Health Connect representa los datos de sueño con algunos componentes principales. Un objeto SleepSessionRecord actúa como el registro central del sueño y contiene detalles como las horas de inicio o finalización, y las fases del sueño. Durante una
sesión, se pueden registrar varios tipos de datos, como HeartRateRecord o
OxygenSaturationRecord.
Sesiones de sueño
Los datos de sueño se representan con SleepSessionRecord. Cada registro almacena lo siguiente:
startTimeendTimestages: Es una lista deSleepSessionRecord.Stageque incluye el sueño profundo, ligero, REM y despierto.- Metadatos de la sesión opcionales (título, notas)
Las apps pueden escribir varios tipos de datos asociados con una sesión.
Tipos de datos
Entre los tipos de datos comunes que se registran durante una sesión de sueño, se incluyen los siguientes:
SleepSessionRecord: Registra la duración del sueño y las etapas, incluidas las de sueño profundo, ligero, REM y despierto.HeartRateRecord: Registra la frecuencia cardíaca durante el sueño.OxygenSaturationRecord: Registra la saturación de oxígeno (SpO2) durante el sueño.RespiratoryRateRecord: Registra la frecuencia respiratoria durante el sueño.
Cada tipo de datos se almacena como un registro individual.
Consideraciones de desarrollo
Las apps de seguimiento del sueño suelen necesitar ejecutarse durante períodos prolongados, con frecuencia en segundo plano cuando la pantalla está apagada. Cuando crees tus funciones de sueño, es importante que consideres cómo administrar la ejecución en segundo plano y solicitar los permisos necesarios para los datos de sueño.
Ejecución en segundo plano
Las apps de seguimiento del sueño suelen ejecutarse durante la noche con la pantalla apagada. En este estado, debes usar lo siguiente:
- Servicios en primer plano para la recopilación de datos
WorkManagerpara la escritura diferida o la sincronización- Estrategias de procesamiento por lotes para escrituras de registros regulares de datos detallados, como la frecuencia cardíaca
Mantén la continuidad usando el mismo ID de sesión en todas las escrituras.
Permisos
Tu app debe solicitar los permisos pertinentes de Health Connect antes de leer o escribir datos de sueño. Para obtener una lista completa de los tipos de datos, consulta Tipos de datos de Health Connect. Los permisos comunes para el sueño incluyen las sesiones de sueño y las métricas, como la frecuencia cardíaca o la saturación de oxígeno.
El acceso a los datos de sueño está protegido por los siguientes permisos:
android.permission.health.READ_SLEEPandroid.permission.health.WRITE_SLEEP
Si deseas agregar la función de sueño a tu app, comienza por solicitar permisos para el tipo de datos SleepSession.
Este es el permiso que debes declarar para poder escribir datos de sueño:
<application>
<uses-permission
android:name="android.permission.health.WRITE_SLEEP" />
...
</application>
Para leer los datos de sueño, debes solicitar los siguientes permisos:
<application>
<uses-permission
android:name="android.permission.health.READ_SLEEP" />
...
</application>
A continuación, se muestra un ejemplo de cómo solicitar permisos para una sesión de sueño que incluye datos de frecuencia cardíaca, saturación de oxígeno y frecuencia respiratoria:
Después de crear una instancia de cliente, tu app debe solicitarle permisos al usuario. Los usuarios deben poder otorgar o rechazar permisos en cualquier momento. Para hacerlo, crea un conjunto de permisos para los tipos de datos necesarios. Primero, asegúrate de que los permisos del conjunto se declaren en tu manifiesto de Android.
val permissions = setOf( HealthPermission.getReadPermission(SleepSessionRecord::class), HealthPermission.getWritePermission(SleepSessionRecord::class), HealthPermission.getReadPermission(HeartRateRecord::class), HealthPermission.getWritePermission(HeartRateRecord::class), HealthPermission.getReadPermission(OxygenSaturationRecord::class), HealthPermission.getWritePermission(OxygenSaturationRecord::class), HealthPermission.getReadPermission(RespiratoryRateRecord::class), HealthPermission.getWritePermission(RespiratoryRateRecord::class) )
getGrantedPermissions para ver si tu app ya tiene otorgados los permisos necesarios. De lo contrario, usa createRequestPermissionResultContract para solicitarlos. Se mostrará la pantalla de permisos de 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.") } } }
Cómo implementar una sesión de sueño
En esta sección, se describe el flujo de trabajo recomendado para registrar datos de sueño.
Para alinear tipos de datos como HeartRateRecord o OxygenSaturationRecord con una sesión de sueño, regístralos con marcas de tiempo que se encuentren entre el startTime y el endTime de la sesión. Health Connect no usa un identificador de sesión para vincular las sesiones de sueño con datos detallados. En cambio, la asociación es implícita a través de intervalos de tiempo superpuestos. Cuando leas datos de sueño, puedes usar el período de una sesión para consultar los tipos de datos asociados, como se muestra en Cómo leer datos de sueño.
Cómo escribir una sesión
Si bien los datos detallados, como la frecuencia cardíaca, se pueden registrar durante una sesión de sueño, el SleepSessionRecord en sí solo se debe escribir en Health Connect una vez que finaliza la sesión, por ejemplo, cuando el usuario se despierta. El
registro debe incluir el
startTime, el endTime y una lista de objetos SleepSessionRecord.Stage
registrados durante la sesión, ya que SleepSessionRecord requiere que endTime
sea posterior a startTime.
Para escribir una sesión de sueño, sigue estos pasos:
- Genera un ID de registro de cliente único.
- Cuando el usuario se despierta o se detiene el seguimiento del sueño, recopila todas las fases del sueño y construye un
SleepSessionRecord. - Inserta el registro con
insertRecords.
Ejemplo:
val clientRecordId = UUID.randomUUID().toString()
val sessionStartTime = LocalDateTime.of(2023, 10, 30, 22, 0).toInstant(ZoneOffset.UTC)
val sessionEndTime = LocalDateTime.of(2023, 10, 31, 7, 0).toInstant(ZoneOffset.UTC)
val stages = mutableListOf<SleepSessionRecord.Stage>()
// Add recorded stages, for example:
stages.add(SleepSessionRecord.Stage(
startTime = sessionStartTime.plusSeconds(3600),
endTime = sessionStartTime.plusSeconds(7200),
stage = SleepSessionRecord.STAGE_TYPE_LIGHT)
)
stages.add(SleepSessionRecord.Stage(
startTime = sessionStartTime.plusSeconds(7200),
endTime = sessionStartTime.plusSeconds(10800),
stage = SleepSessionRecord.STAGE_TYPE_DEEP)
)
// ... other stages
val session = SleepSessionRecord(
startTime = sessionStartTime,
startZoneOffset = ZoneOffset.UTC,
endTime = sessionEndTime,
endZoneOffset = ZoneOffset.UTC,
stages = stages,
metadata = Metadata(clientRecordId = clientRecordId)
)
healthConnectClient.insertRecords(listOf(session))
Cómo leer datos de sueño
Las apps pueden leer las sesiones de sueño y sus datos asociados para resumir la actividad,
proporcionar estadísticas de salud o sincronizar datos con un servidor externo. Por ejemplo, puedes
leer un SleepSessionRecord y, luego, consultar el HeartRateRecord
que se produjo durante ese mismo intervalo.
Sesión de lectura con datos asociados
Puedes leer las sesiones de sueño con un ReadRecordsRequest con SleepSessionRecord como tipo de registro, filtrado por un período. Para leer los datos asociados de una sesión determinada, realiza una segunda solicitud para el tipo de datos seleccionado, como HeartRateRecord, filtrando por startTime y endTime de la sesión de sueño.
En el siguiente ejemplo, se muestra cómo leer las sesiones de sueño con datos de frecuencia cardíaca asociados para un período determinado:
suspend fun readSleepSessionsWithAssociatedData(
healthConnectClient: HealthConnectClient,
startTime: Instant,
endTime: Instant
) {
val response = healthConnectClient.readRecords(
ReadRecordsRequest(
recordType = SleepSessionRecord::class,
timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
)
)
for (sleepRecord in response.records) {
// Process each session
val stages = sleepRecord.stages
val notes = sleepRecord.notes
// To read specific granular data (like heart rate) that occurred during
// this session, use the session's startTime and endTime to filter
// the request for that data type.
val hrResponse = healthConnectClient.readRecords(
ReadRecordsRequest(
recordType = HeartRateRecord::class,
timeRangeFilter = TimeRangeFilter.between(
sleepRecord.startTime,
sleepRecord.endTime
)
)
)
for (heartRateRecord in hrResponse.records) {
for (sample in heartRateRecord.samples) {
val bpm = sample.beatsPerMinute
}
}
}
}
Prácticas recomendadas
Sigue estos lineamientos para mejorar la confiabilidad de los datos y la experiencia del usuario:
- Escribe con frecuencia durante el monitoreo de actividades: Para el monitoreo de actividades, escribe los datos a medida que estén disponibles o en un intervalo máximo de 15 minutos.
- Usa WorkManager para las sincronizaciones en segundo plano: Usa
WorkManagerpara las escrituras diferidas. Intenta establecer un intervalo de 15 minutos para lograr un equilibrio entre los datos en tiempo real y la eficiencia de la batería. - Agrupa las solicitudes de escritura: No escribas cada evento de sensor de forma individual. Divide tus solicitudes en fragmentos. Health Connect controla hasta 1,000 registros por solicitud de escritura.
- Mantén los IDs de sesión estables y únicos: Usa identificadores coherentes para tus sesiones. Si se edita o actualiza una sesión, usar el mismo ID evita que se trate como una sesión nueva y separada.
- Usa el procesamiento por lotes para los tipos de datos: Para reducir la sobrecarga de entrada y salida, y preservar la duración de la batería, agrupa tus datos en una sola llamada a
insertRecordsen lugar de escribir cada punto de forma individual. - Evita escribir datos duplicados: Usa IDs de cliente: Cuando crees registros, establece un
metadata.clientRecordId. Health Connect usa este valor para identificar registros únicos. Si intentas escribir un registro con unclientRecordIdque ya existe, Health Connect ignorará el duplicado o actualizará el registro existente en lugar de crear uno nuevo. Establecer unmetadata.clientRecordIdes la forma más eficaz de evitar duplicados durante los reintentos de sincronización o las reinstalaciones de la app.val record = StepsRecord( count = 100, startTime = startTime, endTime = endTime, startZoneOffset = ZoneOffset.UTC, endZoneOffset = ZoneOffset.UTC, metadata = Metadata( // Use a unique ID from your own database clientRecordId = "daily_steps_2023_10_27_user_123" ) )
- Verifica los datos existentes: Antes de sincronizar, consulta el período para ver si ya existen registros de tu app.
- Asegúrate de que las marcas de tiempo no se superpongan: Verifica que no se inicie una sesión nueva antes de que finalice la anterior. Las sesiones superpuestas pueden causar conflictos en los paneles de fitness y los cálculos de resumen.
- Proporciona justificaciones claras para el permiso: Usa el flujo de
Permission.createIntentpara explicar por qué tu app necesita acceder a los datos de salud, por ejemplo: "Para supervisar tus tendencias del estrés vascular y proporcionar estadísticas". - Prueba sesiones de larga duración: Supervisa el consumo de batería durante sesiones que duren varias horas para verificar que el intervalo de procesamiento por lotes y el uso de sensores no agoten la batería del dispositivo.
- Alinea las marcas de tiempo con las frecuencias de los sensores: Haz coincidir las marcas de tiempo de los registros con la frecuencia real de los sensores para mantener la alta fidelidad de los datos.
Pruebas
Para verificar la exactitud de los datos y una experiencia del usuario de alta calidad, sigue estas estrategias de prueba y consulta la documentación oficial de Prueba los casos de uso principales.
Herramientas de verificación
- Health Connect Toolbox: Usa esta app complementaria para inspeccionar registros de forma manual, borrar datos de prueba y simular cambios en la base de datos. Es la mejor manera de verificar que tus registros se almacenen correctamente.
- Pruebas de unidades con
FakeHealthConnectClient: Usa la biblioteca de pruebas para verificar cómo tu app controla los casos extremos, como la revocación de permisos o las excepciones de la API, sin necesidad de un dispositivo físico.
Lista de verificación de calidad
Arquitectura típica
Por lo general, una implementación de seguimiento del sueño incluye lo siguiente:
| Componente | Administra |
|---|---|
| Controlador de sesiones | Estado de la sesión Temporizador Lógica de procesamiento por lotes Controladores de tipos de datos Recopilación de datos |
| Capa del repositorio (un wrapper de las operaciones de Health Connect): | Inserta sesiones Inserta tipos de datos Inserta fases del sueño Lee resúmenes de sesiones |
| Capa de la IU (pantallas): | Duración Tipos de datos en tiempo real Visualización de las fases del sueño |
Solución de problemas
| Síntoma | Causa posible | Solución |
|---|---|---|
| Tipos de datos faltantes (por ejemplo, frecuencia cardíaca) | Faltan permisos de escritura o los filtros de tiempo son incorrectos. | Verifica que hayas solicitado el permiso de tipo de datos específico y que el usuario lo haya otorgado. Verifica que tu ReadRecordsRequest use un TimeRangeFilter que coincida con la sesión. Consulta Permisos. |
| No se puede escribir la sesión | Marcas de tiempo superpuestas | Es posible que Health Connect rechace los registros que se superpongan con los datos existentes de la misma app. Valida que el startTime de una sesión nueva sea posterior al endTime de la anterior. |
| No se registraron datos de sensores durante el sueño | El servicio en primer plano se cerró o está inactivo. | Para recopilar datos de sensores durante la noche mientras la pantalla está apagada, puedes usar un servicio en primer plano con foregroundServiceType="health". |
| Aparecen registros duplicados | Falta clientRecordId. |
Asigna un clientRecordId único en el Metadata de cada registro. Esto permite que Health Connect realice la desduplicación si se escriben los mismos datos dos veces durante un reintento de sincronización. Consulta las prácticas recomendadas. |
Pasos comunes para la depuración
| Verifica el estado de los permisos. | Siempre llama a getPermissionStatus() antes de intentar una operación de lectura o escritura. Los usuarios pueden revocar los permisos en la configuración del sistema en cualquier momento. |
| Verifica el modo de ejecución. | Si tu app no recopila datos en segundo plano, verifica que hayas declarado los permisos correctos en tu archivo AndroidManifest.xml y que el usuario no haya colocado la app en el modo "Restringido por batería". |