Guia de migração do SDK do Samsung Health para Android para o SDK de dados do Samsung Health

 

Guia de migração do SDK do Samsung Health para Android para o SDK de dados do Samsung Health

Após o lançamento do Samsung Health Data SDK, o Samsung Health SDK para Android será descontinuado em alguns meses. Após essa transição, os aplicativos parceiros que atualmente utilizam o Samsung Health SDK para Android precisarão migrar para o Samsung Health Data SDK.

Benefícios da migração para o SDK de dados do Samsung Health

O Samsung Health Data SDK permite que aplicativos acessem dados de saúde do app Samsung Health em smartphones Android. Além de oferecer a mesma funcionalidade do Samsung Health SDK para Android, ele também proporciona diversas vantagens adicionais. Comparado ao Samsung Health SDK para Android, o Samsung Health Data SDK aplica a lógica de serviço exibida nos rastreadores do app Samsung Health e fornece dados mais específicos do app. Isso permite que os provedores de serviços de saúde compreendam melhor os indicadores de saúde dos usuários.

Por exemplo, para obter os mesmos dados de contagem de passos exibidos no aplicativo Samsung Health ao usar o SDK do Samsung Health para Android, você precisa:

  • Defina o tipo de dados como StepDailyTrend.
  • Defina os filtros para ambos:
    • O período de tempo
    • TIPO_FONTE_TODOS

Isso garante que você receba os mesmos dados de contagem de passos exibidos no aplicativo Samsung Health.

Código do SDK Samsung Health para Android


val healthDataResolver = HealthDataResolver(healthDataStore, null)

val date = LocalDate
    .now()
    .atStartOfDay()
    .toInstant(ZoneOffset.UTC)
    .toEpochMilli()

val filter = Filter.and(
    Filter.eq(StepDailyTrend.DAY_TIME, date),
    Filter.eq(StepDailyTrend.SOURCE_TYPE, StepDailyTrend.SOURCE_TYPE_ALL)
)

val stepsRequest = HealthDataResolver.ReadRequest.Builder()
    .setDataType(StepDailyTrend.HEALTH_DATA_TYPE)
    .setFilter(filter)
    .build()

Com o SDK de Dados do Samsung Health, você pode simplificar uma solicitação de dados utilizando o agregador total e aplicando apenas um filtro de tempo. Essa solicitação de dados permite recuperar a contagem total diária de passos exibida no aplicativo Samsung Health sem se preocupar com a possível falha ao definir o tipo de origem como "todos".

Código do SDK de dados de saúde da Samsung


val startTime = LocalDate.now().atStartOfDay()
val endTime = LocalDateTime.now()
val localTimeFilter = LocalTimeFilter.of(startTime, endTime)
val stepsRequest = DataType.StepsType.TOTAL.requestBuilder
    .setLocalTimeFilter(localTimeFilter)
    .build()

O SDK de dados de saúde da Samsung fornece vários tipos de dados de metas, como metas de passos, metas de sono e metas de calorias ativas queimadas. Os tipos de dados de metas ajudam a fornecer orientações adequadas aos usuários.

O SDK de Dados do Samsung Health pode ler, gravar, atualizar e excluir dados de saúde no aplicativo Samsung Health. Ele também pode recuperar dados associados a informações específicas. Por exemplo, o aplicativo Samsung Health mede continuamente a oxigenação sanguínea e a temperatura da pele durante o sono. O SDK de Dados do Samsung Health permite recuperar facilmente os dados de oxigenação sanguínea e temperatura da pele relacionados a essas informações específicas do sono.

O SDK do Samsung Health para Android permanecerá operacional por pelo menos 2 anos após sua descontinuação. Após esse período, este SDK será removido, portanto, recomendamos que você atualize seu aplicativo para usar o SDK de Dados do Samsung Health.

Processo de desenvolvimento

Anteriormente, o SDK do Samsung Health para Android exigia que os desenvolvedores enviassem uma solicitação de parceria para obter acesso, que precisava ser aprovado antes do uso. Agora, com o SDK de Dados do Samsung Health, você pode baixar e usar o SDK no modo de desenvolvedor sem precisar enviar uma solicitação de parceria. Para maior conveniência dos desenvolvedores, o SDK de Dados do Samsung Health aprimorou a funcionalidade do modo de desenvolvedor. Se você precisar apenas ler os dados do aplicativo Samsung Health, pode ativar o modo de desenvolvedor e prosseguir com o desenvolvimento e os testes sem precisar da solicitação de parceria. Se você quiser testar a gravação de dados no aplicativo Samsung Health usando o SDK de Dados do Samsung Health ou distribuir seu aplicativo, será necessário enviar uma solicitação de parceria.

Para ver o processo detalhado de desenvolvimento de um aplicativo com o SDK de dados do Samsung Health, consulte a página do processo .

Verificando os tipos de dados suportados pelo SDK de dados do Samsung Health

Antes de começar a usar o Samsung Health Data SDK, compare-o com o Samsung Health SDK para Android e seus tipos de dados existentes para determinar se os tipos de dados que você deseja usar em seu aplicativo são compatíveis e quais dados adicionais podem ser utilizados.

Categoria

Tipo de dados do SDK Samsung Health para Android

Tipo de dados correspondente no SDK de dados do Samsung Health

Atividade

Constantes de saúde. Exercício

Tipo de exercício

Constantes de saúde.Andares subidos

Tipo de andares escalados

HealthConstants.StepDailyTrend (somente leitura)

Tipo de passos (somente leitura)

HealthConstants.StepCount (somente leitura)

Não fornecido

Não fornecido

Tipo de Meta de Etapa (somente leitura)

Não fornecido

Tipo de resumo de atividade (somente leitura)

Não fornecido

Tipo de Meta de CaloriasQueimadasAtivas (somente leitura)

Não fornecido

Tipo de meta de tempo ativo (somente leitura)

Ingestão de alimentos

Constantes de Saúde.Nutrição

Tipo de Nutrição

Não fornecido

Tipo de Meta Nutricional (somente leitura)

Constantes de saúde. Ingestão de água.

Tipo de ingestão de água

Não fornecido

Tipo de meta de ingestão de água (somente leitura)

Descansar

Constantes de saúde.Sono

Tipo de sono

Constantes de saúde.Estágio do sono

Não fornecido

Não fornecido

Tipo de objetivo de sono (somente leitura)

Assistência médica

Constantes de saúde. Glicemia

Tipo de glicose no sangue

Constantes de saúde.Pressão arterial

Tipo de pressão arterial

Constantes de saúde.Temperatura corporal

Temperatura corporal

Constantes de saúde. Frequência cardíaca

Tipo de Frequência Cardíaca

HealthConstants.OxygenSaturationType

Tipo de oxigênio no sangue

Constantes de saúde.Peso

Tipo de composição corporal

Não fornecido

Temperatura da pele

Pontuação

Não fornecido

Tipo de pontuação de energia (somente leitura)

Perfil do usuário

Perfil de usuário de saúde (somente leitura)

Tipo de dados do perfil do usuário (somente leitura)

Verificando a experiência do usuário

Para acessar dados de saúde do Samsung Health Data SDK, você precisa obter permissões de dados e o consentimento do usuário. Para isso, siga o mesmo processo do Samsung Health SDK para Android. Você pode solicitar permissões de dados em Solicitação de permissões de dados.

Observação:
Ao usar os dois SDKs em conjunto, as permissões de dados de cada SDK são exibidas ao usuário, o que pode resultar em uma interface de usuário inconveniente. Portanto, recomendamos o uso do SDK de Dados do Samsung Health.

Permissões de dados do SDK Samsung Health para Android

Permissões de dados do SDK de dados do Samsung Health

Começando

1) Baixe o SDK de Dados do Samsung Health

Acesse a página do Samsung Health Data SDK para fazer o download do Samsung Health Data SDK.

2) Ativar o modo de desenvolvedor do SDK de dados de saúde da Samsung

Se você precisar apenas ler dados do aplicativo Samsung Health, pode ativar o modo de desenvolvedor sem precisar enviar uma solicitação adicional de parceiro. Consulte as instruções do modo de desenvolvedor para saber como ativá-lo.

Se você deseja gravar dados no aplicativo Samsung Health, precisa enviar uma solicitação de parceria .

3) Importando a biblioteca do SDK de dados do Samsung Health

Remova a biblioteca do SDK Samsung Health para Android do seu projeto de aplicativo.

  • dados-saúde-samsung-abcaar

E adicione a biblioteca do SDK de dados do Samsung Health à pasta app/libs.

  • samsung-health-data-api-abcaar (Observe que 'abc' é a versão do SDK.)

4) Atualizar manifesto do aplicativo

Se o manifesto do seu aplicativo tiver oElemento do aplicativo Samsung Health, por favor, remova-o.

Manifesto do aplicativo - Remova oElemento para o SDK Samsung Health para Android

    <manifest ... >
    <queries>
        <package android:name="com.sec.android.app.shealth" />
    </queries>

</manifest>

Se o manifesto do aplicativo tiver oRemova as linhas de código relacionadas às permissões de dados de saúde do SDK Samsung Health para Android.

Manifesto do aplicativo - Remover as declarações de permissão de dados para o SDK do Samsung Health para Android

<manifest ... >

    <application ... >
        <meta-data android:name="com.samsung.android.health.permission.read"
            android:value="com.samsung.health.exercise;com.samsung.shealth.step_daily_trend"/>
        <meta-data android:name="com.samsung.android.health.permission.write"
    </application>

</manifest>

5) Configurações do Gradle

No arquivo app/build.gradle, remova a dependência do SDK do Samsung Health para Android.

app/build.gradle - Remova a dependência do SDK do Samsung Health para Android

dependencies {
    implementation files('src/main/libs/samsung-health-data-1.5.1.aar')
}

Adicione a dependência para o SDK de dados de saúde da Samsung.

app/build.gradle - Adicione a dependência para o SDK de Dados do Samsung Health

dependencies {
    implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.aar"))))
}

Adicione a biblioteca gson como dependência.

app/build.gradle - Adicione a dependência para o SDK de Dados do Samsung Health

dependencies {
    implementation "com.google.code.gson:gson:2.9.0"
}

E aplique o plugin kotlin-parcelize ao arquivo app/build.gradle.

app/build.gradle - Adicione o plugin para o SDK de Dados do Samsung Health

plugins {
    id("kotlin-parcelize")
}

6) Conectando-se ao Samsung Health

Para acessar dados de saúde no aplicativo Samsung Health, você precisa conectar o SDK ao aplicativo Samsung Health. Se o aplicativo Samsung Health não estiver instalado ou se você tiver uma versão anterior à versão compatível, ocorrerá uma exceção após a solicitação de conexão. Se for uma exceção solucionável, chame a API resolve() para resolvê-la.

Abaixo, segue um exemplo de trecho de código ao usar o SDK do Samsung Health para Android.

Conectando-se ao Samsung Health com o SDK do Samsung Health para Android

lateinit var healthDataStore: HealthDataStore

fun connect(activity: Activity) {
    healthDataStore = HealthDataStore(context, object : HealthDataStore.ConnectionListener {
        override fun onConnected() {
            Log.i(APP_TAG, "Health data service is connected")
        }

        override fun onConnectionFailed(error: HealthConnectionErrorResult) {
            if (error.hasResolution()) {
                error.resolve(activity)
            } else {
                Log.i(APP_TAG, "Health data service is not available")
            }
        }

        override fun onDisconnected() {
            Log.i(APP_TAG, "Health data service is disconnected")
        }
    })

    runCatching {
        healthDataStore.connectService()
    }.onFailure { error ->
        error.message?.let { Log.i(APP_TAG, it) }
    }
}

Para conectar-se ao aplicativo Samsung Health usando o SDK de dados do Samsung Health, você pode fazer isso conforme mostrado no código abaixo.

Conectando-se ao Samsung Health com o SDK de dados do Samsung Health

lateinit var healthDataStore: HealthDataStore

fun connect(activity: Activity) {
    runCatching {
        healthDataStore = HealthDataService.getStore(context)
    }.onSuccess {
        Log.i(APP_TAG, "Health data service is connected")
    }.onFailure { error ->
        if (error is ResolvablePlatformException && error.hasResolution) {
            error.resolve(activity)
        }
        // handle other types of HealthDataException
        error.message?.let { Log.i(APP_TAG, it) }
    }
}

7) Solicitar permissões de dados

Após conectar-se com sucesso ao aplicativo Samsung Health, você precisa solicitar permissão de acesso aos dados de saúde do usuário. Ao obter o consentimento explícito do usuário, você poderá acessar os dados de saúde.

Antes de solicitar permissão para acesso aos dados, verifique se o usuário já a concedeu. Caso a permissão necessária ainda não tenha sido obtida, prossiga com a solicitação.

O código a seguir é um exemplo de como solicitar permissões de dados para ler a contagem diária de passos, informações nutricionais e dados do perfil do usuário ao usar o SDK do Samsung Health para Android.

Solicitar permissão de dados com o SDK do Samsung Health para Android

private val permissionListener: HealthResultHolder.ResultListener<PermissionResult> =
    HealthResultHolder.ResultListener<PermissionResult> { result ->
        if (result.resultMap.values.contains(FALSE)) {
            Log.i(APP_TAG, "Not all required permissions granted")
        } else {
            Log.i(APP_TAG, "All required permissions granted")
        }
    }

fun requestPermissions(activity: Activity, healthDataStore: HealthDataStore) {
    val permissionSet = setOf(
        PermissionKey(
            StepDailyTrend.HEALTH_DATA_TYPE,
            HealthPermissionManager.PermissionType.READ
        ),
        PermissionKey(
            Nutrition.HEALTH_DATA_TYPE,
            HealthPermissionManager.PermissionType.READ
        ),
        PermissionKey(
            HealthConstants.USER_PROFILE_DATA_TYPE,
            HealthPermissionManager.PermissionType.READ
        )
    )
    val permissionManager = HealthPermissionManager(healthDataStore)

    runCatching {
        val grantedPermissions = permissionManager.isPermissionAcquired(permissionSet)

        if (grantedPermissions.values.all { it }) {
            Log.i(APP_TAG, "All required permissions granted")
        } else {
            Log.i(APP_TAG, "Not all required permissions granted")
            permissionManager.requestPermissions(permissionSet, activity)
                .setResultListener(permissionListener)
        }
    }.onFailure { error ->
        error.message?.let { Log.i(APP_TAG, it) }
    }
}

Ao executar o código acima, a seguinte captura de tela mostra a janela pop-up de permissão de dados exibida ao usuário.

Ao usar o SDK de dados do Samsung Health, você pode fazer o seguinte:

Solicitação de permissão de dados com o SDK de dados do Samsung Health

suspend fun requestPermissions(healthDataStore: HealthDataStore, activity: Activity) {
    val permissionSet = setOf(
        Permission.of(DataTypes.STEPS, AccessType.READ),
        Permission.of(DataTypes.NUTRITION, AccessType.READ),
        Permission.of(DataTypes.USER_PROFILE, AccessType.READ)
    )
    val grantedPermissions = healthDataStore.getGrantedPermissions(permissionSet)

    if (grantedPermissions.containsAll(permissionSet)) {
        Log.i(APP_TAG, "All required permissions granted")
    } else {
        healthDataStore.requestPermissions(permissionSet, activity)
    }
}

Ao solicitar permissões de dados com o Samsung Health Data SDK, a seguinte captura de tela será exibida ao usuário.

8) Solicitação de Dados

Solicitação assíncrona

As operações assíncronas permitem que o aplicativo continue processando outras tarefas sem esperar que a tarefa atual seja concluída. Isso evita que a thread principal seja bloqueada. Melhora a experiência do usuário, mantendo o aplicativo interativo durante tarefas de longa duração e oferecendo suporte ao gerenciamento eficiente de operações simultâneas.

Abaixo, você pode ver um exemplo de código de como usar o SDK do Samsung Health para Android para fazer uma solicitação assíncrona.

Solicitação assíncrona ao usar o SDK Samsung Health para Android

fun readStepsAsync(healthDataStore: HealthDataStore) {
    val healthDataResolver = HealthDataResolver(healthDataStore, null)

    val date = LocalDate
        .now()
        .atStartOfDay()
        .toInstant(ZoneOffset.UTC)
        .toEpochMilli()

    val filter = Filter.and(
        Filter.eq(StepDailyTrend.DAY_TIME, date),
        Filter.eq(StepDailyTrend.SOURCE_TYPE, StepDailyTrend.SOURCE_TYPE_ALL)
    )

    val stepsRequest = HealthDataResolver.ReadRequest.Builder()
        .setDataType(StepDailyTrend.HEALTH_DATA_TYPE)
        .setFilter(filter)
        .build()

    try {
        healthDataResolver.read(stepsRequest).setResultListener { result ->
            try {
                val iterator = result.iterator()

                if (iterator.hasNext()) {
                    val healthData = iterator.next()
                    val stepCount = healthData.getInt(StepDailyTrend.COUNT)
                    Log.i(MainActivity.APP_TAG, "Step count: $stepCount")
                }
            } finally {
                result.close()
            }
        }
    } catch (exception: Exception) {
        exception.message?.let { Log.i(MainActivity.APP_TAG, it) }
    }
}

Ao usar o SDK de dados do Samsung Health, você pode realizar a mesma operação da seguinte forma. Use uma API que inclua Async.

Solicitação assíncrona com o SDK de dados do Samsung Health

fun readStepsAsync(healthDataStore: HealthDataStore, activity: Activity) {
    val startTime = LocalDate.now().atStartOfDay()
    val endTime = LocalDateTime.now()
    val localTimeFilter = LocalTimeFilter.of(startTime, endTime)
    val stepsRequest = DataType.StepsType.TOTAL.requestBuilder
        .setLocalTimeFilter(localTimeFilter)
        .build()

    healthDataStore.aggregateDataAsync(stepsRequest).setCallback(
        Looper.getMainLooper(),
        { result ->
            val stepCount = result.dataList.first().value
            Log.i(MainActivity.APP_TAG, "Step count: $stepCount")
        }) { error ->
        if (error is ResolvablePlatformException && error.hasResolution) {
            error.resolve(activity)
        }
    }
}

Solicitação síncrona

As operações síncronas executam tarefas sequencialmente, exigindo que o aplicativo espere a conclusão da tarefa atual antes de prosseguir para a próxima. Embora essa abordagem seja simples de implementar e garanta um fluxo de execução previsível, ela pode bloquear a thread principal. Isso torna as operações síncronas mais adequadas para tarefas simples e curtas do que para processos complexos ou concorrentes.

Para realizar operações síncronas ao usar o SDK do Samsung Health para Android, você pode usar a API await().

Solicitação síncrona com o SDK do Samsung Health para Android

fun readStepsSync(healthDataStore: HealthDataStore) {
    val healthDataResolver = HealthDataResolver(healthDataStore, null)

    val date = LocalDate
        .now()
        .atStartOfDay()
        .toInstant(ZoneOffset.UTC)
        .toEpochMilli()

    val filter = Filter.and(
        Filter.eq(StepDailyTrend.DAY_TIME, date),
        Filter.eq(StepDailyTrend.SOURCE_TYPE, StepDailyTrend.SOURCE_TYPE_ALL)
    )

    val stepsRequest = HealthDataResolver.ReadRequest.Builder()
        .setDataType(StepDailyTrend.HEALTH_DATA_TYPE)
        .setFilter(filter)
        .build()

    try {
        healthDataResolver.read(stepsRequest).await().run {
            try {
                val iterator = iterator()

                if (iterator.hasNext()) {
                    val healthData = iterator.next()
                    val stepCount = healthData.getInt(StepDailyTrend.COUNT)
                    Log.i(MainActivity.APP_TAG, "Step count: $stepCount")
                }
            } finally {
                close()
            }
        }
    } catch (exception: Exception) {
        exception.message?.let { Log.i(MainActivity.APP_TAG, it) }
    }
}

Para operações síncronas envolvendo o SDK de dados do Samsung Health, utilize a seguinte abordagem.

Solicitação síncrona com o SDK de dados do Samsung Health

suspend fun readStepsSync(healthDataStore: HealthDataStore) {
    val startTime = LocalDate.now().atStartOfDay()
    val endTime = LocalDateTime.now()
    val stepsRequest = DataType.StepsType.TOTAL.requestBuilder
        .setLocalTimeFilterWithGroup(
            LocalTimeFilter.Companion.of(startTime, endTime),
            LocalTimeGroup.of(LocalTimeGroupUnit.HOURLY, 1)
        )
        .build()

    try {
        val readResult = healthDataStore.aggregateData(stepsRequest)
        val stepCount = readResult.dataList.first().value
        Log.i(MainActivity.APP_TAG, "Step count: $stepCount")
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

9) Implementação e teste do aplicativo

O acesso aos dados de saúde é necessário para que o aplicativo realize testes e garanta seu funcionamento correto. Para obter informações detalhadas sobre como acessar os dados de saúde, consulte a seção Acesso aos dados de saúde.

10) Solicite a parceria antes de distribuir seu aplicativo.

O modo de desenvolvedor do Samsung Health Data SDK é um recurso fornecido apenas para fins de desenvolvimento. Para garantir que um aplicativo que utiliza o Samsung Health Data SDK funcione corretamente sem a necessidade de ativar o modo de desenvolvedor, é preciso enviar uma solicitação de parceria pelo site de desenvolvedores antes de distribuir o aplicativo nas lojas de aplicativos. Após a aprovação do aplicativo parceiro, as informações detalhadas do aplicativo serão registradas no sistema da Samsung.

Acesso a dados de saúde

Passos

O Samsung Health mede os passos dados de smartphones com o aplicativo Samsung Health instalado e de dispositivos vestíveis Galaxy conectados, como o Galaxy Watch, Galaxy Fit ou Galaxy Ring. Ele agrega e elimina dados duplicados para fornecer a contagem diária de passos. Os dados de contagem de passos são somente leitura.

Os tipos de dados correspondentes às etapas no Samsung Health SDK para Android e no Samsung Health Data SDK são os seguintes:

SDK Samsung Health para Android

SDK de dados de saúde da Samsung

HealthConstants.StepDailyTrend (somente leitura)
HealthConstants.StepCount (somente leitura)

Tipo de passos (somente leitura)

Aqui está um exemplo de código que lê a contagem total de passos de hoje ao usar o SDK do Samsung Health para Android.

Veja o total de passos dados hoje com o SDK do Samsung Health para Android.

fun readTodayStepCountData(healthDataStore: HealthDataStore) {
    val startTime = LocalDate
        .now()
        .atStartOfDay()
        .toInstant(ZoneOffset.UTC)
        .toEpochMilli()

    val filter = Filter.and(
        Filter.eq(StepDailyTrend.DAY_TIME, startTime),
        Filter.eq(StepDailyTrend.SOURCE_TYPE, StepDailyTrend.SOURCE_TYPE_ALL)
    )

    val healthDataResolver = HealthDataResolver(healthDataStore, null)

    val request = HealthDataResolver.ReadRequest.Builder()
        .setDataType(StepDailyTrend.HEALTH_DATA_TYPE)
        .setFilter(filter)
        .build()

    try {
        healthDataResolver.read(request).setResultListener { result ->
            try {
                val iterator = result.iterator()

                if (iterator.hasNext()) {
                    val healthData = iterator.next()
                    val totalCount = healthData.getInt(StepDailyTrend.COUNT)
                    Log.i(MainActivity.APP_TAG, "Today steps count: $totalCount")
                } else {
                    Log.i(MainActivity.APP_TAG, "No step data available")

O código para obter a contagem total de passos de hoje ao usar o SDK de dados do Samsung Health é o seguinte.

Leia o total de passos dados hoje com o SDK de dados do Samsung Health.

suspend fun readTodayStepCountData(healthDataStore: HealthDataStore) {
    val startTime = LocalDate.now().atStartOfDay()
    val endTime = LocalDateTime.now()
    val readRequest = DataType.StepsType.TOTAL.requestBuilder
        .setLocalTimeFilter(LocalTimeFilter.of(startTime, endTime))
        .build()

    try {
        val readResult = healthDataStore.aggregateData(readRequest)
        val data = readResult.dataList.first()
        val totalCount = data.value
        Log.i(MainActivity.APP_TAG, "Today steps count: $totalCount")
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

Exercício

O aplicativo Samsung Health registra os dados de exercícios do usuário. Quando o usuário usa um Galaxy Watch, Galaxy Fit ou Galaxy Ring e registra dados de exercícios, o aplicativo registra sua frequência cardíaca, velocidade do exercício e distância.

Os tipos de dados de exercícios correspondentes no Samsung Health SDK para Android e no Samsung Health Data SDK são os seguintes:

SDK Samsung Health para Android

SDK de dados de saúde da Samsung

Constantes de saúde. Exercício

Tipo de exercício

Segue abaixo um exemplo de código para ler os dados de exercícios de hoje usando o SDK do Samsung Health para Android.

Leitura de dados de exercícios com o SDK Samsung Health para Android

fun readTodayExercise(healthDataStore: HealthDataStore) {
    val startTime = LocalDate.now().atStartOfDay().toInstant(ZoneOffset.UTC).toEpochMilli()
    val endTime =
        LocalDate.now().plusDays(1).atStartOfDay().toInstant(ZoneOffset.UTC).toEpochMilli()

    val healthDataResolver = HealthDataResolver(healthDataStore, null)

    val readRequest = HealthDataResolver.ReadRequest.Builder()
        .setDataType(Exercise.HEALTH_DATA_TYPE)
        .setLocalTimeRange(
            FloorsClimbed.START_TIME,
            FloorsClimbed.TIME_OFFSET,
            startTime,
            endTime
        )
        .build()

    try {
        healthDataResolver.read(readRequest).setResultListener { result ->
            try {
                val iterator = result.iterator()

                iterator.forEach { healthData ->
                    val exerciseType = healthData.getInt(Exercise.EXERCISE_TYPE)
                    val duration = healthData.getLong(Exercise.DURATION)
                    val calories = healthData.getFloat(Exercise.CALORIE)
                    Log.i(
                        MainActivity.APP_TAG,
                        "Exercise type: $exerciseType, duration: $duration, calories: $calories"
                    )
                }
            } finally {
                result.close()
            }
        }
    } catch (exception: Exception) {
        exception.message?.let { Log.i(MainActivity.APP_TAG, it) }
    }
}

Segue abaixo um exemplo de código para leitura dos dados de exercícios de hoje usando o SDK de dados do Samsung Health.

Leitura de dados de exercícios com o SDK de dados do Samsung Health

suspend fun readTodayExercise(healthDataStore: HealthDataStore) {
    val startTime = LocalDate.now().atStartOfDay()
    val endTime = LocalDateTime.now()
    val readRequest = DataTypes.EXERCISE.readDataRequestBuilder
        .setLocalTimeFilter(LocalTimeFilter.of(startTime, endTime))
        .build()

    try {
        val readResult = healthDataStore.readData(readRequest)
        val dataPoints = readResult.dataList

        if (dataPoints.isEmpty()) {
            Log.i(MainActivity.APP_TAG, "No exercises today")
            return
        }

        dataPoints.forEach { dataPoint ->
            val exerciseType = dataPoint.getValue(DataType.ExerciseType.EXERCISE_TYPE)
            val sessions = dataPoint.getValue(DataType.ExerciseType.SESSIONS)

            sessions?.forEach { session ->
                val exerciseSessionType = session.exerciseType
                val exerciseSessionDuration = session.duration
                val exerciseSessionCalories = session.calories
                Log.i(
                    MainActivity.APP_TAG,
                    "Exercise type: $exerciseType, session type: $exerciseSessionType, duration: $exerciseSessionDuration, calories: $exerciseSessionCalories"
                )
            }
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

Segue um exemplo de código para gravar dados de exercícios ao usar o SDK do Samsung Health para Android.

Gravação de dados de exercícios de corrida com o SDK Samsung Health para Android

fun insertRunningExercise(healthDataStore: HealthDataStore) {
    val fiveMinutesAsSeconds = 300L
    val exerciseType = 1002
    val calories = 73f
    val distance = 1000f
    val deviceId = HealthDeviceManager(healthDataStore).localDevice.uuid
    val startTime = Instant.now().minusSeconds(fiveMinutesAsSeconds)
    val endTime = Instant.now()
    val timeOffset = TimeZone.getDefault().getOffset(endTime.toEpochMilli()).toLong()
    val duration = Duration.between(startTime, endTime)
    val healthDataResolver = HealthDataResolver(healthDataStore, null)

    val liveData = createLiveData(
        listOf(
            ExerciseLiveData(
                start_time = startTime.toEpochMilli(),
                heart_rate = 144f,
                speed = 1.6f
            ),
            ExerciseLiveData(
                start_time = startTime.plusSeconds(30).toEpochMilli(),
                heart_rate = 146f,
                speed = 1.8f
            ),
            ExerciseLiveData(
                start_time = startTime.plusSeconds(60).toEpochMilli(),
                heart_rate = 146f,
                speed = 1.9f
            ),
            ExerciseLiveData(
                start_time = startTime.plusSeconds(90).toEpochMilli(),
                heart_rate = 152f,
                speed = 2f
            ),
            ExerciseLiveData(
                start_time = startTime.plusSeconds(120).toEpochMilli(),
                heart_rate = 154f,
                speed = 2.1f
            ),
            ExerciseLiveData(
                start_time = startTime.plusSeconds(150).toEpochMilli(),
                heart_rate = 161f,
                speed = 2.2f
            ),
            ExerciseLiveData(
                start_time = startTime.plusSeconds(180).toEpochMilli(),
                heart_rate = 159f,
                speed = 2.1f
            ),
            ExerciseLiveData(
                start_time = startTime.plusSeconds(210).toEpochMilli(),
                heart_rate = 160f,
                speed = 2.2f
            ),
            ExerciseLiveData(
                start_time = startTime.plusSeconds(240).toEpochMilli(),
                heart_rate = 159f,
                speed = 2.1f
            ),
            ExerciseLiveData(
                start_time = startTime.plusSeconds(270).toEpochMilli(),
                heart_rate = 161f,
                speed = 2.2f
            ),
            ExerciseLiveData(
                start_time = startTime.plusSeconds(300).toEpochMilli(),
                heart_rate = 160f,
                speed = 2f
            )
        )
    )

    val healthData = HealthData().apply {
        sourceDevice = deviceId
        putLong(Exercise.START_TIME, startTime.toEpochMilli())
        putLong(Exercise.END_TIME, endTime.toEpochMilli())
        putLong(Exercise.TIME_OFFSET, timeOffset)
        putInt(Exercise.EXERCISE_TYPE, exerciseType)
        putLong(Exercise.DURATION, duration.toMillis())
        putFloat(Exercise.CALORIE, calories)
        putFloat(Exercise.DISTANCE, distance)
        putBlob(Exercise.LIVE_DATA, liveData)
    }

    val insertRequest = HealthDataResolver.InsertRequest.Builder()
        .setDataType(Exercise.HEALTH_DATA_TYPE)
        .build()

    insertRequest.addHealthData(healthData)

    try {
        val result = healthDataResolver.insert(insertRequest).await()

        if (result.status == STATUS_SUCCESSFUL) {
            Log.i(
                MainActivity.APP_TAG,
                "Inserted running exercise. Count of data: ${result.count}"
            )
        } else {
            Log.i(MainActivity.APP_TAG, "Inserting failed")
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

private fun createLiveData(liveDataList: List<ExerciseLiveData>): ByteArray {
    val zip = HealthDataUtil.getJsonBlob(liveDataList)

    return zip
}

data class ExerciseLiveData(
    val start_time: Long,
    val heart_rate: Float,
    val speed: Float
)

O código de exemplo para gravar dados de exercícios usando o SDK de dados do Samsung Health é o seguinte. É possível gravar dados de uma sessão de exercícios.

Gravação de dados de exercícios de corrida com o SDK de dados do Samsung Health

suspend fun insertRunningExercise(healthDataStore: HealthDataStore) {
    val fiveMinutesAsSeconds = 300L
    val calories = 73f
    val distance = 1000f
    val startTime = Instant.now().minusSeconds(fiveMinutesAsSeconds)
    val endTime = Instant.now()
    val duration = Duration.between(startTime, endTime)

    val exerciseLog = listOf(
        ExerciseLog.of(
            timestamp = startTime,
            heartRate = 144f,
            speed = 1.6f,
            cadence = null,
            count = null,
            power = null
        ),
        ExerciseLog.of(
            timestamp = startTime.plusSeconds(30),
            heartRate = 146f,
            speed = 1.8f,
            cadence = null,
            count = null,
            power = null
        ),
        ExerciseLog.of(
            timestamp = startTime.plusSeconds(60),
            heartRate = 146f,
            speed = 1.9f,
            cadence = null,
            count = null,
            power = null
        ),
        ExerciseLog.of(
            timestamp = startTime.plusSeconds(90),
            heartRate = 152f,
            speed = 2f,
            cadence = null,
            count = null,
            power = null
        ),
        ExerciseLog.of(
            timestamp = startTime.plusSeconds(120),
            heartRate = 154f,
            speed = 2.1f,
            cadence = null,
            count = null,
            power = null
        ),
        ExerciseLog.of(
            timestamp = startTime.plusSeconds(150),
            heartRate = 161f,
            speed = 2.2f,
            cadence = null,
            count = null,
            power = null
        ),
        ExerciseLog.of(
            timestamp = startTime.plusSeconds(180),
            heartRate = 159f,
            speed = 2.1f,
            cadence = null,
            count = null,
            power = null
        ),
        ExerciseLog.of(
            timestamp = startTime.plusSeconds(210),
            heartRate = 160f,
            speed = 2.2f,
            cadence = null,
            count = null,
            power = null
        ),
        ExerciseLog.of(
            timestamp = startTime.plusSeconds(240),
            heartRate = 159f,
            speed = 2.1f,
            cadence = null,
            count = null,
            power = null
        ),
        ExerciseLog.of(
            timestamp = startTime.plusSeconds(270),
            heartRate = 161f,
            speed = 2.2f,
            cadence = null,
            count = null,
            power = null
        ),
        ExerciseLog.of(
            timestamp = startTime.plusSeconds(300),
            heartRate = 160f,
            speed = 2f,
            cadence = null,
            count = null,
            power = null
        )
    )

    try {
        val session = ExerciseSession.builder()
            .setStartTime(startTime)
            .setEndTime(endTime)
            .setExerciseType(DataType.ExerciseType.PredefinedExerciseType.RUNNING)
            .setDuration(duration)
            .setCalories(calories)
            .setDistance(distance)
            .setLog(exerciseLog)
            .build()

        val healthDataPoint = HealthDataPoint.builder()
            .setStartTime(startTime)
            .setEndTime(endTime)
            .addFieldData(
                DataType.ExerciseType.EXERCISE_TYPE,
                DataType.ExerciseType.PredefinedExerciseType.RUNNING
            )
            .addFieldData(DataType.ExerciseType.SESSIONS, listOf(session))
            .build()

        val insertRequest = DataTypes.EXERCISE.insertDataRequestBuilder
            .addData(healthDataPoint)
            .build()

        healthDataStore.insertData(insertRequest)
        Log.i(MainActivity.APP_TAG, "Inserted running exercise")
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

Andares Subidos

Os dados de andares subidos são um dos tipos de dados de saúde relacionados à atividade. Eles são exibidos no Rastreador de Atividades do aplicativo Samsung Health.

Os tipos de dados correspondentes aos andares subidos no Samsung Health SDK para Android e no Samsung Health Data SDK são os seguintes:

SDK Samsung Health para Android

SDK de dados de saúde da Samsung

Constantes de saúde.Andares subidos

Tipo de andares escalados

Para ler os dados de andares subidos hoje usando o SDK do Samsung Health para Android, o seguinte código de exemplo pode ser usado.

Dados de andares subidos com o SDK do Samsung Health para Android

fun readTodayFloorsClimbed(healthDataStore: HealthDataStore) {
    val startTime = LocalDate.now().atStartOfDay().toInstant(ZoneOffset.UTC).toEpochMilli()
    val endTime =
        LocalDate.now().plusDays(1).atStartOfDay().toInstant(ZoneOffset.UTC).toEpochMilli()

    val healthDataResolver = HealthDataResolver(healthDataStore, null)

    val readRequest = HealthDataResolver.ReadRequest.Builder()
        .setDataType(FloorsClimbed.HEALTH_DATA_TYPE)
        .setLocalTimeRange(
            FloorsClimbed.START_TIME,
            FloorsClimbed.TIME_OFFSET,
            startTime,
            endTime
        )
        .build()

    try {
        healthDataResolver.read(readRequest).setResultListener { result ->
            try {
                val iterator = result.iterator()

                if (iterator.hasNext()) {
                    val healthData = iterator.next()
                    val totalCount = healthData.getFloat(FloorsClimbed.FLOOR)
                    Log.i(MainActivity.APP_TAG, "Today floors climbed: $totalCount")
                } else {
                    Log.i(MainActivity.APP_TAG, "Today floors climbed: 0")
                }
            } finally {
                result.close()
            }
        }
    } catch (exception: Exception) {
        exception.message?.let { Log.i(MainActivity.APP_TAG, it) }
    }
}

Ao usar o SDK de dados do Samsung Health para ler os dados de andares subidos hoje, o resultado é o seguinte:

Análise dos dados de andares subidos com o SDK de Dados de Saúde da Samsung

suspend fun readTodayFloorsClimbed(healthDataStore: HealthDataStore) {
    val startTime = LocalDate.now().atStartOfDay()
    val endTime = LocalDateTime.now()
    val readRequest = DataType.FloorsClimbedType.TOTAL.requestBuilder
        .setLocalTimeFilter(LocalTimeFilter.of(startTime, endTime))
        .build()

    try {
        val readResult = healthDataStore.aggregateData(readRequest)
        val data = readResult.dataList
        val totalCount = if (data.isNotEmpty()) data.first().value else 0
        Log.i(MainActivity.APP_TAG, "Today floors climbed: $totalCount")
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

Para registrar os andares subidos ao usar o SDK do Samsung Health para Android, o seguinte código de exemplo pode ser utilizado.

Registrando dados de andares subidos com o SDK do Samsung Health para Android

fun insertTodayFloorsClimbed(healthDataStore: HealthDataStore) {
    val oneMinuteAsSeconds = 60L
    val floor = 2f
    val deviceId = HealthDeviceManager(healthDataStore).localDevice.uuid
    val startTime = Instant.now().minusSeconds(oneMinuteAsSeconds).toEpochMilli()
    val endTime = Instant.now().toEpochMilli()
    val timeOffset = TimeZone.getDefault().getOffset(endTime).toLong()
    val healthDataResolver = HealthDataResolver(healthDataStore, null)

    val healthData = HealthData().apply {
        sourceDevice = deviceId
        putLong(FloorsClimbed.START_TIME, startTime)
        putLong(FloorsClimbed.END_TIME, endTime)
        putLong(FloorsClimbed.TIME_OFFSET, timeOffset)
        putFloat(FloorsClimbed.FLOOR, floor)
    }

    val insertRequest = HealthDataResolver.InsertRequest.Builder()
        .setDataType(FloorsClimbed.HEALTH_DATA_TYPE)
        .build()

    insertRequest.addHealthData(healthData)

    try {
        val result = healthDataResolver.insert(insertRequest).await()

        if (result.status == STATUS_SUCCESSFUL) {
            Log.i(
                MainActivity.APP_TAG,
                "Inserted floor climbed. Count of data: ${result.count}"
            )
        } else {
            Log.i(MainActivity.APP_TAG, "Inserting failed")
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

Ao usar o SDK de dados do Samsung Health para registrar os andares subidos hoje, o resultado é o seguinte:

Registrando dados de andares subidos com o SDK de Dados de Saúde da Samsung

suspend fun insertTodayFloorClimbed(healthDataStore: HealthDataStore) {
    val oneMinuteAsSeconds = 60L
    val floor = 2f
    val startTime = Instant.now().minusSeconds(oneMinuteAsSeconds)
    val endTime = Instant.now()

    try {
        val healthDataPoint = HealthDataPoint.builder()
            .setStartTime(startTime)
            .setEndTime(endTime)
            .addFieldData(DataType.FloorsClimbedType.FLOOR, floor)
            .build()

        val insertRequest = DataTypes.FLOORS_CLIMBED.insertDataRequestBuilder
            .addData(healthDataPoint)
            .build()

        healthDataStore.insertData(insertRequest)
        Log.i(MainActivity.APP_TAG, "Inserted floor climbed")
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

Nutrição

O aplicativo Samsung Health oferece um recurso de rastreamento alimentar que permite aos usuários registrar e gerenciar seus dados alimentares para cada tipo de refeição, como café da manhã, almoço e jantar.

Os tipos de dados nutricionais correspondentes no Samsung Health SDK para Android e no Samsung Health Data SDK são os seguintes:

SDK Samsung Health para Android

SDK de dados de saúde da Samsung

Constantes de Saúde.Nutrição

Tipo de Nutrição

Aqui está um exemplo de código para ler os dados nutricionais de hoje usando o SDK do Samsung Health para Android.

Como ler dados nutricionais com o SDK Samsung Health para Android

fun readTodayNutrition(healthDataStore: HealthDataStore) {
    val startTime = LocalDate.now().atStartOfDay().toInstant(ZoneOffset.UTC).toEpochMilli()
    val endTime =
        LocalDate.now().plusDays(1).atStartOfDay().toInstant(ZoneOffset.UTC).toEpochMilli()

    val healthDataResolver = HealthDataResolver(healthDataStore, null)

    val nutritionRequest = HealthDataResolver.ReadRequest.Builder()
        .setDataType(Nutrition.HEALTH_DATA_TYPE)
        .setLocalTimeRange(Nutrition.START_TIME, Nutrition.TIME_OFFSET, startTime, endTime)
        .build()

    try {
        healthDataResolver.read(nutritionRequest).setResultListener { result ->
            try {
                val iterator = result.iterator()

                iterator.forEach { healthData ->
                    val title = healthData.getString(Nutrition.TITLE)
                    val mealType = healthData.getInt(Nutrition.MEAL_TYPE)
                    val calories = healthData.getFloat(Nutrition.CALORIE)
                    Log.i(MainActivity.APP_TAG, "Today nutrition: $title, $mealType, 
                        $calories")
                }
            } finally {
                result.close()
            }
        }
    } catch (exception: Exception) {
        exception.message?.let { Log.i(MainActivity.APP_TAG, it) }
    }
}

Ao usar o SDK de dados de saúde da Samsung para ler os dados nutricionais de hoje, o resultado é o seguinte:

Reading nutrition data with Samsung Health Data SDK
suspend fun readTodayNutrition(healthDataStore: HealthDataStore) {
    val startTime = LocalDate.now().atStartOfDay()
    val endTime = LocalDateTime.now()
    val readRequest = DataTypes.NUTRITION.readDataRequestBuilder
        .setLocalTimeFilter(LocalTimeFilter.of(startTime, endTime))
        .build()

    try {
        val readResult = healthDataStore.readData(readRequest)

        if (readResult.dataList.isEmpty()) {
            Log.i(MainActivity.APP_TAG, "No nutrition today")
            return
        }

        readResult.dataList.forEach { healthData ->
            val title = healthData.getValue(DataType.NutritionType.TITLE)
            val mealType = healthData.getValue(DataType.NutritionType.MEAL_TYPE)
            val calories = healthData.getValue(DataType.NutritionType.CALORIES)
            Log.i(MainActivity.APP_TAG, "Today nutrition: $title, $mealType, $calories")
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

Aqui está um exemplo de código para escrever dados nutricionais ao usar o SDK Samsung Health para Android.

Como gravar dados nutricionais com o SDK Samsung Health para Android

fun insertNutrition(healthDataStore: HealthDataStore) {

    val myDevice = HealthDeviceManager(healthDataStore)

    val mealTitle = "Toast and coffee"
    val calories = 66f
    val totalFat = 0.8f
    val saturatedFat = 0.1f
    val protein = 2.1f
    val carbohydrate = 11.9f
    val totalSugars = 1f
    val dietaryFiber = 0.6f
    val sodium = 135f
    val calcium = 40.3f
    val iron = 0.78f
    val potassium = 140f
    //for females, age 19 - 50, according to https://nap.nationalacademies.org/catalog/11537/dietary-reference-intakes-the-essential-guide-to-nutrient-requirements
    val referenceIndexForIronInMilligrams = 8.1f
    // for age 19-50, refer to the link above.
    val referenceIndexForCalciumInMilligrams = 1000f

    val startTime = Instant.now().toEpochMilli()
    val timeOffset = TimeZone.getDefault().getOffset(startTime).toLong()

    val data = HealthData().apply {
        sourceDevice = myDevice.localDevice.uuid
        putLong(HealthConstants.Nutrition.START_TIME, startTime);
        putLong(HealthConstants.Nutrition.TIME_OFFSET, timeOffset);
        putInt(HealthConstants.Nutrition.MEAL_TYPE, MEAL_TYPE_BREAKFAST)
        putString(HealthConstants.Nutrition.TITLE, mealTitle)
        putFloat(HealthConstants.Nutrition.CALORIE, calories)
        putFloat(HealthConstants.Nutrition.TOTAL_FAT, totalFat)
        putFloat(HealthConstants.Nutrition.SATURATED_FAT, saturatedFat)
        putFloat(HealthConstants.Nutrition.PROTEIN, protein)
        putFloat(HealthConstants.Nutrition.CARBOHYDRATE, carbohydrate)
        putFloat(HealthConstants.Nutrition.SUGAR, totalSugars)
        putFloat(HealthConstants.Nutrition.DIETARY_FIBER, dietaryFiber)
        putFloat(HealthConstants.Nutrition.SODIUM, sodium)
        putFloat(HealthConstants.Nutrition.POTASSIUM, potassium)
        val calciumAsPercentOfReferenceIntake =
            calcium / referenceIndexForCalciumInMilligrams * 100
        val ironInPercentOfReferenceIntake= iron / referenceIndexForIronInMilligrams * 100
        putFloat(HealthConstants.Nutrition.CALCIUM, calciumAsPercentOfReferenceIntake)
        putFloat(HealthConstants.Nutrition.IRON, ironInPercentOfReferenceIntake)
    }
    val insertRequest = HealthDataResolver.InsertRequest.Builder()
        .setDataType(HealthConstants.Nutrition.HEALTH_DATA_TYPE)
        .build()
    val handler = Handler(Looper.getMainLooper())
    val healthDataResolver = HealthDataResolver(healthDataStore, handler)
    try {
        insertRequest.addHealthData(data)
        val insertResult = healthDataResolver.insert(insertRequest).await()
        Log.i(TAG, "insertNutrition status: ${insertResult.status}")
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

Ao usar o SDK de dados de saúde da Samsung para gravar dados nutricionais, o processo é o seguinte:

Como escrever dados nutricionais com o SDK de dados de saúde da Samsung

suspend fun insertNutrition(healthDataStore: HealthDataStore) {

    val startTime = LocalDateTime.now()
    val mealTitle = "Toast and coffee"
    val calories = 66f
    val totalFat = 0.8f
    val saturatedFat = 0.1f
    val protein = 2.1f
    val carbohydrate = 11.9f
    val sugar = 1f
    val dietaryFiber = 0.6f
    val sodium = 135f
    val calcium = 40.3f
    val iron = 0.78f
    val potassium = 140f

    try {
        val healthDataPoint = HealthDataPoint.builder()
            .setLocalStartTime(startTime)
            .addFieldData(DataType.NutritionType.MEAL_TYPE, MealType.BREAKFAST)
            .addFieldData(DataType.NutritionType.TITLE, mealTitle)
            .addFieldData(DataType.NutritionType.CALORIES, calories)
            .addFieldData(DataType.NutritionType.TOTAL_FAT, totalFat)
            .addFieldData(DataType.NutritionType.SATURATED_FAT, saturatedFat)
            .addFieldData(DataType.NutritionType.PROTEIN, protein)
            .addFieldData(DataType.NutritionType.CARBOHYDRATE, carbohydrate)
            .addFieldData(DataType.NutritionType.SUGAR, sugar)
            .addFieldData(DataType.NutritionType.DIETARY_FIBER, dietaryFiber)
            .addFieldData(DataType.NutritionType.SODIUM, sodium)
            .addFieldData(DataType.NutritionType.CALCIUM, calcium)
            .addFieldData(DataType.NutritionType.IRON, iron)
            .addFieldData(DataType.NutritionType.POTASSIUM, potassium)
            .build()

        val insertDataRequest = DataTypes.NUTRITION.insertDataRequestBuilder
            .addData(healthDataPoint)
            .build()
        healthDataStore.insertData(insertDataRequest)

    } catch(e: Exception) {
        e.printStackTrace()
    }
}

Ingestão de água

Os tipos de dados do Samsung Health SDK para Android e do Samsung Health Data SDK são os seguintes.

SDK Samsung Health para Android

SDK de dados de saúde da Samsung

Constantes de saúde. Ingestão de água.

Tipo de ingestão de água

Segue abaixo um exemplo de código para ler os dados de ingestão de água de hoje usando o SDK Samsung Health para Android.

Leitura de dados de ingestão de água com o SDK Samsung Health para Android

fun readTodayTotalWaterIntake (
    healthDataStore: HealthDataStore
) {
    val startTime = LocalDate.now().atStartOfDay().toInstant(ZoneOffset.UTC).toEpochMilli()
    val endTime = LocalDateTime.now().toInstant(ZoneOffset.UTC).toEpochMilli()
    val handler = Handler(Looper.getMainLooper())
    val healthDataResolver = HealthDataResolver(healthDataStore, handler)
    val waterIntakeId = "water_intake_sum"
    val aggregateRequest = HealthDataResolver.AggregateRequest.Builder()
        .addFunction(
            HealthDataResolver.AggregateRequest.AggregateFunction.SUM,
            HealthConstants.WaterIntake.AMOUNT,
            waterIntakeId
        )
        .setLocalTimeRange(
            HealthConstants.WaterIntake.START_TIME,
            HealthConstants.WaterIntake.TIME_OFFSET, startTime, endTime
        )
        .setDataType(HealthConstants.WaterIntake.HEALTH_DATA_TYPE).build()
    try {
        healthDataResolver.aggregate(aggregateRequest).setResultListener { result ->
            try {
                result?.forEach { healthData ->
                    val waterIntakeSum = healthData.getFloat(waterIntakeId)
                }
            } finally {
                result.close()
            }
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

Ao usar o SDK de dados de saúde da Samsung para ler os dados de ingestão de água de hoje, o resultado é o seguinte:

Leitura de dados de ingestão de água com o SDK de dados de saúde da Samsung

suspend fun readTodayTotalWaterIntake(
    healthDataStore: com.samsung.android.sdk.health.data.HealthDataStore
) {
    val startTime = LocalDate.now().atStartOfDay()
    val endTime = LocalDateTime.now()
    val localTimeFilter = LocalTimeFilter.of(startTime, endTime)
    val readRequest = DataType.WaterIntakeType.TOTAL.requestBuilder
        .setLocalTimeFilter(localTimeFilter)
        .build()
    try {
        val result = healthDataStore.aggregateData(readRequest)
        result.dataList.lastOrNull()?.let { dataPoint ->
            val waterIntake = dataPoint.value
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

Segue um exemplo de código para registrar dados de ingestão de água ao usar o SDK Samsung Health para Android.

Gravação de dados de ingestão de água com o SDK Samsung Health para Android

fun insertWaterIntake(healthDataStore: HealthDataStore) {

    val myDevice = HealthDeviceManager(healthDataStore)
    val waterAmountInMilliliters = 250f
    val unitAmount = 250f

    val startTime = Instant.now().toEpochMilli()
    val timeOffset = TimeZone.getDefault().getOffset(startTime).toLong()

    val data = HealthData().apply {
        sourceDevice = myDevice.localDevice.uuid
        putLong(HealthConstants.WaterIntake.START_TIME, startTime);
        putLong(HealthConstants.WaterIntake.TIME_OFFSET, timeOffset);
        putFloat(HealthConstants.WaterIntake.AMOUNT, waterAmountInMilliliters)
        putFloat(HealthConstants.WaterIntake.UNIT_AMOUNT, unitAmount)
    }
    val insertRequest = HealthDataResolver.InsertRequest.Builder()
        .setDataType(HealthConstants.WaterIntake.HEALTH_DATA_TYPE)
        .build()
    val handler = Handler(Looper.getMainLooper())
    val healthDataResolver = HealthDataResolver(healthDataStore, handler)
    try {
        insertRequest.addHealthData(data)
        val insertResult = healthDataResolver.insert(insertRequest).await()
        Log.i(TAG, "insertWaterIntake status: ${insertResult.status}")
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

Ao usar o SDK de dados de saúde da Samsung para gravar dados de ingestão de água, o processo é o seguinte:

Gravação de dados de ingestão de água com o SDK de dados de saúde da Samsung

suspend fun insertWaterIntake(healthDataStore: HealthDataStore) {
    val startTime = LocalDateTime.now()
    val waterAmountInMilliliters = 250f

    try {
        val healthDataPoint = HealthDataPoint.builder()
            .setLocalStartTime(startTime)
            .addFieldData(DataType.WaterIntakeType.AMOUNT, waterAmountInMilliliters)
            .build()

        val insertDataRequest = DataTypes.WATER_INTAKE.insertDataRequestBuilder
            .addData(healthDataPoint)
            .build()
        healthDataStore.insertData(insertDataRequest)
    } catch(e: Exception) {
        e.printStackTrace()
    }
}

Sono e estágio do sono

Os tipos de dados do Samsung Health SDK para Android e do Samsung Health Data SDK são os seguintes.

SDK Samsung Health para Android

SDK de dados de saúde da Samsung

HealthConstants.Sleep
HealthConstants.SleepStage

Tipo de sono

O código para ler os dados de sono da noite anterior usando o SDK do Samsung Health para Android é o seguinte.

Analisando os dados de sono da noite anterior com o SDK Samsung Health para Android.

fun readLastSleep(
    healthDataStore: HealthDataStore
) {
    val handler = Handler(Looper.getMainLooper())
    val healthDataResolver = HealthDataResolver(healthDataStore, handler)
    val resultCount = 1
    val resultOffset = 0
    val request: HealthDataResolver.ReadRequest =
        HealthDataResolver.ReadRequest.Builder()
            .setDataType(HealthConstants.Sleep.HEALTH_DATA_TYPE)
            .setSort(HealthConstants.Sleep.START_TIME, SortOrder.DESC)
            .setResultCount(resultOffset, resultCount)
            .build()
    try {
        healthDataResolver.read(request).setResultListener { result ->
            try {
                result.lastOrNull()?.let { healthData ->
                    val sleepId = healthData.getString(HealthConstants.Sleep.UUID)
                    val sleepStartTime =
                        Instant.ofEpochMilli(healthData.getLong(HealthConstants.Sleep.START_TIME))
                    val sleepEndTime =
                        Instant.ofEpochMilli(healthData.getLong(HealthConstants.Sleep.END_TIME))
                    readSleepStagesForSleepId(healthDataStore, sleepId)
                }
            } finally {
                result.close()
            }
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

fun readSleepStagesForSleepId(
    healthDataStore: HealthDataStore,
    sleepId: String
) {
    val handler = Handler(Looper.getMainLooper())
    val healthDataResolver = HealthDataResolver(healthDataStore, handler)
    val request: HealthDataResolver.ReadRequest =
        HealthDataResolver.ReadRequest.Builder()
            .setDataType(HealthConstants.SleepStage.HEALTH_DATA_TYPE)
            .setFilter(Filter.eq(HealthConstants.SleepStage.SLEEP_ID, sleepId))
            .build()
    try {
        healthDataResolver.read(request).setResultListener { result ->
            try {
                result?.forEach { sleepStageData ->
                    val sleepStageName =
                        sleepStageNameById(sleepStageData.getInt(HealthConstants.SleepStage.STAGE))
                    val sleepStageStartTime =
                        Instant.ofEpochMilli(sleepStageData.getLong(HealthConstants.SleepStage.START_TIME))
                    val sleepStageEndTime =
                        Instant.ofEpochMilli(sleepStageData.getLong(HealthConstants.SleepStage.END_TIME))
                }
            } finally {
                result.close()
            }
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

fun sleepStageNameById(id: Int): String {
    return when (id) {
        HealthConstants.SleepStage.STAGE_AWAKE -> "AWAKE"
        HealthConstants.SleepStage.STAGE_DEEP -> "DEEP"
        HealthConstants.SleepStage.STAGE_LIGHT -> "LIGHT"
        HealthConstants.SleepStage.STAGE_REM -> "REM"
        else -> ""
    }
}

Ao usar o SDK de dados do Samsung Health para ler os dados de sono da noite anterior, o resultado é o seguinte:

Analisando os dados de sono da noite anterior com o SDK de Dados de Saúde da Samsung.

  suspend fun readSleepTotalDuration(
    healthDataStore: HealthDataStore
) {
    val daysBackOffset = 400L
    val startTime =
        LocalDate.now()
            .minusDays(daysBackOffset)
    val endTime = LocalDate.now()
    val localDateFilter = LocalDateFilter.of(startTime, endTime)
    val request = DataType.SleepType.TOTAL_DURATION.requestBuilder
        .setLocalDateFilter(localDateFilter)
        .build()
    try {
        val result = healthDataStore.aggregateData(request)
        result.dataList.forEach { aggregatedData ->
            val startTime = aggregatedData.startTime
            val endTime = aggregatedData.endTime
            val totalDuration = aggregatedData.value
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
}


suspend fun readLastSleep(
    healthDataStore: HealthDataStore
) {
    val resultCount = 1
    val readRequest = DataTypes.SLEEP.readDataRequestBuilder
        .setOrdering(Ordering.DESC)
        .setLimit(resultCount)
        .build()
    try {
        val result = healthDataStore.readData(readRequest)
        result.dataList.lastOrNull()?.let { sleepData ->
            val sleepId = sleepData.uid
            val sleepStartTime = sleepData.startTime
            val sleepEndTime = sleepData.endTime
            val sleepSessions = sleepData.getValue(DataType.SleepType.SESSIONS)
            sleepSessions?.forEach { sleepSession ->
                val sessionDuration = sleepSession.duration
                val sessionStartTime = sleepSession.startTime
                val sessionEndTime = sleepSession.endTime
                val sleepStages = sleepSession.stages
                sleepStages?.forEach { sleepStage ->
                    val sleepStageName = sleepStage.stage.name
                    val sleepStageStartTime = sleepStage.startTime
                    val sleepStageEndTime = sleepStage.endTime
                }
            }
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

O código para gravar dados de sono ao usar o SDK do Samsung Health para Android é o seguinte.

Gravando os dados de sono da noite anterior com o SDK Samsung Health para Android.

fun insertSleepData(healthDataStore: HealthDataStore) {
    val handler = Handler(Looper.getMainLooper())
    val healthDataResolver = HealthDataResolver(healthDataStore, handler)
    val healthDeviceManager = HealthDeviceManager(healthDataStore)

    val zoneOffset = ZoneOffset.systemDefault().rules.getOffset(Instant.now())
    val startTime = LocalDate.now().minusDays(1).atTime(23, 10).toInstant(zoneOffset)
    val endTime = LocalDate.now().atTime(6, 30).toInstant(zoneOffset)
    val timeOffset = TimeZone.getDefault().getOffset(Instant.now().toEpochMilli())

    val sleepData = HealthData().apply {
        sourceDevice = healthDeviceManager.localDevice.uuid
        putLong(HealthConstants.Sleep.START_TIME, startTime.toEpochMilli())
        putLong(HealthConstants.Sleep.END_TIME, endTime.toEpochMilli())
        putLong(HealthConstants.Sleep.TIME_OFFSET, timeOffset.toLong())
    }

    val insertRequest = InsertRequest.Builder()
        .setDataType(HealthConstants.Sleep.HEALTH_DATA_TYPE)
        .build()
    insertRequest.addHealthData(sleepData)

    try {
        val insertResult = healthDataResolver.insert(insertRequest).await()
        if (insertResult.status != BaseResult.STATUS_SUCCESSFUL) {
            Log.i(
                MainActivity.APP_TAG,
                "Error inserting sleep data. Error code: ${insertResult.status}"
            )
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }

    val resultCount = 1
    val resultOffset = 0
    val readRequest =
        HealthDataResolver.ReadRequest.Builder()
            .setDataType(HealthConstants.Sleep.HEALTH_DATA_TYPE)
            .setSort(HealthConstants.Sleep.UPDATE_TIME, SortOrder.DESC)
            .setResultCount(resultOffset, resultCount)
            .build()

    try {
        val readResult = healthDataResolver.read(readRequest).await()
        val sleepId = readResult.last().getString(HealthConstants.Sleep.UUID)
        writeSleepStages(healthDataStore, sleepId)
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

private fun writeSleepStages(healthDataStore: HealthDataStore, sleepId: String) {
    val handler = Handler(Looper.getMainLooper())
    val healthDataResolver = HealthDataResolver(healthDataStore, handler)
    val healthDeviceManager = HealthDeviceManager(healthDataStore)

    val startDate = LocalDate.now().minusDays(1)
    val endDate = LocalDate.now()
    val zoneOffset = ZoneOffset.systemDefault().rules.getOffset(Instant.now())
    val timeOffset = TimeZone.getDefault().getOffset(Instant.now().toEpochMilli())
    val sleepStages = mutableListOf<HealthData>()
    var sleepStage = HealthData().apply {
        sourceDevice = healthDeviceManager.localDevice.uuid
        putLong(HealthConstants.SleepStage.TIME_OFFSET, timeOffset.toLong())
        putString(HealthConstants.SleepStage.SLEEP_ID, sleepId)
        putLong(
            HealthConstants.SleepStage.START_TIME,
            startDate.atTime(23, 10).toInstant(zoneOffset).toEpochMilli()
        )
        putLong(
            HealthConstants.SleepStage.END_TIME,
            startDate.atTime(23, 35).toInstant(zoneOffset).toEpochMilli()
        )
        putInt(HealthConstants.SleepStage.STAGE, HealthConstants.SleepStage.STAGE_LIGHT)
    }
    sleepStages.add(sleepStage)

    sleepStage = HealthData().apply {
        sourceDevice = healthDeviceManager.localDevice.uuid
        putLong(HealthConstants.SleepStage.TIME_OFFSET, timeOffset.toLong())
        putString(HealthConstants.SleepStage.SLEEP_ID, sleepId)
        putLong(
            HealthConstants.SleepStage.START_TIME,
            startDate.atTime(23, 35).toInstant(zoneOffset).toEpochMilli()
        )
        putLong(
            HealthConstants.SleepStage.END_TIME,
            endDate.atTime(1, 50).toInstant(zoneOffset).toEpochMilli()
        )
        putInt(HealthConstants.SleepStage.STAGE, HealthConstants.SleepStage.STAGE_DEEP)
    }
    sleepStages.add(sleepStage)
    sleepStage = HealthData().apply {
        sourceDevice = healthDeviceManager.localDevice.uuid
        putLong(HealthConstants.SleepStage.TIME_OFFSET, timeOffset.toLong())
        putString(HealthConstants.SleepStage.SLEEP_ID, sleepId)
        putLong(
            HealthConstants.SleepStage.START_TIME,
            endDate.atTime(1, 50).toInstant(zoneOffset).toEpochMilli()
        )
        putLong(
            HealthConstants.SleepStage.END_TIME,
            endDate.atTime(2, 20).toInstant(zoneOffset).toEpochMilli()
        )
        putInt(HealthConstants.SleepStage.STAGE, HealthConstants.SleepStage.STAGE_REM)
    }
    sleepStages.add(sleepStage)
    sleepStage = HealthData().apply {
        sourceDevice = healthDeviceManager.localDevice.uuid
        putLong(HealthConstants.SleepStage.TIME_OFFSET, timeOffset.toLong())
        putString(HealthConstants.SleepStage.SLEEP_ID, sleepId)
        putLong(
            HealthConstants.SleepStage.START_TIME,
            endDate.atTime(2, 20).toInstant(zoneOffset).toEpochMilli()
        )
        putLong(
            HealthConstants.SleepStage.END_TIME,
            endDate.atTime(2, 55).toInstant(zoneOffset).toEpochMilli()
        )
        putInt(HealthConstants.SleepStage.STAGE, HealthConstants.SleepStage.STAGE_LIGHT)
    }
    sleepStages.add(sleepStage)
    sleepStage = HealthData().apply {
        sourceDevice = healthDeviceManager.localDevice.uuid
        putLong(HealthConstants.SleepStage.TIME_OFFSET, timeOffset.toLong())
        putString(HealthConstants.SleepStage.SLEEP_ID, sleepId)
        putLong(
            HealthConstants.SleepStage.START_TIME,
            endDate.atTime(2, 55).toInstant(zoneOffset).toEpochMilli()
        )
        putLong(
            HealthConstants.SleepStage.END_TIME,
            endDate.atTime(3, 10).toInstant(zoneOffset).toEpochMilli()
        )
        putInt(HealthConstants.SleepStage.STAGE, HealthConstants.SleepStage.STAGE_AWAKE)
    }
    sleepStages.add(sleepStage)
    sleepStage = HealthData().apply {
        sourceDevice = healthDeviceManager.localDevice.uuid
        putLong(HealthConstants.SleepStage.TIME_OFFSET, timeOffset.toLong())
        putString(HealthConstants.SleepStage.SLEEP_ID, sleepId)
        putLong(
            HealthConstants.SleepStage.START_TIME,
            endDate.atTime(3, 10).toInstant(zoneOffset).toEpochMilli()
        )
        putLong(
            HealthConstants.SleepStage.END_TIME,
            endDate.atTime(4, 30).toInstant(zoneOffset).toEpochMilli()
        )
        putInt(HealthConstants.SleepStage.STAGE, HealthConstants.SleepStage.STAGE_DEEP)
    }
    sleepStages.add(sleepStage)
    sleepStage = HealthData().apply {
        sourceDevice = healthDeviceManager.localDevice.uuid
        putLong(HealthConstants.SleepStage.TIME_OFFSET, timeOffset.toLong())
        putString(HealthConstants.SleepStage.SLEEP_ID, sleepId)
        putLong(
            HealthConstants.SleepStage.START_TIME,
            endDate.atTime(4, 30).toInstant(zoneOffset).toEpochMilli()
        )
        putLong(
            HealthConstants.SleepStage.END_TIME,
            endDate.atTime(5, 10).toInstant(zoneOffset).toEpochMilli()
        )
        putInt(HealthConstants.SleepStage.STAGE, HealthConstants.SleepStage.STAGE_REM)
    }
    sleepStages.add(sleepStage)
    sleepStage = HealthData().apply {
        sourceDevice = healthDeviceManager.localDevice.uuid
        putLong(HealthConstants.SleepStage.TIME_OFFSET, timeOffset.toLong())
        putString(HealthConstants.SleepStage.SLEEP_ID, sleepId)
        putLong(
            HealthConstants.SleepStage.START_TIME,
            endDate.atTime(5, 10).toInstant(zoneOffset).toEpochMilli()
        )
        putLong(
            HealthConstants.SleepStage.END_TIME,
            endDate.atTime(6, 20).toInstant(zoneOffset).toEpochMilli()
        )
        putInt(HealthConstants.SleepStage.STAGE, HealthConstants.SleepStage.STAGE_LIGHT)
    }
    sleepStages.add(sleepStage)
    sleepStage = HealthData().apply {
        sourceDevice = healthDeviceManager.localDevice.uuid
        putLong(HealthConstants.SleepStage.TIME_OFFSET, timeOffset.toLong())
        putString(HealthConstants.SleepStage.SLEEP_ID, sleepId)
        putLong(
            HealthConstants.SleepStage.START_TIME,
            endDate.atTime(6, 20).toInstant(zoneOffset).toEpochMilli()
        )
        putLong(
            HealthConstants.SleepStage.END_TIME,
            endDate.atTime(6, 30).toInstant(zoneOffset).toEpochMilli()
        )
        putInt(HealthConstants.SleepStage.STAGE, HealthConstants.SleepStage.STAGE_AWAKE)
    }
    sleepStages.add(sleepStage)

    val insertRequest = InsertRequest.Builder()
        .setDataType(HealthConstants.SleepStage.HEALTH_DATA_TYPE)
        .build()
    insertRequest.addHealthData(sleepStages)

    try {
        val insertResult = healthDataResolver.insert(insertRequest).await()
        if (insertResult.status != BaseResult.STATUS_SUCCESSFUL) {
            Log.i(
                MainActivity.APP_TAG,
                "Error inserting stages data. Error code: ${insertResult.status}"
            )
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

Ao usar o SDK de dados do Samsung Health para gravar dados de sono, o processo é o seguinte:

Gravando os dados de sono da noite anterior com o SDK de dados do Samsung Health.

suspend fun insertSleepData(healthDataStore: HealthDataStore) {
    val startDate = LocalDate.now().minusDays(1)
    val endDate = LocalDate.now()
    val startTime = startDate.atTime(23, 10)
    val endTime = endDate.atTime(6, 30)
    val zoneOffset = ZoneOffset.systemDefault().rules.getOffset(Instant.now())
    val duration = Duration.between(startTime, endTime)


    val sleepStageList = listOf(
        SleepSession.SleepStage.of(
            startDate.atTime(23, 10).toInstant(zoneOffset),
            startDate.atTime(23, 35).toInstant(zoneOffset),
            DataType.SleepType.StageType.LIGHT
        ),
        SleepSession.SleepStage.of(
            startDate.atTime(23, 35).toInstant(zoneOffset),
            endDate.atTime(1, 50).toInstant(zoneOffset),
            DataType.SleepType.StageType.DEEP
        ),
        SleepSession.SleepStage.of(
            endDate.atTime(1, 50).toInstant(zoneOffset),
            endDate.atTime(2, 20).toInstant(zoneOffset),
            DataType.SleepType.StageType.REM
        ),
        SleepSession.SleepStage.of(
            endDate.atTime(2, 20).toInstant(zoneOffset),
            endDate.atTime(2, 55).toInstant(zoneOffset),
            DataType.SleepType.StageType.LIGHT
        ),
        SleepSession.SleepStage.of(
            endDate.atTime(2, 55).toInstant(zoneOffset),
            endDate.atTime(3, 10).toInstant(zoneOffset),
            DataType.SleepType.StageType.AWAKE
        ),
        SleepSession.SleepStage.of(
            endDate.atTime(3, 10).toInstant(zoneOffset),
            endDate.atTime(4, 30).toInstant(zoneOffset),
            DataType.SleepType.StageType.DEEP
        ),
        SleepSession.SleepStage.of(
            endDate.atTime(4, 30).toInstant(zoneOffset),
            endDate.atTime(5, 10).toInstant(zoneOffset),
            DataType.SleepType.StageType.REM
        ),
        SleepSession.SleepStage.of(
            endDate.atTime(5, 10).toInstant(zoneOffset),
            endDate.atTime(6, 20).toInstant(zoneOffset),
            DataType.SleepType.StageType.LIGHT
        ),
        SleepSession.SleepStage.of(
            endDate.atTime(6, 20).toInstant(zoneOffset),
            endDate.atTime(6, 30).toInstant(zoneOffset),
            DataType.SleepType.StageType.AWAKE
        )
    )

    val sleepSession = SleepSession.of(
        startTime.toInstant(zoneOffset),
        endTime.toInstant(zoneOffset),
        duration,
        sleepStageList
    )
    try {
        val healthDataPoint = HealthDataPoint.builder()
            .setLocalStartTime(startTime)
            .setLocalEndTime(endTime)
            .addFieldData(
                DataType.SleepType.DURATION,
                duration
            )
            .addFieldData(DataType.SleepType.SESSIONS, listOf(sleepSession))
            .build()

        val insertDataRequest = DataTypes.SLEEP.insertDataRequestBuilder
            .addData(healthDataPoint)
            .build()

        healthDataStore.insertData(insertDataRequest)
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

Peso

Os tipos de dados de peso correspondentes no Samsung Health SDK para Android e no Samsung Health Data SDK são os seguintes:

SDK Samsung Health para Android

SDK de dados de saúde da Samsung

Constantes de saúde.Peso

Tipo de composição corporal

Para ler os dados de peso mais recentes ao usar o SDK do Samsung Health para Android, o seguinte código de exemplo pode ser usado.

Como ler os últimos dados de peso com o SDK do Samsung Health para Android

fun readLatestWeight(
    healthDataStore: HealthDataStore
) {
    val resultCount = 1
    val resultOffset = 0
    val handler = Handler(Looper.getMainLooper())
    val healthDataResolver = HealthDataResolver(healthDataStore, handler)
    val request: HealthDataResolver.ReadRequest =
        HealthDataResolver.ReadRequest.Builder()
            .setDataType(HealthConstants.Weight.HEALTH_DATA_TYPE)
            .setSort(HealthConstants.OxygenSaturation.START_TIME, SortOrder.DESC)
            .setResultCount(resultOffset, resultCount)
            .build()
    try {
        healthDataResolver.read(request).setResultListener { result ->
            try {
                result.lastOrNull()?.let { healthData ->
                    val measurementStartTime =
                        Instant.ofEpochMilli(healthData.getLong(HealthConstants.Weight.START_TIME))
                    val weight = healthData.getFloat(HealthConstants.Weight.WEIGHT)
                    val bodyFat = healthData.getFloat(HealthConstants.Weight.BODY_FAT)
                }
            } finally {
                result.close()
            }
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

Ao usar o SDK de dados do Samsung Health para ler os dados de peso mais recentes, o resultado é o seguinte:

Leitura dos últimos dados de peso com o SDK de dados do Samsung Health

suspend fun readLatestWeight(
    healthDataStore: HealthDataStore
) {
    val resultCount = 1
    val readRequest = DataTypes.BODY_COMPOSITION.readDataRequestBuilder
        .setOrdering(Ordering.DESC)
        .setLimit(resultCount)
        .build()
    try {
        val result = healthDataStore.readData(readRequest)
        result.dataList.lastOrNull()?.let { dataPoint ->
            val weight = dataPoint.getValue(DataType.BodyCompositionType.WEIGHT)
            val bodyFat = dataPoint.getValue(DataType.BodyCompositionType.BODY_FAT)
            val measurementStartTime = dataPoint.startTime
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

Aqui está um exemplo de código para gravar dados de peso ao usar o SDK do Samsung Health para Android.

Gravação de dados de peso com o SDK Samsung Health para Android

fun insertWeightData(
    healthDataStore: HealthDataStore
) {
    val weight = 75F
    val zoneId = ZoneOffset.systemDefault()
    val startTime = LocalDate.now().atTime(9, 0).atZone(zoneId).toInstant().toEpochMilli()
    val timeOffset = TimeZone.getDefault().getOffset(startTime).toLong()
    val mHealthDataResolver =
        HealthDataResolver(healthDataStore, Handler(Looper.getMainLooper()))
    val healthDeviceManager = HealthDeviceManager(healthDataStore)
    val data = HealthData().apply {
        putLong(HealthConstants.Weight.START_TIME, startTime)
        putLong(HealthConstants.Weight.TIME_OFFSET, timeOffset)
        putFloat(HealthConstants.Weight.WEIGHT, weight)
        // Register local device as the source of data
        sourceDevice = healthDeviceManager.localDevice.uuid
    }

    try {
        val insertRequest = InsertRequest.Builder()
            .setDataType(HealthConstants.Weight.HEALTH_DATA_TYPE)
            .build()
        insertRequest.addHealthData(data)

        val result = mHealthDataResolver.insert(insertRequest).await()
        Log.i(MainActivity.APP_TAG, "insert result status: ${result.status}")
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

Gravação de dados de peso com o SDK de dados do Samsung Health

suspend fun insertWeightData(
    healthDataStore: HealthDataStore
) {
    val weight = 75F
    val localDateTime = LocalDate.now().atTime(9, 0)
    val zoneId = ZoneOffset.systemDefault()
    val zoneOffset = zoneId.rules.getOffset(localDateTime)

    try {
        val healthDataPoint = HealthDataPoint.builder()
            .addFieldData(DataType.BodyCompositionType.WEIGHT, weight)
            .setLocalStartTime(localDateTime, zoneOffset)
            .build()
        val insertRequest = DataTypes.BODY_COMPOSITION.insertDataRequestBuilder
            .addData(healthDataPoint)
            .build()

        healthDataStore.insertData(insertRequest)
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

Frequência cardíaca

Os tipos de dados de frequência cardíaca correspondentes no Samsung Health SDK para Android e no Samsung Health Data SDK são os seguintes:

SDK Samsung Health para Android

SDK de dados de saúde da Samsung

Constantes de saúde. Frequência cardíaca

Tipo de Frequência Cardíaca

Segue abaixo um exemplo de código para leitura dos dados de frequência cardíaca de hoje usando o SDK Samsung Health para Android.

Analisando os dados de frequência cardíaca de hoje com o SDK Samsung Health para Android.

class ReadHeartRate {

    fun readTodayHeartRate(
        healthDataStore: HealthDataStore
    ) {
        val startTime = LocalDate.now().atStartOfDay().toInstant(ZoneOffset.UTC).toEpochMilli()
        val endTime = LocalDateTime.now().toInstant(ZoneOffset.UTC).toEpochMilli()
        val handler = Handler(Looper.getMainLooper())
        val healthDataResolver = HealthDataResolver(healthDataStore, handler)
        val request: HealthDataResolver.ReadRequest =
            HealthDataResolver.ReadRequest.Builder()
                .setDataType(HealthConstants.HeartRate.HEALTH_DATA_TYPE)
                .setLocalTimeRange(
                    HealthConstants.HeartRate.START_TIME,
                    HealthConstants.HeartRate.TIME_OFFSET, startTime, endTime
                ).build()
        try {
            healthDataResolver.read(request).setResultListener { result ->
                try {
                    result?.forEach { healthData ->
                        val heartRate = healthData.getFloat(HealthConstants.HeartRate.HEART_RATE)
                        val measurementStartTime =
                            Instant.ofEpochMilli(healthData.getLong(HealthConstants.HeartRate.START_TIME))
                        val measurementEndTime =
                            Instant.ofEpochMilli(healthData.getLong(HealthConstants.HeartRate.END_TIME))
                        val binningData = healthData.getBlob(HealthConstants.HeartRate.BINNING_DATA)
                        val liveDataList = HealthDataUtil.getStructuredDataList(
                            binningData,
                            HeartRateLiveData::class.java
                        )
                        liveDataList.forEach { liveDataPoint ->
                            val heartRate = liveDataPoint.heart_rate
                            val startTime = Instant.ofEpochMilli(liveDataPoint.start_time)
                        }
                    }
                } finally {
                    result.close()
                }
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }
}

data class HeartRateLiveData(
    val heart_rate: Float,
    val heart_rate_min: Float,
    val heart_rate_max: Float,
    val start_time: Long,
    val end_time: Long
)

Ao usar o SDK de dados do Samsung Health para ler os dados de frequência cardíaca de hoje, o resultado é o seguinte:

Analisando os dados de frequência cardíaca de hoje com o SDK de dados do Samsung Health.

suspend fun readTodayHeartRate (
    healthDataStore: HealthDataStore
) {
    val startTime = LocalDate.now().atStartOfDay()
    val endTime = LocalDateTime.now()
    val localTimeFilter = LocalTimeFilter.of(startTime, endTime)
    val readRequest = DataTypes.HEART_RATE.readDataRequestBuilder
        .setLocalTimeFilter(localTimeFilter)
        .build()
    try {
        val result = healthDataStore.readData(readRequest)
        result.dataList.forEach { dataPoint ->
            val startTime = dataPoint.startTime
            val endTime = dataPoint.endTime
            val heartRate = dataPoint.getValue(DataType.HeartRateType.HEART_RATE)
            val heartRateSeriesData = dataPoint.getValue(DataType.HeartRateType.SERIES_DATA)
            heartRateSeriesData?.forEach { seriesData ->
                val startTime = seriesData.startTime
                val heartRate = seriesData.heartRate
            }
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

Para registrar dados de frequência cardíaca ao usar o SDK do Samsung Health para Android, o seguinte código de exemplo pode ser utilizado.

Gravação de dados de frequência cardíaca com o SDK Samsung Health para Android

fun insertTodayHeartRate(healthDataStore: HealthDataStore) {
    val tenMinutesAsSeconds = 600L
    val heartRate = 76f
    val heartBeatCount = 1
    val deviceId = HealthDeviceManager(healthDataStore).localDevice.uuid
    val startTime = Instant.now().minusSeconds(tenMinutesAsSeconds).toEpochMilli()
    val endTime = Instant.now().toEpochMilli()
    val timeOffset = TimeZone.getDefault().getOffset(endTime).toLong()
    val healthDataResolver = HealthDataResolver(healthDataStore, null)

    val healthData = HealthData().apply {
        sourceDevice = deviceId
        putLong(HeartRate.START_TIME, startTime)
        putLong(HeartRate.END_TIME, endTime)
        putLong(HeartRate.TIME_OFFSET, timeOffset)
        putFloat(HeartRate.HEART_RATE, heartRate)
        putInt(HeartRate.HEART_BEAT_COUNT, heartBeatCount)
    }

    val insertRequest = HealthDataResolver.InsertRequest.Builder()
        .setDataType(HeartRate.HEALTH_DATA_TYPE)
        .build()

    insertRequest.addHealthData(healthData)

    try {
        val result = healthDataResolver.insert(insertRequest).await()

        if (result.status == STATUS_SUCCESSFUL) {
            Log.i(MainActivity.APP_TAG, "Inserted heart rate. Count of data: ${result.count}")
        } else {
            Log.i(MainActivity.APP_TAG, "Inserting failed")
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

Ao usar o SDK de dados do Samsung Health para gravar dados de frequência cardíaca, o processo é o seguinte:

Gravação de dados de frequência cardíaca com o SDK de dados do Samsung Health

suspend fun insertTodayHeartRate(healthDataStore: HealthDataStore) {
    val tenMinutesAsSeconds = 600L
    val heartRate = 76f
    val startTime = LocalDateTime.now().minusSeconds(tenMinutesAsSeconds)
    val endTime = LocalDateTime.now()

    try {
        val healthDataPoint = HealthDataPoint.builder()
            .setLocalStartTime(startTime)
            .setLocalEndTime(endTime)
            .addFieldData(DataType.HeartRateType.HEART_RATE, heartRate)
            .build()

        val insertRequest = DataTypes.HEART_RATE.insertDataRequestBuilder
            .addData(healthDataPoint)
            .build()

        healthDataStore.insertData(insertRequest)
        Log.i(MainActivity.APP_TAG, "Inserted heart rate")
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

Glicemia

Os tipos de dados de glicose no sangue correspondentes no Samsung Health SDK para Android e no Samsung Health Data SDK são os seguintes:

SDK Samsung Health para Android

SDK de dados de saúde da Samsung

Constantes de saúde. Glicemia

Tipo de glicose no sangue

Aqui está um exemplo de código para ler os dados de glicemia de hoje usando o SDK Samsung Health para Android.

Como ler os dados de glicemia de hoje com o SDK Samsung Health para Android.

fun readTodayBloodGlucose (
    healthDataStore: HealthDataStore
) {
    val startTime = LocalDate.now().atStartOfDay().toInstant(ZoneOffset.UTC).toEpochMilli()
    val endTime = LocalDateTime.now().toInstant(ZoneOffset.UTC).toEpochMilli()
    val handler = Handler(Looper.getMainLooper())
    val healthDataResolver = HealthDataResolver(healthDataStore, handler)
    val request: HealthDataResolver.ReadRequest =
        HealthDataResolver.ReadRequest.Builder()
            .setDataType(HealthConstants.BloodGlucose.HEALTH_DATA_TYPE)
            .setLocalTimeRange(
                HealthConstants.OxygenSaturation.START_TIME,
                HealthConstants.OxygenSaturation.TIME_OFFSET, startTime, endTime
            ).build()
    try {
        healthDataResolver.read(request).setResultListener { result ->
            try {
                result.forEach { healthData ->
                    val measurementStartTime =
                        Instant.ofEpochMilli(healthData.getLong(HealthConstants.BloodGlucose.START_TIME))
                    val bloodGlucose = healthData.getFloat(HealthConstants.BloodGlucose.GLUCOSE)
                    //Refer to the documentation for MEAL_TYPE, MEASUREMENT_TYPE, SAMPLE_SOURCE_TYPE mapping
                    val mealType = healthData.getInt(HealthConstants.BloodGlucose.MEAL_TYPE)
                    val measurementType =
                        healthData.getInt(HealthConstants.BloodGlucose.MEASUREMENT_TYPE)
                    val sampleSourceType =
                        healthData.getInt(HealthConstants.BloodGlucose.SAMPLE_SOURCE_TYPE)
                }
            } finally {
                result.close()
            }
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

Ao usar o SDK de dados de saúde da Samsung para ler os dados de glicose no sangue de hoje, o resultado é o seguinte:

Analisando os dados de glicemia de hoje com o SDK de Dados de Saúde da Samsung.

fun readTodayBloodGlucose(
    healthDataStore: HealthDataStore
) {
    val startTime = LocalDate.now().atStartOfDay().toInstant(ZoneOffset.UTC).toEpochMilli()
    val endTime = LocalDateTime.now().toInstant(ZoneOffset.UTC).toEpochMilli()
    val handler = Handler(Looper.getMainLooper())
    val healthDataResolver = HealthDataResolver(healthDataStore, handler)
    val request: HealthDataResolver.ReadRequest =
        HealthDataResolver.ReadRequest.Builder()
            .setDataType(HealthConstants.BloodGlucose.HEALTH_DATA_TYPE)
            .setLocalTimeRange(
                HealthConstants.OxygenSaturation.START_TIME,
                HealthConstants.OxygenSaturation.TIME_OFFSET, startTime, endTime
            ).build()
    try {
        healthDataResolver.read(request).setResultListener { result ->
            try {
                result.forEach { healthData ->
                    val measurementStartTime =
                        Instant.ofEpochMilli(healthData.getLong(HealthConstants.BloodGlucose.START_TIME))
                    val bloodGlucose = healthData.getFloat(HealthConstants.BloodGlucose.GLUCOSE)
                    //Refer to the documentation for MEAL_TYPE, MEASUREMENT_TYPE, SAMPLE_SOURCE_TYPE mapping
                    val mealType = healthData.getInt(HealthConstants.BloodGlucose.MEAL_TYPE)
                    val measurementType =
                        healthData.getInt(HealthConstants.BloodGlucose.MEASUREMENT_TYPE)
                    val sampleSourceType =
                        healthData.getInt(HealthConstants.BloodGlucose.SAMPLE_SOURCE_TYPE)
                }
            } finally {
                result.close()
            }
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

O código para gravar dados de sono ao usar o SDK do Samsung Health para Android é o seguinte.

Gravação de dados de glicemia com o SDK Samsung Health para Android

fun insertBloodGlucoseData(healthDataStore: HealthDataStore) {
    val handler = Handler(Looper.getMainLooper())
    val healthDataResolver = HealthDataResolver(healthDataStore, handler)
    val healthDeviceManager = HealthDeviceManager(healthDataStore)

    val tenMinutesAsSeconds = 600L
    val startTime = Instant.now().minusSeconds(tenMinutesAsSeconds)
    val timeOffset = TimeZone.getDefault().getOffset(startTime.toEpochMilli())
    val glucose = 4.8f

    val bloodGlucoseData = HealthData().apply {
        sourceDevice = healthDeviceManager.localDevice.uuid
        putLong(
            HealthConstants.BloodPressure.START_TIME, startTime.toEpochMilli()
        )
        putLong(HealthConstants.BloodGlucose.TIME_OFFSET, timeOffset.toLong())
        putFloat(HealthConstants.BloodGlucose.GLUCOSE, glucose)
        putInt(
            HealthConstants.BloodGlucose.MEASUREMENT_TYPE,
            HealthConstants.BloodGlucose.MEASUREMENT_TYPE_WHOLE_BLOOD
        )
        putInt(
            HealthConstants.BloodGlucose.MEAL_TYPE,
            HealthConstants.BloodGlucose.MEAL_TYPE_FASTING
        )
    }

    val insertRequest = InsertRequest.Builder()
        .setDataType(HealthConstants.BloodGlucose.HEALTH_DATA_TYPE)
        .build()
    insertRequest.addHealthData(bloodGlucoseData)

    try {
        val insertResult = healthDataResolver.insert(insertRequest).await()
        if (insertResult.status != BaseResult.STATUS_SUCCESSFUL) {
            Log.i(
                MainActivity.APP_TAG,
                "Error inserting blood glucose data. Error code: ${insertResult.status}"
            )
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

Segue um exemplo de código para gravar dados de glicemia usando o SDK de dados de saúde da Samsung.

Gravação de dados de glicemia com o SDK de dados de saúde da Samsung

suspend fun insertBloodGlucoseData(healthDataStore: HealthDataStore) {
    val startTime = LocalDateTime.now().minusMinutes(10)
    val glucose = 4.8f
    try {
        val healthDataPoint = HealthDataPoint.builder()
            .setLocalStartTime(startTime)
            .setLocalEndTime(startTime)
            .addFieldData(DataType.BloodGlucoseType.GLUCOSE_LEVEL, glucose)
            .addFieldData(
                DataType.BloodGlucoseType.MEASUREMENT_TYPE,
                DataType.BloodGlucoseType.MeasurementType.WHOLE_BLOOD
            )
            .addFieldData(
                DataType.BloodGlucoseType.MEAL_STATUS,
                DataType.BloodGlucoseType.MealStatus.FASTING
            )
            .build()

        val insertDataRequest = DataTypes.BLOOD_GLUCOSE.insertDataRequestBuilder
            .addData(healthDataPoint)
            .build()

        healthDataStore.insertData(insertDataRequest)
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

Oxigênio no sangue

Os tipos de dados de oxigenação sanguínea correspondentes no Samsung Health SDK para Android e no Samsung Health Data SDK são os seguintes:

SDK Samsung Health para Android

SDK de dados de saúde da Samsung

HealthConstants.OxygenSaturationType

Tipo de oxigênio no sangue

O código de exemplo para ler os dados mais recentes de oxigenação sanguínea ao usar o SDK Samsung Health para Android é o seguinte.

Como ler os dados mais recentes de oxigenação sanguínea com o SDK Samsung Health para Android.

fun readLatestBloodOxygen(
    healthDataStore: HealthDataStore
) {
    val resultOffset = 0;
    val resultCount = 1
    val handler = Handler(Looper.getMainLooper())
    val healthDataResolver = HealthDataResolver(healthDataStore, handler)
    val request: HealthDataResolver.ReadRequest =
        HealthDataResolver.ReadRequest.Builder()
            .setDataType(HealthConstants.OxygenSaturation.HEALTH_DATA_TYPE)
            .setSort(HealthConstants.OxygenSaturation.START_TIME, SortOrder.DESC)
            .setResultCount(resultOffset, resultCount)
            .build()
    try {
        healthDataResolver.read(request).setResultListener { result ->
            try {
                result.lastOrNull()?.let { healthData ->
                    val bloodOxygen = healthData.getFloat(HealthConstants.OxygenSaturation.SPO2)
                    val measurementStartTime =
                        Instant.ofEpochMilli(healthData.getLong(HealthConstants.OxygenSaturation.START_TIME))
                }
            } finally {
                result.close()
            }
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

Ao usar o SDK de dados de saúde da Samsung para ler os dados mais recentes de oxigênio no sangue, o processo é o seguinte:

Leia os dados mais recentes de oxigenação sanguínea com o SDK de Dados de Saúde da Samsung.

suspend fun readLatestBloodOxygen(
    healthDataStore: HealthDataStore
) {
    val resultCount = 1
    val readRequest = DataTypes.BLOOD_OXYGEN.readDataRequestBuilder
        .setOrdering(Ordering.DESC)
        .setLimit(resultCount)
        .build()
    try {
        val result = healthDataStore.readData(readRequest)
        result.dataList.lastOrNull()?.let { dataPoint ->
            val bloodOxygen = dataPoint.getValue(DataType.BloodOxygenType.OXYGEN_SATURATION)
            val measurementStartTime = dataPoint.startTime
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

Aqui está um exemplo de código para registrar dados de oxigenação sanguínea ao usar o SDK Samsung Health para Android.

Gravação de dados de oxigenação sanguínea com o SDK Samsung Health para Android

fun insertBloodOxygenData(
    healthDataStore: HealthDataStore
) {
    val bloodOxygen = 98F
    val tenMinutesAsSeconds = 10L * 60L
    val zoneId = ZoneOffset.systemDefault()
    val time = LocalDateTime.now().minusSeconds(tenMinutesAsSeconds).atZone(zoneId)
        .toInstant().toEpochMilli()
    val timeOffset = TimeZone.getDefault().getOffset(time).toLong()
    val mHealthDataResolver =
        HealthDataResolver(healthDataStore, Handler(Looper.getMainLooper()))
    val healthDeviceManager = HealthDeviceManager(healthDataStore)
    val data = HealthData().apply {
        putLong(HealthConstants.OxygenSaturation.START_TIME, time)
        putLong(HealthConstants.OxygenSaturation.END_TIME, time)
        putLong(HealthConstants.OxygenSaturation.TIME_OFFSET, timeOffset)
        putFloat(HealthConstants.OxygenSaturation.SPO2, bloodOxygen)
        // Register local device as the source of data
        sourceDevice = healthDeviceManager.localDevice.uuid
    }

    try {
        val insertRequest = InsertRequest.Builder()
            .setDataType(HealthConstants.OxygenSaturation.HEALTH_DATA_TYPE)
            .build()
        insertRequest.addHealthData(data)

        val result = mHealthDataResolver.insert(insertRequest).await()
        Log.i(MainActivity.APP_TAG, "insert result status: ${result.status}")
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

Segue um exemplo de código para gravar dados de oxigenação sanguínea usando o SDK de dados de saúde da Samsung.

Gravação de dados de oxigenação sanguínea com o SDK de dados de saúde da Samsung

suspend fun insertBloodOxygenData(
    healthDataStore: HealthDataStore
) {
    val bloodOxygen = 98F
    val tenMinutesAsSeconds = 10L * 60L
    val time = LocalDateTime.now().minusSeconds(tenMinutesAsSeconds)
    val zoneId = ZoneOffset.systemDefault()
    val zoneOffset = zoneId.rules.getOffset(time)

    try {
        val healthDataPoint = HealthDataPoint.builder()
            .addFieldData(DataType.BloodOxygenType.OXYGEN_SATURATION, bloodOxygen)
            .setLocalStartTime(time, zoneOffset)
            .setLocalEndTime(time, zoneOffset)
            .build()
        val insertRequest = DataTypes.BLOOD_OXYGEN.insertDataRequestBuilder
            .addData(healthDataPoint)
            .build()

        healthDataStore.insertData(insertRequest)
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

Pressão arterial

Os tipos de dados de pressão arterial correspondentes no Samsung Health SDK para Android e no Samsung Health Data SDK são os seguintes:

SDK Samsung Health para Android

SDK de dados de saúde da Samsung

Constantes de saúde.Pressão arterial

Tipo de pressão arterial

O código para ler os dados mais recentes de pressão arterial ao usar o SDK do Samsung Health para Android é o seguinte.

Como ler os dados mais recentes de pressão arterial com o SDK Samsung Health para Android.

fun readLatestBloodPressure(
    healthDataStore: HealthDataStore
) {
    val resultOffset = 0;
    val resultCount = 1
    val handler = Handler(Looper.getMainLooper())
    val healthDataResolver = HealthDataResolver(healthDataStore, handler)
    val request: HealthDataResolver.ReadRequest =
        HealthDataResolver.ReadRequest.Builder()
            .setDataType(HealthConstants.BloodPressure.HEALTH_DATA_TYPE)
            .setSort(HealthConstants.BloodPressure.START_TIME, SortOrder.DESC)
            .setResultCount(resultOffset, resultCount)
            .build()
    try {
        healthDataResolver.read(request).setResultListener { result ->
            try {
                result?.lastOrNull()?.let { healthData ->
                    val startTime =
                        Instant.ofEpochMilli(healthData.getLong(HealthConstants.BloodPressure.START_TIME))
                    val systolicPressure =
                        healthData.getFloat(HealthConstants.BloodPressure.SYSTOLIC)
                    val diastolicPressure =
                        healthData.getFloat(HealthConstants.BloodPressure.DIASTOLIC)
                    val mean = healthData.getFloat(HealthConstants.BloodPressure.MEAN)
                    val pulse = healthData.getInt(HealthConstants.BloodPressure.PULSE)
                    val sourcePackageName =
                        healthData.getString(HealthConstants.Common.PACKAGE_NAME)
                    val sourceDeviceID =
                        healthData.getString(HealthConstants.Common.DEVICE_UUID)
                }
            } finally {
                result.close()
            }
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

Ao usar o SDK de dados de saúde da Samsung para ler os dados mais recentes de pressão arterial, o processo é o seguinte:

Leia os dados mais recentes de pressão arterial com o SDK de dados de saúde da Samsung.

suspend fun readLatestBloodPressure(
    healthDataStore: HealthDataStore
) {
    val resultCount = 1
    val readRequest = DataTypes.BLOOD_PRESSURE.readDataRequestBuilder
        .setOrdering(Ordering.DESC)
        .setLimit(resultCount)
        .build()
    try {
        val result = healthDataStore.readData(readRequest)
        result.dataList.lastOrNull()?.let { dataPoint ->
            val startTime = dataPoint.startTime
            val systolicPressure = dataPoint.getValue(DataType.BloodPressureType.SYSTOLIC)
            val diastolicPressure = dataPoint.getValue(DataType.BloodPressureType.DIASTOLIC)
            val mean = dataPoint.getValue(DataType.BloodPressureType.MEAN)
            val pulse = dataPoint.getValue(DataType.BloodPressureType.PULSE_RATE)
            val sourcePackageName = dataPoint.dataSource?.appId
            val sourceDeviceId = dataPoint.dataSource?.deviceId
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

O código para gravar dados de pressão arterial ao usar o SDK Samsung Health para Android é o seguinte.

Gravação de dados de pressão arterial com o SDK Samsung Health para Android

fun insertBloodPressureData(healthDataStore: HealthDataStore) {
    val handler = Handler(Looper.getMainLooper())
    val healthDataResolver = HealthDataResolver(healthDataStore, handler)
    val healthDeviceManager = HealthDeviceManager(healthDataStore)

    val tenMinutesAsSeconds = 600L
    val startTime = Instant.now().minusSeconds(tenMinutesAsSeconds)
    val timeOffset = TimeZone.getDefault().getOffset(startTime.toEpochMilli())
    val systolic = 119f
    val diastolic = 87f
    val mean = 0f

    val bloodPressureData = HealthData().apply {
        sourceDevice = healthDeviceManager.localDevice.uuid
        putLong(HealthConstants.BloodPressure.START_TIME, startTime.toEpochMilli())
        putLong(HealthConstants.BloodPressure.TIME_OFFSET, timeOffset.toLong())
        putFloat(HealthConstants.BloodPressure.SYSTOLIC, systolic)
        putFloat(HealthConstants.BloodPressure.DIASTOLIC, diastolic)
        putFloat(HealthConstants.BloodPressure.MEAN, mean)
    }

    val insertRequest = InsertRequest.Builder()
        .setDataType(HealthConstants.BloodPressure.HEALTH_DATA_TYPE)
        .build()
    insertRequest.addHealthData(bloodPressureData)

    try {
        val insertResult = healthDataResolver.insert(insertRequest).await()
        if (insertResult.status != BaseResult.STATUS_SUCCESSFUL) {
            Log.i(
                MainActivity.APP_TAG,
                "Error inserting blood pressure data. Error code: ${insertResult.status}"
            )
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

Segue um exemplo de código para gravar dados de pressão arterial usando o SDK de dados de saúde da Samsung.

Gravação de dados de pressão arterial com o SDK de dados de saúde da Samsung

suspend fun insertBloodPressureData(healthDataStore: HealthDataStore) {
    val startTime = LocalDateTime.now().minusMinutes(10)
    val systolic = 119f
    val diastolic = 87f
    val mean = 0f
    try {
        val healthDataPoint = HealthDataPoint.builder()
            .setLocalStartTime(startTime)
            .addFieldData(DataType.BloodPressureType.SYSTOLIC, systolic)
            .addFieldData(DataType.BloodPressureType.DIASTOLIC, diastolic)
            .addFieldData(DataType.BloodPressureType.MEAN, mean)
            .build()

        val insertDataRequest = DataTypes.BLOOD_PRESSURE.insertDataRequestBuilder
            .addData(healthDataPoint)
            .build()

        healthDataStore.insertData(insertDataRequest)
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

Temperatura corporal

Os tipos de dados de temperatura corporal correspondentes no Samsung Health SDK para Android e no Samsung Health Data SDK são os seguintes:

SDK Samsung Health para Android

SDK de dados de saúde da Samsung

Constantes de saúde.Temperatura corporal

Tipo de temperatura corporal

Aqui está um exemplo de código que lê os dados de temperatura corporal de hoje ao usar o SDK Samsung Health para Android.

Como ler os dados de temperatura corporal de hoje com o SDK Samsung Health para Android.

fun readTodayBodyTemperature(
    healthDataStore: HealthDataStore
) {
    val startTime = LocalDate.now().atStartOfDay().toInstant(ZoneOffset.UTC).toEpochMilli()
    val endTime = LocalDateTime.now().toInstant(ZoneOffset.UTC).toEpochMilli()
    val handler = Handler(Looper.getMainLooper())
    val healthDataResolver = HealthDataResolver(healthDataStore, handler)
    val readRequest: HealthDataResolver.ReadRequest =
        HealthDataResolver.ReadRequest.Builder()
            .setDataType(HealthConstants.BodyTemperature.HEALTH_DATA_TYPE)
            .setLocalTimeRange(
                HealthConstants.BodyTemperature.START_TIME,
                HealthConstants.BodyTemperature.TIME_OFFSET,
                startTime,
                endTime
            ).build()

    try {
        healthDataResolver.read(readRequest).setResultListener { result ->
            try {
                result.lastOrNull()?.let { healthData ->
                    val measurementStartTime =
                        Date(healthData.getLong(HealthConstants.BodyTemperature.START_TIME))
                    val bodyTemperature =
                        healthData.getFloat(HealthConstants.BodyTemperature.TEMPERATURE)
                }
            } finally {
                result.close()
            }
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

Ao usar o SDK de dados de saúde da Samsung para ler os dados de temperatura corporal de hoje, o processo é o seguinte:

Leitura da temperatura corporal de hoje - SDK de dados do Samsung Health

suspend fun readTodayBodyTemperature(
    healthDataStore: com.samsung.android.sdk.health.data.HealthDataStore
) {
    val startTime = LocalDate.now().atStartOfDay()
    val endTime = LocalDateTime.now()
    val localTimeFilter = LocalTimeFilter.of(startTime, endTime)
    val readRequest = DataTypes.BODY_TEMPERATURE.readDataRequestBuilder
        .setLocalTimeFilter(localTimeFilter)
        .build()

    try {
        val result = healthDataStore.readData(readRequest)
        result.dataList.lastOrNull()?.let { dataPoint ->
            val measurementStartTime = dataPoint.startTime
            val bodyTemperature =
                dataPoint.getValue(DataType.BodyTemperatureType.BODY_TEMPERATURE)
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

Segue um exemplo de código para gravar dados de temperatura corporal usando o SDK Samsung Health para Android.

Gravação de dados de temperatura corporal com o SDK Samsung Health para Android

fun insertBodyTemperatureData(
    healthDataStore: HealthDataStore
) {
    val bodyTemperature = 37F
    val tenMinutesAsSeconds = 10L * 60L
    val zoneId = ZoneOffset.systemDefault()
    val startTime = LocalDateTime.now().minusSeconds(tenMinutesAsSeconds).atZone(zoneId)
        .toInstant().toEpochMilli()
    val timeOffset = TimeZone.getDefault().getOffset(startTime).toLong()
    val mHealthDataResolver =
        HealthDataResolver(healthDataStore, Handler(Looper.getMainLooper()))
    val healthDeviceManager = HealthDeviceManager(healthDataStore)
    val data = HealthData().apply {
        putLong(HealthConstants.BodyTemperature.START_TIME, startTime)
        putLong(HealthConstants.BodyTemperature.TIME_OFFSET, timeOffset)
        putFloat(HealthConstants.BodyTemperature.TEMPERATURE, bodyTemperature)
        // Register local device as the source of data
        sourceDevice = healthDeviceManager.localDevice.uuid
    }

    try {
        val insertRequest = InsertRequest.Builder()
            .setDataType(HealthConstants.BodyTemperature.HEALTH_DATA_TYPE)
            .build()
        insertRequest.addHealthData(data)

        val result = mHealthDataResolver.insert(insertRequest).await()
        Log.i(MainActivity.APP_TAG, "insert result status: ${result.status}")
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

Ao usar o SDK de dados de saúde da Samsung para gravar dados de temperatura corporal, o procedimento é o seguinte:

Gravação de dados de temperatura corporal com o SDK de dados de saúde da Samsung

suspend fun insertBodyTemperatureData(
    healthDataStore: HealthDataStore
) {
    val bodyTemperature = 37F
    val tenMinutesAsSeconds = 10L * 60L
    val time = LocalDateTime.now().minusSeconds(tenMinutesAsSeconds)
    val zoneId = ZoneOffset.systemDefault()
    val zoneOffset = zoneId.rules.getOffset(time)

    try {
        val healthDataPoint = HealthDataPoint.builder()
            .addFieldData(DataType.BodyTemperatureType.BODY_TEMPERATURE, bodyTemperature)
            .setLocalStartTime(time, zoneOffset)
            .setLocalEndTime(time, zoneOffset)
            .build()
        val insertRequest = DataTypes.BODY_TEMPERATURE.insertDataRequestBuilder
            .addData(healthDataPoint)
            .build()

        healthDataStore.insertData(insertRequest)
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

Perfil do usuário

Os tipos de dados de perfil de usuário correspondentes no Samsung Health SDK para Android e no Samsung Health Data SDK são os seguintes:

SDK Samsung Health para Android

SDK de dados de saúde da Samsung

Perfil de usuário de saúde

Tipo de dados do perfil do usuário

Segue um exemplo de código para obter dados de perfil do usuário ao usar o SDK do Samsung Health para Android.

Obtendo dados de perfil do usuário com o SDK do Samsung Health para Android

fun readUserProfile(
    healthDataStore: HealthDataStore
) {
    val userProfile = HealthUserProfile.getProfile(healthDataStore)
    val gender = genderNameById(userProfile.gender)
    val height = userProfile.height
    val weight = userProfile.weight
}

fun genderNameById(id: Int): String {
    return when (id) {
        HealthUserProfile.GENDER_MALE -> "MALE"
        HealthUserProfile.GENDER_FEMALE -> "FEMALE"
        else -> "UNKNOWN"
    }
}

Segue um exemplo de código para obter dados de perfil do usuário ao usar o SDK de dados do Samsung Health.

Obtenção de dados de perfil do usuário com o SDK de dados do Samsung Health

suspend fun readUserProfile(
    healthDataStore: HealthDataStore
) {
    val readRequest = DataTypes.USER_PROFILE.readDataRequestBuilder
        .build()
    try {
        val result = healthDataStore.readData(readRequest)
        result.dataList.lastOrNull()?.let { dataPoint ->
            val gender = dataPoint.getValue(DataType.UserProfileDataType.GENDER)
            val height = dataPoint.getValue(DataType.UserProfileDataType.HEIGHT)
            val weight = dataPoint.getValue(DataType.UserProfileDataType.WEIGHT)
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

Dispositivo de origem dos dados

O código para obter informações do dispositivo de origem que forneceu dados de sono ao usar o SDK do Samsung Health para Android é o seguinte.

Obtendo informações do dispositivo de origem dos dados com o SDK do Samsung Health para Android

fun getSourceDeviceInfoOfSleepData(
    healthDataStore: HealthDataStore
) {
    val resultCount = 1
    val resultOffset = 0
    val handler = Handler(Looper.getMainLooper())
    val healthDataResolver = HealthDataResolver(healthDataStore, handler)
    val request: HealthDataResolver.ReadRequest =
        HealthDataResolver.ReadRequest.Builder()
            .setDataType(HealthConstants.Sleep.HEALTH_DATA_TYPE)
            .setSort(HealthConstants.Sleep.START_TIME, SortOrder.DESC)
            .setResultCount(resultOffset, resultCount)
            .build()
    try {
        healthDataResolver.read(request).setResultListener { result ->
            try {
                result?.forEach { healthData ->
                    val deviceId = healthData.getString(HealthConstants.Sleep.DEVICE_UUID)
                    val healthDevice =
                        HealthDeviceManager(healthDataStore).getDeviceByUuid(deviceId)
                    val deviceName = healthDevice.customName
                    val deviceType = deviceGroupNameById(healthDevice.group)
                }
            } finally {
                result.close()
            }
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

fun deviceGroupNameById(id: Int): String {
    return when (id) {
        HealthDevice.GROUP_MOBILE -> "MOBILE"
        HealthDevice.GROUP_EXTERNAL -> "EXTERNAL"
        HealthDevice.GROUP_COMPANION -> "COMPANION or WATCH"
        else -> "UNKNOWN"
    }
}

Para obter informações sobre o dispositivo de origem que forneceu dados de sono ao usar o SDK de dados do Samsung Health, o seguinte código de exemplo pode ser usado.

Obtendo informações do dispositivo de origem dos dados com o SDK de dados do Samsung Health

suspend fun getSourceDeviceInfoOfSleepData(
    healthDataStore: HealthDataStore
) {
    val resultCount = 1
    val readRequest = DataTypes.SLEEP.readDataRequestBuilder
        .setOrdering(Ordering.DESC)
        .setLimit(resultCount)
        .build()
    try {
        val result = healthDataStore.readData(readRequest)
        result.dataList.forEach { sleepData ->
            val deviceManager = healthDataStore.getDeviceManager()
            sleepData.dataSource?.let { dataSource ->
                val device = deviceManager.getDevice(dataSource.deviceId)
                val deviceId = device?.id
                val deviceName = device?.name
                val deviceType = device?.deviceType
            }
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

Está com algum problema?

Mantemos um canal de suporte para desenvolvedores no site da Samsung Developers. Caso encontre algum problema ou tenha alguma dúvida, acesse https://developer.samsung.com/dev-support e envie sua solicitação após fazer login em sua conta Samsung.

Comentários

Postagens mais visitadas deste blog

Razer anuncia Wolverine Ultimate, o controle para Xbox One e PC mais personalizável do mercado

HyperX lança kit de teclas texturizadas e em novas cores para personalização de teclados gamers

Prepare o bolso! Pré-venda de GTA 6 é listada por mais de R$ 650 na Europa