Logging API na urządzeniach mobilnych

Interfejs Recording API na urządzeniach mobilnych umożliwia aplikacji rejestrowanie kroków w sposób podobny do krokomierza, który pobiera dane o liczbie kroków z urządzenia mobilnego, nie obciążając przy tym baterii. 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 korzystać z interfejsu Recording API na urządzeniu mobilnym w ramach funkcji związanych ze zdrowiem i fitnessem.

Przykładem jest interfejs API nagrywania na urządzeniu mobilnym na GitHubie.

Ważne informacje

Interfejs API do nagrywania ma kilka przydatnych funkcji, które nie są dostępne w innych interfejsach:

  • Po rozpoczęciu lub odnowieniu subskrypcji nagrywania dane z ostatniej subskrypcji są dostępne przez maksymalnie 10 dni.
  • Dane są dostępne tylko wtedy, gdy subskrypcja jest aktywna. Jeśli subskrypcja zostanie usunięta przez wywołanie funkcji unsubscribe, zebrane dane kroków 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 do pliku build.gradle tę zależność:

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 nagrywać 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ć, korzystając z 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

Jeśli wersja Usług Google Play jest za niska, system zgłasza wyjątek ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED.

Subskrypcja danych dotyczących aktywności

Aby poprosić o zbieranie danych o krokuch 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)
  }

Czytanie i przetwarzanie danych dotyczących kondycji

Po subskrypcji żądaj danych za pomocą metody readData. Następnie możesz uzyskać punkty danych lokalnych z wynikającego z tego LocalDataSet, tworząc 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 swoją kolekcję danych. W każdej chwili możesz użyć funkcji readData, aby pobrać najnowsze dane.

Pamiętaj, że LocalRecordingClient przechowuje dane z maksymalnie 10 dni. Aby zmniejszyć ryzyko utraty danych, możesz okresowo zbierać dane w tle za pomocą WorkManagera.

Anulowanie subskrypcji danych o kondycji

Aby zwolnić zasoby, anuluj subskrypcję zbierania danych z czujników, gdy aplikacja ich już nie potrzebuje. Aby anulować subskrypcję, 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)
  }