Rejestrowanie danych o aktywności fizycznej za pomocą interfejsu Recording API

Interfejs Recording API na urządzeniach mobilnych umożliwia aplikacji rejestrowanie danych o aktywności fizycznej z urządzenia mobilnego w sposób energooszczędny. Za pomocą tego interfejsu API możesz na przykład rejestrować kroki, podobnie jak w przypadku krokomierza pobierającego dane o liczbie kroków. Ten interfejs API nie wymaga konta, co oznacza, że do korzystania z usługi nie jest potrzebne konto Google, a dane są przechowywane na urządzeniu.

Z tego przewodnika dowiesz się, jak używać interfejsu Recording API na urządzeniach mobilnych w aplikacjach związanych ze zdrowiem i fitness.

Przykład znajdziesz w przykładowym interfejsie Recording API na urządzenia mobilne w GitHubie.

Istotne informacje

Interfejs Recording API na urządzeniach mobilnych ma kilka unikalnych funkcji:

  • Po rozpoczęciu lub odnowieniu subskrypcji nagrywania dostępne są dane od ostatniej subskrypcji (maksymalnie z 10 dni).
  • Dane są dostępne tylko wtedy, gdy masz aktywną subskrypcję. Jeśli subskrypcja zostanie usunięta przez wywołanie funkcji unsubscribe, zebrane dane nie będą dostępne.

Typy danych

Interfejs Recording API na urządzeniach mobilnych może rejestrować te typy danych:

Rozpocznij

Na początek dodaj tę zależność do pliku build.gradle:

Kotlin DSL

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

...

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

Groovy DSL

apply plugin: 'com.android.application'

...

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

Prośba o uprawnienia

Aby rejestrować dane za pomocą interfejsu Recording API na urządzeniu mobilnym, aplikacja musi poprosić o to uprawnienie:

  • android.permission.ACTIVITY_RECOGNITION

Sprawdzanie wersji Usług Google Play

Aby korzystać z interfejsu Recording API na urządzeniu mobilnym, użytkownik musi mieć zaktualizowane Usługi Google Play do wersji LOCAL_RECORDING_CLIENT_MIN_VERSION_CODE. Możesz to sprawdzić za pomocą metody 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

W przeciwnym razie, jeśli wersja Usług Google Play użytkownika jest zbyt niska, system zgłosi wyjątek ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED.

Subskrybowanie danych o aktywności

Aby poprosić o zbieranie danych o krokach w tle, użyj metody subscribe, jak pokazano w tym fragmencie kodu:

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

Odczytywanie i przetwarzanie danych o aktywności

Po zasubskrybowaniu poproś o dane za pomocą metody readData. Następnie możesz uzyskać obiekty LocalDataPoint z wynikowego obiektu LocalDataSet, wysyłając żądanie LocalDataReadRequest, jak pokazano w tym fragmencie kodu:

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

LocalRecordingClient stale aktualizuje zbiór danych. W dowolnym momencie możesz użyć readData, aby pobrać najnowsze dane.

Pamiętaj, że LocalRecordingClient przechowuje dane z maksymalnie 10 dni. Aby zmniejszyć ryzyko utraty danych, możesz użyć WorkManagera do okresowego zbierania danych w tle.

Anulowanie subskrypcji danych o aktywności

Aby zwolnić zasoby, pamiętaj, aby anulować subskrypcję zbierania danych z czujników, gdy aplikacja nie będzie już ich potrzebować. Aby zrezygnować z subskrypcji, użyj metody 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)
  }