Se você quiser criar um app que gerencie os sinais vitais do usuário, use a Conexão Saúde para fazer o seguinte:
- Ler dados de sinais vitais, como pressão arterial, frequência cardíaca e temperatura corporal, de outros apps
- Gravar dados vitais registrados pelo app ou dispositivos conectados
- Monitorar tendências e fornecer insights de saúde com base em dados vitais
Este guia descreve como trabalhar com tipos de dados de métricas vitais, abordando permissões, fluxos de trabalho de leitura e gravação e práticas recomendadas.
Visão geral: como criar um rastreador de métricas vitais abrangente
Para criar uma experiência abrangente de acompanhamento de sinais vitais usando o Conexão Saúde, siga estas etapas principais:
- Solicitar as permissões adequadas para tipos de dados de métricas vitais.
- Gravar dados de sinais vitais usando registros como
BloodPressureRecord,HeartRateRecorde outros registros de sinais vitais. - Leitura de dados vitais para exibição, análise ou sincronização.
- Usar o agrupamento em lote para leitura e gravação de dados eficientes.
Esse fluxo de trabalho permite a interoperabilidade com outros apps da Conexão Saúde e verifica o acesso aos dados controlado pelo usuário.
Antes de começar
Antes de implementar os recursos de métricas vitais:
- Integre a Conexão Saúde usando a dependência adequada.
- Crie uma instância
HealthConnectClient. - Verifique se o app implementa fluxos de permissão de tempo de execução com base nas permissões de saúde.
Principais conceitos
Os dados de sinais vitais na Conexão Saúde são representados por vários tipos de registros, cada um correspondendo a uma medição fisiológica específica. Ao contrário das sessões de treino, os sinais vitais geralmente são registrados como dados de um ponto no tempo ou com base em intervalos.
Tipos de dados de métricas vitais
Os dados do Vitals são representados por tipos de registros individuais. Os tipos comuns incluem:
BloodPressureRecord: representa uma única leitura de pressão arterial, incluindo pressão sistólica e diastólica, além da posição do corpo.HeartRateRecord: representa uma série de medições de frequência cardíaca.RestingHeartRateRecord: representa uma única medição da frequência cardíaca em repouso.BodyTemperatureRecord: representa uma única leitura de temperatura corporal, incluindo o local de medição.BloodGlucoseRecord: representa uma única leitura de glicemia, incluindo relação com refeição e fonte de amostra.OxygenSaturationRecord: representa uma única leitura de saturação de oxigênio no sangue.RespiratoryRateRecord: representa uma única medição da frequência respiratória.
Para conferir uma lista completa de tipos de dados, consulte Tipos de dados do Conexão Saúde.
Considerações de desenvolvimento
Os dados de métricas vitais podem ser sensíveis, e os apps podem precisar gravar dados em resposta a medições de sensores ou entrada do usuário, ou sincronizar dados de um back-end. As permissões são essenciais para lidar com dados de sinais vitais.
Permissões
Seu app precisa solicitar as permissões relevantes da Conexão Saúde antes de ler ou gravar dados vitais. As permissões comuns para sinais vitais incluem pressão arterial, frequência cardíaca, temperatura corporal, glicemia, saturação de oxigênio e ritmo respiratório. Isso inclui o seguinte:
- Pressão arterial:permissões de leitura e gravação para
BloodPressureRecord. - Frequência cardíaca:permissões de leitura e gravação para
HeartRateRecord. - Frequência cardíaca em repouso:permissões de leitura e gravação para
RestingHeartRateRecord. - Temperatura corporal:permissões de leitura e gravação para
BodyTemperatureRecord. - Glicemia:permissões de leitura e gravação para
BloodGlucoseRecord. - Saturação de oxigênio:permissões de leitura e gravação para
OxygenSaturationRecord. - Ritmo respiratório:permissões de leitura e gravação para
RespiratoryRateRecord.
Confira um exemplo de como solicitar permissões para pressão arterial, frequência cardíaca e temperatura corporal:
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.
Para isso, crie um conjunto de permissões para os tipos de dados necessários. Verifique se as permissões no conjunto foram declaradas primeiro no manifesto do Android.
// Create a set of permissions for required data types
val PERMISSIONS =
setOf(
HealthPermission.getReadPermission(BloodPressureRecord::class),
HealthPermission.getWritePermission(BloodPressureRecord::class),
HealthPermission.getReadPermission(HeartRateRecord::class),
HealthPermission.getWritePermission(HeartRateRecord::class),
HealthPermission.getReadPermission(BodyTemperatureRecord::class),
HealthPermission.getWritePermission(BodyTemperatureRecord::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.
Para solicitar permissões, chame a função checkPermissionsAndRun:
if (!granted.containsAll(PERMISSIONS)) {
requestPermissions.launch(PERMISSIONS)
// Check if required permissions are not granted, and return
}
// Permissions already granted; proceed with inserting or reading data
Se você precisar solicitar permissões para um único tipo de dado, como pressão arterial, inclua apenas esse tipo de dado no conjunto de permissões:
O acesso à pressão arterial é protegido pelas seguintes permissões:
android.permission.health.READ_BLOOD_PRESSUREandroid.permission.health.WRITE_BLOOD_PRESSURE
Para adicionar a capability de pressão arterial ao app, comece solicitando
permissões para o tipo de dado BloodPressureRecord.
Confira a permissão necessária para poder gravar pressão arterial:
<application>
<uses-permission
android:name="android.permission.health.WRITE_BLOOD_PRESSURE" />
...
</application>
Para ler a pressão arterial, solicite as seguintes permissões:
<application>
<uses-permission
android:name="android.permission.health.READ_BLOOD_PRESSURE" />
...
</application>
Gravar dados de sinais vitais
Nesta seção, descrevemos como gravar dados de sinais vitais no app Conexão Saúde. Os dados de sinais vitais geralmente são gravados como registros individuais. Se você estiver gravando vários registros de uma só vez, como ao sincronizar de um sensor ou back-end, use o agrupamento em lote.
Exemplo de como escrever um BloodPressureRecord:
suspend fun writeBloodPressureRecord(healthConnectClient: HealthConnectClient) { val record = BloodPressureRecord( time = Instant.now(), zoneOffset = ZoneOffset.UTC, systolic = Pressure.millimetersOfMercury(120.0), diastolic = Pressure.millimetersOfMercury(80.0), bodyPosition = BloodPressureRecord.BODY_POSITION_SITTING_DOWN, measurementLocation = BloodPressureRecord.MEASUREMENT_LOCATION_LEFT_WRIST ) healthConnectClient.insertRecords(listOf(record)) }
Gravação em lote
Se o app precisar gravar vários pontos de dados, como sincronizar dados de um dispositivo conectado ou de um serviço de back-end, agrupe as gravações para melhorar a eficiência e reduzir o consumo de bateria. A Conexão Saúde pode processar até 1.000 registros em uma única solicitação de gravação.
O código a seguir mostra como gravar vários registros de uma vez:
suspend fun writeBatchRecords(healthConnectClient: HealthConnectClient) { val bloodPressureRecord = BloodPressureRecord( time = Instant.now(), zoneOffset = ZoneOffset.UTC, systolic = Pressure.millimetersOfMercury(120.0), diastolic = Pressure.millimetersOfMercury(80.0), bodyPosition = BloodPressureRecord.BODY_POSITION_SITTING_DOWN, measurementLocation = BloodPressureRecord.MEASUREMENT_LOCATION_LEFT_WRIST ) val heartRateRecord = HeartRateRecord( startTime = Instant.now().minusSeconds(60), startZoneOffset = ZoneOffset.UTC, endTime = Instant.now(), endZoneOffset = ZoneOffset.UTC, samples = listOf(HeartRateRecord.Sample(time = Instant.now().minusSeconds(30), beatsPerMinute = 80)) ) healthConnectClient.insertRecords(listOf(bloodPressureRecord, heartRateRecord)) }
Como ler dados de sinais vitais
Os apps podem ler dados de métricas vitais para mostrar medições, analisar tendências ou sincronizar dados
com um servidor externo. Para ler os sinais vitais, use um ReadRecordsRequest com o tipo de registro específico e filtre por um período.
Exemplo de leitura de dados de BloodPressureRecord:
suspend fun readBloodPressureRecords( healthConnectClient: HealthConnectClient, startTime: Instant, endTime: Instant ) { val response = healthConnectClient.readRecords( ReadRecordsRequest( recordType = BloodPressureRecord::class, timeRangeFilter = TimeRangeFilter.between(startTime, endTime) ) ) for (record in response.records) { // Process each blood pressure record val systolic = record.systolic val diastolic = record.diastolic } }
Se você precisar sincronizar sinais vitais com um servidor de back-end ou manter o repositório de dados do app atualizado com a Conexão Saúde, use ChangeLogs. Isso permite recuperar uma lista de registros inseridos, atualizados ou excluídos desde um ponto específico no tempo, o que é mais eficiente do que rastrear manualmente as mudanças ou ler repetidamente todos os dados. Para mais informações, consulte Sincronizar dados com o app Conexão Saúde.
Práticas recomendadas
Siga estas diretrizes para melhorar a confiabilidade dos dados e a experiência do usuário:
- Frequência e loteamento de gravação: para reduzir o overhead de entrada/saída e preservar a duração da bateria, agrupe os pontos de dados em uma única chamada
insertRecordscom lotes de até 1.000 registros, em vez de gravar cada ponto individualmente.- Rastreamento em tempo real:para atualizações frequentes de sensores (como monitores contínuos de glicose ou de frequência cardíaca), grave dados em lotes em intervalos de até 15 minutos para equilibrar atualizações em tempo real com eficiência da bateria.
- Sincronização em segundo plano:use
WorkManagerpara gravações adiadas, como sincronizar dados de um dispositivo complementar ou serviço de back-end. Tente usar um intervalo de 15 minutos para gravações em lote.
Evite gravar dados duplicados: use IDs de cliente. Ao criar registros, defina um
metadata.clientRecordId. O Conexão Saúde usa isso para identificar registros exclusivos. Se você tentar gravar um registro com umclientRecordIdque já existe, a Conexão Saúde vai ignorar o duplicado ou atualizar o registro atual em vez de criar um novo. Definir ummetadata.clientRecordIdé a maneira mais eficaz de evitar duplicatas durante novas tentativas de sincronização ou reinstalações de apps.val record = BloodPressureRecord( time = Instant.now(), zoneOffset = ZoneOffset.UTC, systolic = Pressure.millimetersOfMercury(120.0), diastolic = Pressure.millimetersOfMercury(80.0), bodyPosition = BloodPressureRecord.BODY_POSITION_SITTING_DOWN, measurementLocation = BloodPressureRecord.MEASUREMENT_LOCATION_LEFT_WRIST, metadata = Metadata( // Use a unique ID from your own database clientRecordId = "bp_20240101_user123" ) )
Verifique os dados atuais:antes de sincronizar, consulte a Conexão Saúde para ver se já existem registros do seu app no período de sincronização. Isso evita duplicidades ou a substituição de dados mais recentes.
Forneça justificativas claras para a permissão:use o fluxo
Permission.createIntentpara explicar por que o app precisa de acesso a dados de saúde, como "Para monitorar suas tendências de pressão arterial e fornecer insights".Alinhe os carimbos de data/hora com as medições:verifique se os carimbos de data/hora dos registros refletem com precisão quando as medições foram feitas. Para dados de intervalo como
HeartRateRecord, verifique sestartTimeeendTimeestão corretos.
Teste
Para verificar a correção dos dados e uma experiência do usuário de alta qualidade, siga estas estratégias de teste e consulte a documentação oficial Testar principais casos de uso.
Ferramentas de verificação
- Caixa de ferramentas do app Conexão Saúde:use esse app complementar para inspecionar manualmente registros, excluir dados de teste e simular mudanças no banco de dados. Essa é a melhor maneira de verificar se seus registros estão sendo armazenados corretamente.
- Teste de unidade com
FakeHealthConnectClient:use a biblioteca de teste para verificar como o app lida com casos extremos, como revogação de permissão ou exceções de API, sem precisar de um dispositivo físico.
Checklist de qualidade
Arquitetura típica
Uma implementação de métricas vitais geralmente inclui:
| Componente | Gerencia |
|---|---|
| Controlador de sinais vitais | Lógica de agrupamento de leitura de sensor/entrada |
| Camada de repositório (encapsula operações da Conexão Saúde): | Inserir registros de sinais vitais Ler registros de sinais vitais |
| Camada de interface (exibições): | Leituras em tempo real Dados históricos Gráficos e tendências |
Solução de problemas
| Sintoma | Possível causa | Resolução |
|---|---|---|
| Tipos de dados ausentes (por exemplo, pressão arterial) | Permissões de gravação ausentes ou filtros de período incorretos. | Verifique se você solicitou e se o usuário concedeu a permissão específica para o tipo de dados. Verifique se o ReadRecordsRequest usa um TimeRangeFilter que abrange o período de medição. Consulte Permissões. |
| Falha na gravação de registros | Unidades ou valores incorretos fora do intervalo válido. | A Conexão Saúde valida os valores de registros. Por exemplo, os valores de pressão arterial precisam estar em um intervalo fisiologicamente plausível. Consulte a documentação do tipo de dados para ver intervalos e unidades válidos. |
| Registros duplicados aparecem | clientRecordId ausente |
Atribua um clientRecordId exclusivo no Metadata de cada registro. Isso permite que a Conexão Saúde faça a remoção de duplicidade se os mesmos dados forem gravados duas vezes durante uma nova tentativa de sincronização. Consulte as práticas recomendadas. |
Etapas comuns de depuração
- Verificar o estado da permissão:sempre chame
getPermissionStatus()antes de tentar uma operação de leitura ou gravação. Os usuários podem revogar permissões nas configurações do sistema a qualquer momento.