Este guia é compatível com a versão 1.1.0-alpha12 do Health Connect.
Este guia aborda o processo para gravar ou atualizar dados na plataforma Conexão Saúde.
Configurar a estrutura de dados
Antes de gravar dados, precisamos configurar os registros. Há mais de 50 tipos de dados e cada um tem as respectivas estruturas. Consulte a referência do Jetpack para detalhes sobre os tipos de dados disponíveis.
Registros básicos
O tipo de dado de Passos na plataforma Conexão Saúde captura o número de passos de um usuário entre as leituras. A contagem de passos é uma medida comum nas plataformas de saúde, condicionamento físico e bem-estar.
O exemplo abaixo mostra como definir dados de contagem de passos:
val endTime = Instant.now()
val startTime = endTime.minus(Duration.ofMinutes(15))
val stepsRecord = StepsRecord(
count = 120,
startTime = startTime,
endTime = endTime,
startZoneOffset = ZoneOffset.UTC,
endZoneOffset = ZoneOffset.UTC,
metadata = Metadata.autoRecorded(
device = Device(type = Device.TYPE_WATCH)
)
)
Registros com unidades de medida
A plataforma Conexão Saúde pode armazenar valores com as unidades de medida deles para maior precisão. Um exemplo é o tipo de dados de Nutrição, que é amplo e abrangente. Ele inclui uma grande variedade de campos nutricionais opcionais, desde o total de carboidratos até quantidades de vitaminas. Cada ponto de dados representa os nutrientes possivelmente consumidos como parte de uma refeição ou de um alimento.
Nesse tipo de dados, todos os nutrientes são representados em unidades de
Mass
, enquanto a energy
é representada em uma unidade de Energy
.
O exemplo abaixo mostra como definir dados nutricionais para um usuário que comeu uma banana:
val endTime = Instant.now()
val startTime = endTime.minus(Duration.ofMinutes(1))
val banana = NutritionRecord(
name = "banana",
energy = 105.0.kilocalories,
dietaryFiber = 3.1.grams,
potassium = 0.422.grams,
totalCarbohydrate = 27.0.grams,
totalFat = 0.4.grams,
saturatedFat = 0.1.grams,
sodium = 0.001.grams,
sugar = 14.0.grams,
vitaminB6 = 0.0005.grams,
vitaminC = 0.0103.grams,
startTime = startTime,
endTime = endTime,
startZoneOffset = ZoneOffset.UTC,
endZoneOffset = ZoneOffset.UTC,
metadata = Metadata.manualEntry(
device = Device(type = Device.TYPE_PHONE)
)
)
Registros com dados de série
A Conexão Saúde pode armazenar uma lista de dados de série. Um exemplo é o tipo de dados Frequência cardíaca, que captura uma série de amostras de batimentos cardíacos detectados entre as leituras.
Nesse tipo de dados, o parâmetro samples
é representado por uma lista de
amostras de frequência cardíaca. Cada amostra contém um valor beatsPerMinute
e um time
.
O exemplo abaixo mostra como definir dados da série para frequência cardíaca:
val endTime = Instant.now()
val startTime = endTime.minus(Duration.ofMinutes(5))
val heartRateRecord = HeartRateRecord(
startTime = startTime,
startZoneOffset = ZoneOffset.UTC,
endTime = endTime,
endZoneOffset = ZoneOffset.UTC,
// records 10 arbitrary data, to replace with actual data
samples = List(10) { index ->
HeartRateRecord.Sample(
time = startTime + Duration.ofSeconds(index.toLong()),
beatsPerMinute = 100 + index.toLong(),
)
},
metadata = Metadata.autoRecorded(
device = Device(type = Device.TYPE_WATCH)
))
Gravar dados
Um dos fluxos de trabalho comuns na plataforma Conexão Saúde é a gravação de dados. Para adicionar registros,
use insertRecords
.
O exemplo abaixo mostra como gravar dados inserindo contagens de passos:
suspend fun insertSteps(healthConnectClient: HealthConnectClient) {
val endTime = Instant.now()
val startTime = endTime.minus(Duration.ofMinutes(5))
try {
val stepsRecord = StepsRecord(
count = 120,
startTime = startTime,
endTime = endTime,
startZoneOffset = ZoneOffset.UTC,
endZoneOffset = ZoneOffset.UTC,
metadata = Metadata.autoRecorded(
device = Device(type = Device.TYPE_WATCH)
)
)
healthConnectClient.insertRecords(listOf(stepsRecord))
} catch (e: Exception) {
// Run error handling here
}
}
Atualizar dados
Se você precisar mudar um ou mais registros, especialmente quando precisar sincronizar o repositório de dados do seu app com os dados da Conexão Saúde, é possível atualizar seus dados. Há duas maneiras de atualizar os dados atuais, dependendo do identificador usado para encontrar os registros.
Metadados
Primeiro, examine a classe Metadata
, porque ela é necessária ao
atualizar dados. Na criação, cada Record
da Conexão Saúde tem um
campo metadata
. As propriedades abaixo são relevantes para a
sincronização:
Propriedades | Descrição |
---|---|
id
|
Cada Record no app Conexão Saúde tem um valor de id
exclusivo.A plataforma Conexão Saúde preenche automaticamente esse registro ao inserir um novo. |
lastModifiedTime
|
Cada Record também grava a última vez em que o
registro foi modificado.A plataforma Conexão Saúde preenche esse registro automaticamente. |
clientRecordId
|
Cada Record pode ter um ID exclusivo associado
a ele para servir como referência no repositório de dados do app.
Seu app fornece esse valor. |
clientRecordVersion
|
Quando um registro tem um clientRecordId , a
clientRecordVersion pode ser usada para permitir que os dados
sejam sincronizados com a versão no repositório de dados
do app.Seu app fornece esse valor. |
Atualizar pelo ID do registro
Para atualizar os dados, primeiro prepare os registros necessários. Faça as mudanças nos
registros, se necessário. Em seguida, chame updateRecords
para fazer
as mudanças.
O exemplo abaixo mostra como atualizar os dados. Para essa finalidade, cada registro tem os valores de zona ajustados para PST.
suspend fun updateSteps(
healthConnectClient: HealthConnectClient,
prevRecordStartTime: Instant,
prevRecordEndTime: Instant
) {
try {
val request = healthConnectClient.readRecords(
ReadRecordsRequest(
recordType = StepsRecord::class, timeRangeFilter = TimeRangeFilter.between(
prevRecordStartTime, prevRecordEndTime
)
)
)
val newStepsRecords = arrayListOf<StepsRecord>()
for (record in request.records) {
// Adjusted both offset values to reflect changes
val sr = StepsRecord(
count = record.count,
startTime = record.startTime,
startZoneOffset = record.startTime.atZone(ZoneId.of("PST")).offset,
endTime = record.endTime,
endZoneOffset = record.endTime.atZone(ZoneId.of("PST")).offset,
metadata = record.metadata
)
newStepsRecords.add(sr)
}
healthConnectClient.updateRecords(newStepsRecords)
} catch (e: Exception) {
// Run error handling here
}
}
Inserir e atualizar usando o ID do registro do cliente
Se você estiver usando os valores opcionais de ID e de versão de registro do cliente,
recomendamos usar insertRecords
em vez de updateRecords
.
A função insertRecords
pode inserir e atualizar dados.
Se os dados já existirem na Conexão Saúde com base no conjunto de IDs do
registro do cliente, eles serão substituídos. Caso contrário, serão gravados como novos.
Esse cenário é útil sempre que você precisa sincronizar dados do
repositório de dados do seu app com a plataforma Conexão Saúde.
O exemplo abaixo mostra como executar uma inserção em dados extraídos do repositório de dados do app:
suspend fun pullStepsFromDatastore() : ArrayList<StepsRecord> {
val appStepsRecords = arrayListOf<StepsRecord>()
// Pull data from app datastore
// ...
// Make changes to data if necessary
// ...
// Store data in appStepsRecords
// ...
var sr = StepsRecord(
metadata = Metadata.autoRecorded(
clientRecordId = "Your client record ID",
device = Device(type = Device.TYPE_WATCH)
),
// Assign more parameters for this record
)
appStepsRecords.add(sr)
// ...
return appStepsRecords
}
suspend fun upsertSteps(
healthConnectClient: HealthConnectClient,
newStepsRecords: ArrayList<StepsRecord>
) {
try {
healthConnectClient.insertRecords(newStepsRecords)
} catch (e: Exception) {
// Run error handling here
}
}
Depois disso, você pode chamar essas funções na linha de execução principal.
upsertSteps(healthConnectClient, pullStepsFromDatastore())
Verificação de valor na versão do registro do cliente
Se o processo de inserção e atualização de dados incluir a versão do registro do cliente, a Conexão
Saúde vai realizar verificações de comparação nos valores de
clientRecordVersion
. Se a versão dos dados inseridos for mais recente que a
atual versão dos dados, eles serão atualizados. Caso contrário, o processo
vai ignorar a mudança e o valor permanecerá o mesmo.
Para incluir o controle de versão nos seus dados, é necessário fornecer à
Metadata.clientRecordVersion
um valor Long
com base na lógica do controle de
versão.
val endTime = Instant.now()
val startTime = endTime.minus(Duration.ofMinutes(15))
val stepsRecord = StepsRecord(
count = 100L,
startTime = startTime,
startZoneOffset = ZoneOffset.UTC,
endTime = endTime,
endZoneOffset = ZoneOffset.UTC,
metadata = Metadata.manualEntry(
clientRecordId = "Your supplied record ID",
clientRecordVersion = 0L, // Your supplied record version
device = Device(type = Device.TYPE_WATCH)
)
)
As inserções não incrementam automaticamente a version
sempre que há mudanças,
evitando instâncias inesperadas de substituição de dados. É necessário fornecê-las manualmente com
um valor mais alto.
Práticas recomendadas para gravar dados
Os apps só podem gravar dados de origem própria na Conexão Saúde.
Se os dados no seu app tiverem sido importados de outro, a responsabilidade vai ser transferida para o outro app gravar os próprios dados na Conexão Saúde.
Também é uma boa ideia implementar uma lógica que processe exceções de gravação, como dados fora dos limites ou um erro interno do sistema. É possível aplicar as estratégias de espera e nova tentativa em um mecanismo de agendamento de jobs. Se a gravação na Conexão Saúde falhar, o app precisa conseguir passar desse ponto de exportação. Não se esqueça de registrar e informar erros para ajudar no diagnóstico.
Ao rastrear dados, há algumas sugestões que você pode seguir, dependendo da maneira como seu app grava dados.
Rastreamento passivo
Esse tipo de rastreamento inclui apps que gravam dados de forma passiva sobre o condicionamento físico ou saúde do usuário, como a gravação contínua em segundo plano dos passos ou da frequência cardíaca.
Seu app precisa gravar dados periodicamente na Conexão Saúde destas formas:
- Em cada sincronização, grave apenas os dados novos e atualizados que foram modificados desde a última sincronização.
- Separe as solicitações em, no máximo, 1.000 registros para cada pedido de gravação.
- Use o
WorkManager
para programar tarefas periódicas em segundo plano com um período de pelo menos 15 minutos. Faça com que as tarefas sejam executadas apenas quando o dispositivo estiver inativo e não estiver com pouca bateria.
val constraints = Constraints.Builder() .requiresBatteryNotLow() .requiresDeviceIdle(true) .build() val writeDataWork = PeriodicWorkRequestBuilder<WriteDataToHealthConnectWorker>( 15, TimeUnit.MINUTES, 5, TimeUnit.MINUTES ) .setConstraints(constraints) .build()
Rastreamento ativo
Isso inclui apps que executam rastreamento baseado em eventos, como exercícios e sono, ou entrada manual do usuário, como nutrição. Esses registros são criados quando o app está em primeiro plano ou em eventos raros em que o app é usado algumas vezes por dia.
Confira se o app não mantém a Conexão Saúde em execução durante todo o evento.
Os dados precisam ser gravados na Conexão Saúde de duas maneiras:
- Sincronizar dados na Conexão Saúde após a conclusão de um evento. Por exemplo, sincronize os dados quando o usuário encerrar uma sessão de exercício rastreada.
- Agende uma tarefa única usando o
WorkManager
para sincronizar dados mais tarde.
Práticas recomendadas para granularidade e frequência de gravações
Ao gravar dados na Conexão Saúde, use a resolução adequada. Usar a resolução adequada ajuda a reduzir a carga de armazenamento, mantendo os dados consistentes e precisos. A resolução de dados abrange duas coisas:
- Frequência de gravações: a frequência com que o app envia novos dados para a Conexão Saúde. Por exemplo, grave novos dados a cada 15 minutos.
- Granularidade dos dados gravados: a frequência com que os dados enviados foram amostrados. Por exemplo, grave amostras de frequência cardíaca a cada 5 segundos. Nem todos os tipos de dados exigem a mesma taxa de amostragem. Há poucos benefícios em atualizar os dados de contagem de passos a cada segundo, ao contrário de uma cadência menos frequente, como a cada 60 segundos. No entanto, taxas de amostragem maiores podem oferecer aos usuários uma visão mais detalhada e granular dos dados de saúde e condicionamento físico. As frequências de taxa de amostragem precisam encontrar um equilíbrio entre detalhes e desempenho.
Gravar dados monitorados ao longo do dia
Para dados coletados de forma contínua, como passos, seu app precisa gravar na Conexão Saúde pelo menos a cada 15 minutos durante o dia.
Tipo de dado |
Unidade |
Esperado |
Exemplo |
Etapas |
passos |
A cada um minuto |
23:14 - 23:15 - 5 etapas 23:16 - 23:17 - 22 etapas 23:17 - 23:18 - 8 etapas |
StepsCadence |
passos/min |
A cada um minuto |
23:14 - 23:15 - 5 spm 23:16 - 23:17 - 22 spm 23:17 - 23:18 - 8 spm |
Impulsos na cadeira de rodas |
empurra |
A cada um minuto |
23:14 - 23:15 - 5 envios 23:16 - 23:17 - 22 envios 23:17 - 23:18 - 8 pushes |
ActiveCaloriesBurned |
Calorias |
A cada 15 minutos |
23:15 - 23:30 - 2 calorias 23:30 - 23:45 - 25 calorias 23:45 - 00:00 - 5 calorias |
TotalCaloriesBurned |
Calorias |
A cada 15 minutos |
23:15 - 23:30 - 16 calorias 23:30 - 23:45 - 16 calorias 23:45 - 00:00 - 16 calorias |
Distância |
km/min |
A cada um minuto |
23:14-23:15 - 0,008 km 23:16 - 23:16 - 0,021 km 23:17 - 23:18 - 0,012 km |
ElevationGained |
m |
A cada um minuto |
20:36 - 20:37 - 3,048m 20:39 - 20:40 - 3,048m 23:23 - 23:24 - 9,144m |
FloorsClimbed |
andares |
A cada um minuto |
23:14 - 23:15 - 5 andares 23:16 - 23:16 - 22 andares 23:17 - 23:18 - 8 andares |
HeartRate |
bpm |
A cada um minuto |
6h11 - 55 bpm |
HeartRateVariabilityRmssd |
ms |
A cada um minuto |
6h11 - 23 ms |
RespiratoryRate |
respirações/minuto |
A cada um minuto |
23:14 - 23:15 - 60 respirações/minuto 23:16 - 23:16 - 62 respirações/minuto 23:17 - 23:18 - 64 respirações/minuto |
OxygenSaturation |
% |
A cada uma hora |
6:11 - 95,208% |
Gravar sessões
Os dados precisam ser gravados na Conexão Saúde no final do treino ou da sessão de sono.
Como prática recomendada, qualquer sessão de sono ou de exercício precisa ser gravada com
o dispositivo de gravação e os metadados apropriados, incluindo
RecordingMethod
.
No mínimo, o aplicativo precisa seguir as orientações na coluna "esperado" abaixo. Sempre que possível, siga as orientações "melhores".
Dados monitorados durante um exercício
Tipo de dado |
Unidade |
Esperado |
Até mais |
Exemplo |
Etapas |
passos |
A cada um minuto |
A cada 1 segundo |
23:14-23:15 - 5 etapas 23:16 - 23:17 - 22 etapas 23:17 - 23:18 - 8 etapas |
StepsCadence |
passos/min |
A cada um minuto |
A cada 1 segundo |
23:14-23:15 - 35 spm 23:16 - 23:17 - 37 spm 23:17 - 23:18 - 40 spm |
Impulsos na cadeira de rodas |
empurra |
A cada um minuto |
A cada 1 segundo |
23:14-23:15 - 5 envios 23:16 - 23:17 - 22 envios 23:17 - 23:18 - 8 pushes |
CyclingPedalingCadence |
rpm |
A cada um minuto |
A cada 1 segundo |
23:14-23:15 - 65 rpm 23:16 - 23:17 - 70 rpm 23:17 - 23:18 - 68 rpm |
Energia |
watts |
A cada um minuto |
A cada 1 segundo |
23:14-23:15 - 250 watts 23:16 - 23:17 - 255 watts 23:17 - 23:18 - 245 watts |
Velocidade |
km/min |
A cada um minuto |
A cada 1 segundo |
23:14-23:15 - 0,3 km/min 23:16 - 23:17 - 0,4 km/min 23:17 - 23:18 -0,4 km/min |
Distância |
km/m |
A cada um minuto |
A cada 1 segundo |
23:14-23:15 - 0,008 km 23:16 - 23:16 - 0,021 km 23:17 - 23:18 - 0,012 km |
ActiveCaloriesBurned |
Calorias |
A cada um minuto |
A cada 1 segundo |
23:14-23:15 - 20 calorias 23:16 - 23:17 - 20 calorias 23:17 - 23:18 - 25 calorias |
TotalCaloriesBurned |
Calorias |
A cada um minuto |
A cada 1 segundo |
23:14-23:15 - 36 calorias 23:16 - 23:17 - 36 calorias 23:17 - 23:18 - 41 calorias |
ElevationGained |
m |
A cada um minuto |
A cada 1 segundo |
20:36 - 20:37 - 3,048m 20:39 - 20:40 - 3,048m 23:23 - 23:24 - 9,144m |
ExerciseRoutes |
lat/lng/alt |
A cada 3 a 5 segundos |
A cada 1 segundo |
|
HeartRate |
bpm |
A cada um minuto |
A cada 1 segundo |
23:14-23:15 - 150 bpm 23:16 - 23:17 -152 bpm 23:17 - 23:18 - 155 bpm |
Dados monitorados durante o sono
Tipo de dado |
Unidade |
Amostras esperadas |
Exemplo |
Estágio do sono |
fase |
Período granular de tempo por estágio do sono |
23:46 - 23:50 - acordado 23:50 - 23:56 - sono leve 23:56 - 00:16 - sono profundo |
RestingHeartRate |
bpm |
Valor diário único (esperado pela manhã) |
6h11 - 60 bpm |
OxygenSaturation |
% |
Valor diário único (esperado pela manhã) |
6:11 - 95,208% |