Si quieres crear una experiencia de seguimiento del sueño en tu app, puedes usar Health Connect para hacer lo siguiente:
- Escribir sesiones de sueño
- Escribir datos de la etapa 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 crear 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
Para crear una experiencia de seguimiento del sueño integral con Health Connect, sigue estos pasos principales:
- Implementar correctamente los permisos según los permisos de salud
- Grabar sesiones con
SleepSessionRecord - Escribir tipos de datos como las etapas del sueño, la frecuencia cardíaca y la saturación de oxígeno de manera coherente durante la sesión
- Administrar correctamente la ejecución en segundo plano para verificar la captura continua de datos durante la noche
- Leer datos de la sesión para obtener análisis y resúmenes posteriores al sueño
Este flujo de trabajo permite la interoperabilidad con otras apps de Health Connect y verifica el acceso a los datos controlados 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 SleepSessionRecord actúa como el registro central del sueño y contiene detalles como las horas de inicio o finalización y las etapas 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: Una lista deSleepSessionRecord.Stageque incluye sueño profundo, ligero, REM y despierto- Metadatos de 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 y las etapas del sueño, incluidos el 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 ejecutarse durante períodos prolongados, con frecuencia en segundo plano cuando la pantalla está apagada. Cuando crees tus funciones de sueño, es importante tener en cuenta 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. Cuando se encuentra en este estado, debes usar lo siguiente:
- Servicios en primer plano para la recopilación de datos
WorkManagerpara la escritura o sincronización diferida- Estrategias de procesamiento por lotes para escrituras de registros regulares de datos detallados, como la frecuencia cardíaca
Mantén la continuidad conservando el ID de sesión coherente 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 sesiones de sueño y métricas como la frecuencia cardíaca o la saturación de oxígeno.
El acceso al 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 el sueño:
<application>
<uses-permission
android:name="android.permission.health.WRITE_SLEEP" />
...
</application>
Para leer el sueño, debes solicitar los siguientes permisos:
<application>
<uses-permission
android:name="android.permission.health.READ_SLEEP" />
...
</application>
En el siguiente ejemplo, se muestra 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.
// Create a set of permissions for required data types
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)
)
Usa getGrantedPermissions para ver si tu app ya tiene otorgados los
permisos necesarios. De lo contrario, usa
createRequestPermissionResultContract para solicitar
esos permisos. Se mostrará la pantalla de permisos de Health Connect.
// 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)
}
}
Debido a que los usuarios pueden otorgar o revocar permisos en cualquier momento, tu app debe verificar los permisos cada vez antes de usarlos y controlar las situaciones en las que se pierde el permiso.
Implementa 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 startTime y endTime de la sesión. Health Connect no usa un identificador de sesión para vincular sesiones de sueño con datos detallados. En cambio, la asociación es implícita a través de intervalos de tiempo superpuestos. Cuando lees datos de sueño, puedes usar el intervalo de tiempo de una sesión para consultar los tipos de datos asociados, como se muestra en Lectura de datos de sueño.
Escribe una sesión
Si bien se pueden registrar datos detallados, como la frecuencia cardíaca, durante una sesión de sueño, el SleepSessionRecord solo se debe escribir en Health Connect una vez que finalizó la sesión, por ejemplo, cuando el usuario se despierta. El
registro debe incluir startTime, endTime de la sesión y una lista de SleepSessionRecord.Stage
objetos 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 despierte o se detenga el seguimiento del sueño, recopila todas las etapas del sueño y crea 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))
Lectura de datos de sueño
Las apps pueden leer 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 ocurrió durante ese mismo intervalo de tiempo.
Leer sesión con datos asociados
Puedes leer sesiones de sueño con un ReadRecordsRequest con SleepSessionRecord como el tipo de registro, filtrado por un intervalo de tiempo. Para leer los datos asociados de una sesión determinada, realiza una segunda solicitud para el tipo de datos seleccionado, como HeartRateRecord, filtrando por el startTime y el endTime de la sesión de sueño.
En el siguiente ejemplo, se muestra cómo leer sesiones de sueño con datos de frecuencia cardíaca asociados para un intervalo de tiempo 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:
- Frecuencia de escritura
- Seguimiento activo(primer plano): Para el seguimiento activo del sueño, escribe datos a medida que estén disponibles o en un intervalo máximo de 15 minutos.
- Sincronización en segundo plano: Usa
WorkManagerpara escrituras diferidas. Intenta usar un intervalo de 15 minutos para lograr un equilibrio entre los datos en tiempo real y la eficiencia de la batería. - Procesamiento por lotes: No escribas cada evento del sensor de forma individual. Fragmenta tus solicitudes. 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 de sueño nueva y separada.
- Usa el procesamiento por lotes para los tipos de datos: Para reducir la sobrecarga de entrada/salida y preservar la duración de la batería, agrupa tus puntos de datos en una sola llamada
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 lo usa 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 apps.val record = RespiratoryRateRecord( rate = 16.0, time = time, zoneOffset = ZoneOffset.UTC, metadata = Metadata( // Use a unique ID from your own database clientRecordId = "respiratory_rate_20231030_1" ) )Verifica los datos existentes: Antes de la sincronización, consulta el intervalo de tiempo 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 motivos claros para el permiso: Usa el flujo
Permission.createIntentpara explicar por qué tu app necesita acceder a los datos de salud, por ejemplo, "Para analizar tus patrones de sueño".Prueba sesiones de larga duración: Supervisa el consumo de batería durante las sesiones que duran varias horas para verificar que el intervalo de procesamiento por lotes y el uso del sensor no agoten el dispositivo.
Alinea las marcas de tiempo con las tasas de los sensores: Haz coincidir las marcas de tiempo de tus registros con la frecuencia real de tus sensores para mantener la alta fidelidad de los datos.
Prueba
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 Test top use cases.
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 unitarias con
FakeHealthConnectClient: Usa la biblioteca de pruebas para verificar cómo controla tu app los casos extremos, como la revocación de permisos o las excepciones de API sin necesidad de un dispositivo físico.
Lista de verificación de calidad
Arquitectura típica
Una implementación de seguimiento del sueño suele incluir lo siguiente:
| Componente | Administra |
|---|---|
| Controlador de sesión | Estado de la sesión Temporizador Lógica de procesamiento por lotes Controladores de tipos de datos Recopilación de datos |
| Capa del repositorio (ajusta las operaciones de Health Connect): | Insertar sesión Insertar tipos de datos Insertar etapas del sueño Leer resúmenes de la sesión |
| Capa de la IU (muestra): | Duración Tipos de datos en vivo Visualización de la etapa del sueño |
Solución de problemas
| Síntoma | Causa posible | Resolución |
|---|---|---|
| Faltan tipos de datos (por ejemplo, frecuencia cardíaca). | Faltan permisos de escritura o filtros de tiempo 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. | Health Connect puede rechazar registros que se superpongan con 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 del sensor durante el sueño. | Se finalizó o se desactivó el servicio en primer plano. | Para recopilar datos del sensor 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 deduplicación si los mismos datos se escriben dos veces durante un reintento de sincronización. Consulta Prácticas recomendadas. |
Pasos comunes de depuración
| Verifica el estado del permiso. | Siempre llama a getPermissionStatus() antes de intentar una operación de lectura o escritura. Los usuarios pueden revocar 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 "Restringida". |