Gravar dados

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 stepsRecord = StepsRecord(
    count = 120,
    startTime = START_TIME,
    endTime = END_TIME,
    startZoneOffset = START_ZONE_OFFSET,
    endZoneOffset = END_ZONE_OFFSET
)

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 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 = START_TIME,
    endTime = END_TIME,
    startZoneOffset = START_ZONE_OFFSET,
    endZoneOffset = END_ZONE_OFFSET
)

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 heartRateRecord = HeartRateRecord(
    startTime = START_TIME,
    startZoneOffset = START_ZONE_OFFSET,
    endTime = END_TIME,
    endZoneOffset = END_ZONE_OFFSET,
    // records 10 arbitrary data, to replace with actual data
    samples = List(10) { index ->
        HeartRateRecord.Sample(
            time = START_TIME + Duration.ofSeconds(index.toLong()),
            beatsPerMinute = 100 + index.toLong(),
        )
    }
)

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) {
    try {
        val stepsRecord = StepsRecord(
            count = 120,
            startTime = START_TIME,
            endTime = END_TIME,
            startZoneOffset = START_ZONE_OFFSET,
            endZoneOffset = END_ZONE_OFFSET
        )
        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)
        }

        client.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(
        // Assign parameters for this record
        metadata = Metadata(
            clientRecordId = cid
        )
    )
    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 sr = StepsRecord(
    count = count,
    startTime = startTime,
    startZoneOffset = startZoneOffset,
    endTime = endTime,
    endZoneOffset = endZoneOffset,
    metadata = Metadata(
        clientRecordId = cid,
        clientRecordVersion = version
    )
)

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 gravação de 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 dados novos e atualizados que tenham sido 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 no app Conexão Saúde, use a resolução adequada. O uso da resolução adequada ajuda a reduzir a carga de armazenamento, mantendo os dados consistentes e precisos. A resolução de dados abrange duas coisas:

  1. Frequência de gravações: com que frequência o aplicativo envia novos dados para a Conexão Saúde. Por exemplo, grave novos dados a cada 15 minutos.
  2. Granularidade dos dados gravados: com que frequência 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 aplicativo precisa gravar na Conexão Saúde pelo menos a cada 15 minutos ao longo do dia.

Tipo de dado

Unidade

Espera-se

Exemplo

Etapas

passos

A cada um minuto

23:14 - 23:15 - 5 passos

23:16 - 23:17 - 22 passos

23:17 - 23:18 - 8 passos

PassosCadência

passos/min

A cada um minuto

23:14 - 23:15 - 5 ppm

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 impulsos

23:16 - 23:17 - 22 impulsos

23:17 - 23:18 - 8 impulsos

Calorias queimadas

Calorias

A cada 15 minutos

23:15 - 23:30 - 2 calorias

23:30 - 23:45 - 25 calorias

23:45 - 00:00 - 5 calorias

Total de calorias queimadas

kcal

A cada 15 minutos

23:15 - 23:30 - 16 kcal

23:30 - 23:45 - 16 kcal

23:45 - 00:00 - 16 kcal

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

Ganho de elevação

m

A cada um minuto

20:36 - 20:37 - 3,048 m

20:39 - 20:40 - 3,048 m

23:23 - 23:24 - 9,144 m

Andares subidos

andares

A cada um minuto

23:14 - 23:15 - 5 andares

23:16 - 23:16 - 22 andares

23:17 - 23:18 - 8 andares

Frequência cardíaca

bpm

A cada um minuto

6h11 - 55 bpm

HeartRateVariabilityRmssd

ms

A cada um minuto

6:11 – 23 ms

Frequência respiratória

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

Saturação de oxigênio

%

A cada uma hora

6:11 – 95,208%

Gravar sessões

Os dados precisam ser gravados na Conexão Saúde ao final do treino ou da sessão de sono.

Como prática recomendada, qualquer sessão de sono ou de exercícios precisa ser gravada com o dispositivo de gravação e os metadados apropriados, incluindo RecordingMethod.

No mínimo, seu aplicativo deve seguir as orientações da coluna "esperado" abaixo. Sempre que possível, siga as "melhores" orientações.

Dados monitorados durante um exercício

Tipo de dado

Unidade

Espera-se

Até mais

Exemplo

Etapas

passos

A cada um minuto

A cada 1 segundo

23:14-23:15 - 5 passos

23:16 - 23:17 - 22 passos

23:17 - 23:18 - 8 passos

PassosCadência

passos/min

A cada um minuto

A cada 1 segundo

23:14-23:15 - 35 spm

23:16 - 23:17 - 37 ppm

23:17 - 23:18 - 40 ppm

Impulsos na cadeira de rodas

empurra

A cada um minuto

A cada 1 segundo

23:14-23:15 - 5 impulsos

23:16 - 23:17 - 22 impulsos

23:17 - 23:18 - 8 impulsos

CiclismoPedalingCadence

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

Potência

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

Calorias queimadas

kcal

A cada um minuto

A cada 1 segundo

23:14-23:15 - 20 kcal

23:16 - 23:17 - 20 kcal

23:17 - 23:18 - 25 kcal

Total de calorias queimadas

kcal

A cada um minuto

A cada 1 segundo

23:14-23:15 - 36 kcal

23:16 - 23:17 - 36 kcal

23:17 - 23:18 - 41 kcal

Ganho de elevação

m

A cada um minuto

A cada 1 segundo

20:36 - 20:37 - 3,048 m

20:39 - 20:40 - 3,048 m

23:23 - 23:24 - 9,144 m

Trajetos de exercícios

lat/lng/alt

A cada 3 a 5 segundos

A cada 1 segundo

Frequência cardíaca

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

Preparação do sono

etapa

Período granular por estágio do sono

23:46 - 23:50 - acordado

23:50 - 23:56 - sono leve

23:56 - 00:16 - sono profundo

Frequência Cardíaca em repouso

bpm

Valor diário único (previsto nas primeiras horas da manhã)

6h11 - 60 bpm

Saturação de oxigênio

%

Valor diário único (previsto nas primeiras horas da manhã)

6:11 – 95,208%