Adicionar trajetos de exercícios

Este guia é compatível com a versão 1.1.0-alpha12 do Health Connect.

Os trajetos de exercícios permitem que os usuários acompanhem por GPS o trajeto das atividades físicas associadas e compartilhem mapas dos treinos deles com outros apps.

Este guia fornece informações sobre como solicitar permissões ao usuário e também descreve como os apps recebem a permissão para gravar dados de trajeto como parte de uma sessão de exercício.

Confira um breve resumo da funcionalidade de leitura e gravação de trajetos de exercícios:

  1. Os apps criam uma nova permissão de gravação para trajetos de exercícios.
  2. A inserção acontece com a criação de uma sessão de exercício com um trajeto como campo.
  3. Leitura:
    1. Para o proprietário da sessão, os dados são acessados usando uma leitura de sessão.
    2. Em um app de terceiros, em uma caixa de diálogo que permite ao usuário conceder uma leitura única de um trajeto.

Solicitar permissões do usuário

Depois de criar uma instância de cliente, seu app precisa solicitar permissões ao usuário. Os usuários precisam ter permissão para conceder ou negar permissões a qualquer momento.

Para fazer isso, crie um conjunto de permissões para os tipos de dados necessários. Verifique se as permissões no conjunto foram declaradas no manifesto do Android primeiro.

// Create a set of permissions for required data types
val PERMISSIONS =
    setOf(
  HealthPermission.getReadPermission(ExerciseSessionRecord::class),
  HealthPermission.getWritePermission(ExerciseSessionRecord::class)
)

Use getGrantedPermissions para conferir se o app já tem as permissões necessárias. Caso contrário, use createRequestPermissionResultContract para solicitar essas permissões. A tela de permissões da Conexão Saúde será exibida.

// Create the permissions launcher
val requestPermissionActivityContract = PermissionController.createRequestPermissionResultContract()

val requestPermissions = registerForActivityResult(requestPermissionActivityContract) { granted ->
  if (granted.containsAll(PERMISSIONS)) {
    // Permissions successfully granted
  } else {
    // Lack of required permissions
  }
}

suspend fun checkPermissionsAndRun(healthConnectClient: HealthConnectClient) {
  val granted = healthConnectClient.permissionController.getGrantedPermissions()
  if (granted.containsAll(PERMISSIONS)) {
    // Permissions already granted; proceed with inserting or reading data
  } else {
    requestPermissions.launch(PERMISSIONS)
  }
}

Como os usuários podem conceder ou revogar permissões a qualquer momento, seu app precisa verificar periodicamente as permissões concedidas e processar cenários em que a permissão é perdida.

Permissões de leitura e gravação de trajetos de exercício

Os trajetos de exercícios têm a própria permissão de gravação no momento de execução (android.permission.health.WRITE_EXERCISE_ROUTE).

Para adicionar a capability de trajeto de exercício ao app, solicite permissões de gravação de um tipo específico de dado.

Você também precisa declarar uma permissão de exercício, já que cada trajeto está associado a uma sessão (o que é igual a um treino).

Confira a permissão necessária para poder gravar trajetos de exercícios:

<application>
  <uses-permission
android:name="android.permission.health.WRITE_EXERCISE_ROUTE" />
  <uses-permission
android:name="android.permission.health.WRITE_EXERCISE" />
...
</application>

Para ler trajetos de exercícios, você precisa solicitar as seguintes permissões:

<application>
  <uses-permission
android:name="android.permission.health.READ_EXERCISE_ROUTES" />
  <uses-permission
android:name="android.permission.health.READ_EXERCISE" />
...
</application>

Para solicitar permissões, use o método PermissionController.createRequestPermissionResultContract() ao conectar seu app ao Conexão Saúde pela primeira vez. Várias permissões que podem ser solicitadas são:

  • Ler dados de integridade, incluindo dados de trajetos: HealthPermission.getReadPermission(ExerciseSessionRecord::class)
  • Gravar dados de saúde, incluindo dados de trajetos: HealthPermission.getWritePermission(ExerciseSessionRecord::class)
  • Gravar dados de trajeto de exercício: HealthPermission.PERMISSION_WRITE_EXERCISE_ROUTE

Ler e gravar dados de trajeto

Os apps inserem um trajeto ao gravar uma sessão com um trajeto como campo.

Se o usuário não tiver permissões de gravação e o trajeto não estiver definido, ele não será atualizado.

Se o app tiver uma permissão de gravação de trajeto e tentar atualizar uma sessão transmitindo um objeto de sessão sem um trajeto, o trajeto atual será excluído.

Sempre que seu app precisar ler dados de trajeto fornecidos por um app de terceiros, uma caixa de diálogo aparecerá solicitando a permissão para a operação de leitura.

Solicitar um trajeto em uma sessão

Aprenda a ler uma sessão na Conexão Saúde e solicitar um trajeto nessa sessão:

suspend fun readExerciseSessionAndRoute() {
    val endTime = Instant.now()
    val startTime = endTime.minus(Duration.ofHours(1))

    val grantedPermissions =
        healthConnectClient.permissionController.getGrantedPermissions()
    if (!grantedPermissions.contains(
          HealthPermission.getReadPermission(ExerciseSessionRecord::class))) {
        // The user doesn't allow the app to read exercise session data.
        return
    }

    val readResponse =
      healthConnectClient.readRecords(
        ReadRecordsRequest(
          ExerciseSessionRecord::class,
          TimeRangeFilter.between(startTime, endTime)
        )
      )
    val exerciseRecord = readResponse.records.first()
    val recordId = exerciseRecord.metadata.id

    // See https://developer.android.com/training/basics/intents/result#launch
    // for appropriately handling ActivityResultContract.
    val requestExerciseRouteLauncher = fragment.registerForActivityResul
    (ExerciseRouteRequestContract()) { exerciseRoute: ExerciseRoute? ->
            if (exerciseRoute != null) {
                displayExerciseRoute(exerciseRoute)
            } else {
                // Consent was denied
            }
        }

    val exerciseSessionRecord =
      healthConnectClient.readRecord(ExerciseSessionRecord::class, recordId).record

    when (val exerciseRouteResult = exerciseSessionRecord.exerciseRouteResult) {
        is ExerciseRouteResult.Data ->
            displayExerciseRoute(exerciseRouteResult.exerciseRoute)
        is ExerciseRouteResult.ConsentRequired ->
            requestExerciseRouteLauncher.launch(recordId)
        is ExerciseRouteResult.NoData -> Unit // No exercise route to show
        else -> Unit
    }
  }

  fun displayExerciseRoute(route: ExerciseRoute?) {
    val locations = route.route.orEmpty()
    for (location in locations) {
      // Handle location.
    }
  }

Gravar um trajeto em uma sessão

O código a seguir demonstra como gravar uma sessão que inclui um trajeto de exercício:

suspend fun InsertExerciseRoute(healthConnectClient: HealthConnectClient) {
    val grantedPermissions =
        healthConnectClient.permissionController.getGrantedPermissions()
    if (!grantedPermissions.contains(
          getWritePermission(ExerciseSessionRecord::class))) {
        // The user doesn't allow the app to write exercise session data.
        return
    }

    val sessionStartTime = Instant.now()
    val sessionDuration = Duration.ofMinutes(20)
    val sessionEndTime = sessionStartTime.plus(sessionDuration)

    val exerciseRoute =
        if (grantedPermissions.contains(PERMISSION_WRITE_EXERCISE_ROUTE)) ExerciseRoute(
            listOf(
                ExerciseRoute.Location(
                    // Location times must be on or after the session start time
                    time = sessionStartTime,
                    latitude = 6.5483,
                    longitude = 0.5488,
                    horizontalAccuracy = Length.meters(2.0),
                    verticalAccuracy = Length.meters(2.0),
                    altitude = Length.meters(9.0),
                ), ExerciseRoute.Location(
                    // Location times must be before the session end time
                    time = sessionEndTime.minusSeconds(1),
                    latitude = 6.4578,
                    longitude = 0.6577,
                    horizontalAccuracy = Length.meters(2.0),
                    verticalAccuracy = Length.meters(2.0),
                    altitude = Length.meters(9.2),
                )
            )
        )
        else
        // The user doesn't allow the app to write exercise route data.
            null
    val exerciseSessionRecord = ExerciseSessionRecord(
        startTime = sessionStartTime,
        startZoneOffset = ZoneOffset.UTC,
        endTime = sessionEndTime,
        endZoneOffset = ZoneOffset.UTC,
        exerciseType = ExerciseSessionRecord.EXERCISE_TYPE_BIKING,
        title = "Morning Bike Ride",
        exerciseRoute = exerciseRoute,
        metadata = Metadata.manualEntry(
            device = Device(type = Device.TYPE_PHONE)
        ),
    )
    val response = healthConnectClient.insertRecords(listOf(exerciseSessionRecord))
}