Aggiungi percorsi per l'esercizio fisico

I percorsi per l'allenamento consentono agli utenti di registrare un percorso GPS per le attività di allenamento associate e di condividere le mappe dei loro esercizi con altre app.

Questa guida descrive in che modo le app ricevono l'autorizzazione per scrivere dati dei percorsi nell'ambito di una sessione di allenamento.

Ecco un breve riepilogo della funzionalità di lettura e scrittura per i percorsi di allenamento:

  1. Le app creano una nuova autorizzazione di scrittura per i percorsi per l'allenamento.
  2. L'inserimento avviene tramite la scrittura di una sessione di allenamento con un percorso come campo.
  3. Lettura:
    1. Per il proprietario della sessione, i dati sono accessibili utilizzando una lettura delle sessioni.
    2. Da un'app di terze parti, tramite una finestra di dialogo che consente all'utente di concedere una lettura una tantum di una route.

Autorizzazioni

Le route di allenamento hanno la propria autorizzazione di scrittura di runtime (android.permission.health.WRITE_EXERCISE_ROUTE).

Per aggiungere la funzionalità di route per l'allenamento alla tua app, inizia richiedendo le autorizzazioni di scrittura per un tipo di dati specifico.

Richiesta di autorizzazione Android 14

Richiesta di autorizzazione Android 14

Richiesta di autorizzazione Android 13

Richiesta di autorizzazione Android 13

Devi anche dichiarare un'autorizzazione all'allenamento, poiché ogni percorso è associato a una sessione di allenamento (una sessione = un esercizio).

Ecco l'autorizzazione che devi dichiarare per poter scrivere i percorsi di allenamento:

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

Per leggere i percorsi per l'esercizio fisico, devi richiedere le seguenti autorizzazioni:

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

Per richiedere le autorizzazioni, usa il metodo PermissionController.createRequestPermissionResultContract() quando connetti per la prima volta la tua app a Connessione Salute. Alcune autorizzazioni che potresti voler richiedere sono:

  • Leggi i dati sullo stato di integrità, inclusi i dati delle route: HealthPermission.getReadPermission(ExerciseSessionRecord::class)
  • Scrivi dati sullo stato, inclusi i dati delle route: HealthPermission.getWritePermission(ExerciseSessionRecord::class)
  • Scrittura dei dati del percorso per l'esercizio fisico: HealthPermission.PERMISSION_WRITE_EXERCISE_ROUTE

Leggi e scrivi dati di route

Le app inseriscono un percorso scrivendo una sessione con un percorso come campo.

Se l'utente non dispone delle autorizzazioni di scrittura e la route non è impostata, non si aggiorna.

Se l'app ha un'autorizzazione di scrittura delle route e tenta di aggiornare una sessione passando in un oggetto sessione senza una route, la route esistente viene eliminata.

Ogni volta che la tua app deve leggere i dati di routing forniti da un'app di terze parti, viene visualizzata una finestra di dialogo in cui viene chiesto all'utente di consentire l'operazione di lettura.

Richiedere un percorso da una sessione

Ecco come leggere una sessione in Connessione Salute e richiedere un percorso da quella sessione:

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

Scrivere un percorso a partire da una sessione

Il seguente codice mostra come registrare una sessione che include un percorso per l'allenamento:

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))
}