Lettura di dati non elaborati

L'esempio seguente mostra come leggere i dati non elaborati nell'ambito del flusso di lavoro comune.

Lettura di dati

Connessione Salute consente alle app di leggere i dati dal data store quando l'app è in primo piano e in background:

  • Letture in primo piano: in genere puoi leggere i dati da Connessione Salute quando la tua app è in primo piano. In questi casi, ti consigliamo di utilizzare un servizio in primo piano per eseguire questa operazione nel caso in cui l'utente o il sistema metta la tua app in background durante un'operazione di lettura.

  • Letture in background: richiedendo un'autorizzazione aggiuntiva all'utente, puoi leggere i dati dopo che l'utente o il sistema ha messo l'app in background. Consulta l'esempio completo di lettura in background.

Il tipo di dati Passaggi in Connessione Salute acquisisce il numero di passi compiuti da un utente tra una lettura e l'altra. Il conteggio dei passi rappresenta una misurazione comune su piattaforme per la salute, il fitness e il benessere. Connessione Salute semplifica la lettura e la scrittura dei dati relativi al numero di passi.

Per leggere i record, crea un ReadRecordsRequest e forniscilo quando chiami readRecords.

L'esempio seguente mostra come leggere i dati relativi al numero di passi di un utente in un determinato periodo di tempo. Per un esempio dettagliato con SensorManager, consulta la guida ai dati sul conteggio dei passi.

suspend fun readStepsByTimeRange(
    healthConnectClient: HealthConnectClient,
    startTime: Instant,
    endTime: Instant
) {
    try {
        val response = healthConnectClient.readRecords(
            ReadRecordsRequest(
                StepsRecord::class,
                timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
            )
        )
        for (stepRecord in response.records) {
            // Process each step record
        }
    } catch (e: Exception) {
        // Run error handling here
    }
}

Esempio di lettura in background

Per leggere i dati in background, dichiara la seguente autorizzazione nel file manifest:

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

L'esempio seguente mostra come leggere i dati relativi al numero di passi in background per un utente in un determinato periodo di tempo utilizzando WorkManager:

class ScheduleWorker(private val appContext: Context, workerParams: WorkerParameters):
    CoroutineWorker(appContext, workerParams) {

    override suspend fun doWork(): Result {
        // Read data and process it.
        ...

        // Return success indicating successful data retrieval
        return Result.success()
    }
}

if (healthConnectClient
    .features
    .getFeatureStatus(
    HealthConnectFeatures.FEATURE_READ_HEALTH_DATA_IN_BACKGROUND
    ) == HealthConnectFeatures.FEATURE_STATUS_AVAILABLE) {

    // Check if necessary permission is granted
    val grantedPermissions = healthConnectClient.permissionController.getGrantedPermissions()

    if (PERMISSION_READ_HEALTH_DATA_IN_BACKGROUND !in grantedPermissions) {
        // Perform read in foreground
        ...
    } else {
        // Schedule the periodic work request in background
        val periodicWorkRequest = PeriodicWorkRequestBuilder<ScheduleWorker>(1, TimeUnit.HOURS)
            .build()

        WorkManager.getInstance(context).enqueueUniquePeriodicWork(
            "read_health_connect",
            ExistingPeriodicWorkPolicy.KEEP,
            periodicWorkRequest
        )
    }
} else {
  // Background reading is not available, perform read in foreground
  ...
}

Il parametro ReadRecordsRequest ha un valore predefinito di pageSize pari a 1000. Se il numero di record in un singolo readResponse supera il valore pageSize della richiesta, devi eseguire l'iterazione su tutte le pagine della risposta per recuperare tutti i record utilizzando pageToken. Tuttavia, fai attenzione a evitare problemi di limitazione della frequenza.

Esempio di lettura di pageToken

Ti consigliamo di utilizzare pageToken per leggere i record al fine di recuperare tutti i dati disponibili nel periodo di tempo richiesto.

L'esempio seguente mostra come leggere tutti i record fino a quando non sono stati esausti tutti i token di pagina:

val type = HeartRateRecord::class
val endTime = Instant.now()
val startTime = endTime.minus(Duration.ofDays(7))

try {
    var pageToken: String? = null
    do {
        val readResponse =
            healthConnectClient.readRecords(
                ReadRecordsRequest(
                    recordType = type,
                    timeRangeFilter = TimeRangeFilter.between(
                        startTime,
                        endTime
                    ),
                    pageToken = pageToken
                )
            )
        val records = readResponse.records
        // Do something with records
        pageToken = readResponse.pageToken
    } while (pageToken != null)
} catch (quotaError: IllegalStateException) {
    // Backoff
}

Per informazioni sulle best practice per la lettura di set di dati di grandi dimensioni, consulta Pianificare per evitare il limite di frequenza.

Leggere i dati scritti in precedenza

Se un'app ha già scritto record in Connessione Salute, è possibile che possa leggere i dati storici. Questo vale per gli scenari in cui l'app deve essere sincronizzata di nuovo con Connessione Salute dopo che l'utente l'ha reinstallata.

Sono previste alcune limitazioni alla lettura:

  • Per Android 14 e versioni successive

    • Nessun limite storico per un'app che legge i propri dati.
    • Limite di 30 giorni per un'app che legge altri dati.
  • Per Android 13 e versioni precedenti

    • Limite di 30 giorni per la lettura di qualsiasi dato da parte dell'app.

Le limitazioni possono essere rimosse richiedendo un'autorizzazione di lettura.

Per leggere i dati storici, devi indicare il nome del pacchetto come oggetto DataOrigin nel parametro dataOriginFilter del ReadRecordsRequest.

L'esempio seguente mostra come indicare il nome di un pacchetto durante la lettura dei record Steps:

try {
    val response =  healthConnectClient.readRecords(
        ReadRecordsRequest(
            recordType = StepsRecord::class,
            timeRangeFilter = TimeRangeFilter.between(startTime, endTime),
            dataOriginFilter = setOf(DataOrigin("com.my.package.name"))
        )
    )
    for (record in response.records) {
        // Process each record
    }
} catch (e: Exception) {
    // Run error handling here
}

Leggere i dati precedenti a 30 giorni

Per impostazione predefinita, tutte le applicazioni possono leggere i dati di Connessione Salute fino a 30 giorni prima della prima concessione dell'autorizzazione.

Se devi estendere le autorizzazioni di lettura oltre le limitazioni predefinite, richiedi il PERMISSION_READ_HEALTH_DATA_HISTORY. In caso contrario, senza questa autorizzazione, un tentativo di lettura di record risalenti a più di 30 giorni fa genera un errore.

Cronologia delle autorizzazioni per un'app eliminata

Se un utente elimina la tua app, tutte le autorizzazioni, inclusa quella di accesso alla cronologia, vengono revocate. Se l'utente reinstalla la tua app e concede di nuovo l'autorizzazione, si applicano le stesse limitazioni predefinite e la tua app può leggere i dati di Connessione Salute fino a 30 giorni prima della nuova data.

Ad esempio, supponiamo che l'utente elimini la tua app il 10 maggio 2023, la reinstalli il 15 maggio 2023 e conceda le autorizzazioni di lettura. La data più recente da cui la tua app ora può leggere i dati per impostazione predefinita è il 15 aprile 2023.