API de grabación en dispositivos móviles

La API de Recording en dispositivos móviles permite que tu app registre pasos, de manera similar a un pulsómetro que recupera datos de recuento de pasos, desde un dispositivo móvil de manera eficiente en términos de batería. Esta API no requiere una cuenta, lo que significa que no se necesita una Cuenta de Google para usar el servicio y los datos se almacenan en el dispositivo.

En esta guía, se muestra cómo usar la API de Recording en dispositivos móviles en tus experiencias de salud y fitness.

Consulta el ejemplo de la API de Recording en dispositivos móviles en GitHub para ver un ejemplo.

Detalles destacados

Existen varias funciones notables exclusivas de la API de Recording en dispositivos móviles:

  • Una vez que se inicia o se renueva la suscripción a la grabación, se puede acceder a los datos desde la suscripción más reciente, por hasta 10 días.
  • Los datos solo están disponibles cuando hay una suscripción activa. Si se quita una suscripción llamando a unsubscribe, no se podrá acceder a los datos de pasos recopilados.

Tipos de datos

La API de Recording en dispositivos móviles puede grabar los siguientes tipos de datos:

Comenzar

Para comenzar, agrega la siguiente dependencia a tu archivo build.gradle:

DSL de Kotlin

plugin {
  id("com.android.application")
}

...

dependencies {
  implementation("com.google.android.gms:play-services-fitness:21.2.0")
}

DSL de Groovy

apply plugin: 'com.android.application'

...

dependencies {
  implementation 'com.google.android.gms:play-services-fitness:21.2.0'
}

Solicita permisos

Para grabar datos con la API de Recording en dispositivos móviles, tu app deberá solicitar el siguiente permiso:

  • android.permission.ACTIVITY_RECOGNITION

Cómo realizar una verificación de la versión de los Servicios de Play

Para usar la API de Recording en dispositivos móviles, el usuario debe tener los Servicios de Google Play actualizados a la versión LOCAL_RECORDING_CLIENT_MIN_VERSION_CODE. Puedes verificar esto con el método isGooglePlayServicesAvailable:

val hasMinPlayServices = isGooglePlayServicesAvailable(context, LocalRecordingClient.LOCAL_RECORDING_CLIENT_MIN_VERSION_CODE)

if(hasMinPlayServices != ConnectionResult.SUCCESS) {
  // Prompt user to update their device's Google Play services app and return
}

// Continue with Recording API functions

De lo contrario, si la versión de los Servicios de Google Play del usuario es demasiado baja, el sistema arroja una excepción ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED.

Suscríbete a los datos de Fitness

Para solicitar la recopilación en segundo plano de datos de pasos, usa el método subscribe, como se muestra en el siguiente fragmento de código:

val localRecordingClient = FitnessLocal.getLocalRecordingClient(this)
// Subscribe to steps data
localRecordingClient.subscribe(LocalDataType.TYPE_STEP_COUNT_DELTA)
  .addOnSuccessListener {
    Log.i(TAG, "Successfully subscribed!")
  }
  .addOnFailureListener { e ->
    Log.w(TAG, "There was a problem subscribing.", e)
  }

Leer y procesar datos de Fitness

Una vez que te hayas suscrito, solicita los datos con el método readData. Luego, puedes obtener LocalDataPoints del LocalDataSet resultante si creas un LocalDataReadRequest, como se muestra en el siguiente fragmento de código:

val endTime = LocalDateTime.now().atZone(ZoneId.systemDefault())
val startTime = endTime.minusWeeks(1)
val readRequest =
  LocalDataReadRequest.Builder()
    // The data request can specify multiple data types to return,
    // effectively combining multiple data queries into one call.
    // This example demonstrates aggregating only one data type.
    .aggregate(LocalDataType.TYPE_STEP_COUNT_DELTA)
    // Analogous to a "Group By" in SQL, defines how data should be
    // aggregated. bucketByTime allows bucketing by time span.
    .bucketByTime(1, TimeUnit.DAYS)
    .setTimeRange(startTime.toEpochSecond(), endTime.toEpochSecond(), TimeUnit.SECONDS)
    .build()

  localRecordingClient.readData(readRequest).addOnSuccessListener { response ->
    // The aggregate query puts datasets into buckets, so flatten into a
    // single list of datasets.
    for (dataSet in response.buckets.flatMap { it.dataSets }) {
      dumpDataSet(dataSet)
    }
  }
  .addOnFailureListener { e ->
    Log.w(TAG,"There was an error reading data", e)
  }

fun dumpDataSet(dataSet: LocalDataSet) {
  Log.i(TAG, "Data returned for Data type: ${dataSet.dataType.name}")
  for (dp in dataSet.dataPoints) {
    Log.i(TAG,"Data point:")
    Log.i(TAG,"\tType: ${dp.dataType.name}")
    Log.i(TAG,"\tStart: ${dp.getStartTime(TimeUnit.HOURS)}")
    Log.i(TAG,"\tEnd: ${dp.getEndTime(TimeUnit.HOURS)}")
    for (field in dp.dataType.fields) {
      Log.i(TAG,"\tLocalField: ${field.name.toString()} LocalValue: ${dp.getValue(field)}")
    }
  }
}

El LocalRecordingClient actualiza continuamente su recopilación de datos. Puedes usar readData para obtener los números más recientes en cualquier momento.

Ten en cuenta que LocalRecordingClient almacena hasta 10 días de datos. Para reducir el riesgo de perder datos, puedes usar WorkManager para recopilar los datos de forma periódica en segundo plano.

Cómo anular la suscripción a los datos de fitness

Para liberar recursos, debes asegurarte de cancelar la suscripción a la recopilación de datos del sensor cuando tu app ya no la necesite. Para cancelar la suscripción, usa el método unsubscribe:

val localRecordingClient = FitnessLocal.getLocalRecordingClient(this)
// Unsubscribe from steps data
localRecordingClient.unsubscribe(LocalDataType.TYPE_STEP_COUNT_DELTA)
  .addOnSuccessListener {
    Log.i(TAG, "Successfully unsubscribed!")
  }
  .addOnFailureListener { e ->
    Log.w(TAG, "There was a problem unsubscribing.", e)
  }