Agregar rutas de ejercicio

Las rutas de ejercicio permiten a los usuarios registrar una ruta de GPS de las actividades asociadas y compartir mapas de sus entrenamientos con otras apps.

En esta guía, se describe el modo en que las apps reciben permiso para escribir datos de ruta como parte de una sesión de ejercicio.

A continuación, se incluye un breve resumen de la función de lectura y escritura de las rutas de ejercicio:

  1. Las apps crean un nuevo permiso de escritura para las rutas de ejercicio.
  2. La inserción se lleva a cabo escribiendo una sesión de ejercicio con una ruta como su campo.
  3. Lectura:
    1. El propietario de la sesión puede acceder a los datos con una lectura de la sesión
    2. Desde una app de terceros, a través de un diálogo que permite al usuario otorgar una lectura única de una ruta

Permisos

Las rutas de ejercicio tienen su propio permiso de escritura del entorno de ejecución (android.permission.health.WRITE_EXERCISE_ROUTE).

Si deseas agregar la función de ruta de ejercicio a tu app, comienza por solicitar permisos de escritura para un tipo de datos específico.

Solicitud de permiso de Android 14

Solicitud de permiso de Android 14

Solicitud de permiso de Android 13

Solicitud de permiso de Android 13

También debes declarar un permiso de ejercicio, ya que cada ruta está asociada con una sesión de ejercicio (una sesión = un entrenamiento).

Este es el permiso que debes declarar para poder escribir rutas de ejercicio:

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

Para leer las rutas de ejercicio, debes solicitar los siguientes permisos:

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

Para solicitar permisos, usa el método PermissionController.createRequestPermissionResultContract() cuando conectes tu app por primera vez a Health Connect. Estos son varios permisos que puedes solicitar:

  • Leer datos de estado, incluidos los datos de ruta: HealthPermission.getReadPermission(ExerciseSessionRecord::class)
  • Escribir datos de estado, incluidos los datos de ruta: HealthPermission.getWritePermission(ExerciseSessionRecord::class)
  • Escribir datos de ruta de ejercicio: HealthPermission.PERMISSION_WRITE_EXERCISE_ROUTE

Cómo leer y escribir datos de ruta

Para insertar una ruta, las apps escriben una sesión con una ruta como un campo.

Si el usuario no tiene permisos de escritura y no está configurada la ruta, esta no se actualiza.

Si tu app tiene un permiso de escritura de ruta y trata de actualizar una sesión pasando un objeto de sesión sin una ruta, se borra la ruta existente.

Cada vez que tu app necesite leer datos de rutas proporcionados por una app de terceros, aparecerá un diálogo en el que se le solicitará al usuario que permita la operación de lectura.

Cómo solicitar una ruta desde una sesión

A continuación, se detalla cómo leer una sesión en Health Connect y solicitar una ruta desde esa sesión:

suspend fun readExerciseSessionAndRoute() {
    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()

    // 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.
    }
  }

Cómo escribir una ruta desde una sesión

En el siguiente código, se muestra cómo registrar una sesión que incluye una ruta de ejercicio:

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.parse("2023-01-01T10:00:00.00Z")
    val sessionDuration = Duration.ofMinutes(20)

    val exerciseRoute =
      if (getPermissions.contains(PERMISSION_EXERCISE_ROUTE_WRITE) {
        ExerciseRoute(
          listOf(
            ExerciseRoute.Location(
              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(
              time = sessionStartTime.plus(sessionDuration)
              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 = /* starting time in milliseconds */,
            startZoneOffset = ZoneOffset.UTC,
            endTime = sessionStartTime.plus(sessionDuration),
            endZoneOffset = ZoneOffset.UTC,
            exerciseType = ExerciseSessionRecord.EXERCISE_TYPE_BIKING,
            title = "Morning Bike Ride",
            exerciseRoute = exerciseRoute
        )

    healthConnectClient.insertRecords(listOf(exerciseSessionRecord))
}