Recording API'yi kullanarak fitness verilerini kaydetme

Mobilde Recording API, uygulamanızın mobil cihazdaki fitness verilerini pil tasarrufu sağlayacak şekilde kaydetmesine olanak tanır. Örneğin, bu API'yi kullanarak adım sayma verilerini alan bir adım sayara benzer şekilde adımları kaydedebilirsiniz. Bu API'nin hesap gerektirmemesi, hizmeti kullanmak için Google Hesabı'nın gerekli olmadığı ve verilerin cihazda depolandığı anlamına gelir.

Uygulamanızın cihazdaki adım sayısının yanı sıra çeşitli kaynaklardaki diğer sağlık ve fitness verilerini okuması gerekiyorsa Health Connect ile entegrasyon daha iyi bir seçenektir. Health Connect, Android 14 (API düzeyi 34) ve sonraki sürümlerde cihazdaki adımlara yerel olarak erişim de sağlar.

Bu kılavuzda, sağlık ve fitness deneyimlerinizde mobil cihazlarda Recording API'nin nasıl kullanılacağı açıklanmaktadır.

Örnek için GitHub'daki mobilde Recording API örneğine bakın.

Önemli ayrıntılar

Mobilde Recording API'ye özgü birkaç önemli özellik vardır:

  • Kayıt aboneliği başlatıldığında veya yenilendiğinde, en son abonelikten itibaren 10 güne kadar olan verilere erişilebilir.
  • Veriler yalnızca etkin bir abonelik olduğunda kullanılabilir. unsubscribe aranarak kaldırılan aboneliklerde toplanan verilere erişilemez.

Veri türleri

Mobil cihazlardaki Recording API, aşağıdaki veri türlerini kaydedebilir:

Başlayın

Başlamak için build.gradle dosyanıza aşağıdaki bağımlılığı ekleyin:

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

İzin iste

Mobilde Recording API'yi kullanarak veri kaydetmek için uygulamanızın aşağıdaki izni istemesi gerekir:

  • android.permission.ACTIVITY_RECOGNITION

Play Hizmetleri sürüm kontrolü yapma

Kullanıcının, mobil cihazda Recording API'yi kullanabilmesi için Google Play Hizmetleri'ni LOCAL_RECORDING_CLIENT_MIN_VERSION_CODE sürümüne güncellemesi gerekir. Bunu isGooglePlayServicesAvailable yöntemini kullanarak kontrol edebilirsiniz:

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

Aksi takdirde, kullanıcının Google Play Hizmetleri sürümü çok düşükse sistem ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED istisnası oluşturur.

Subscribe to Fitness Data

Adım verilerinin arka planda toplanmasını istemek için aşağıdaki kod snippet'inde gösterildiği gibi subscribe yöntemini kullanın:

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

Read and Process Fitness Data

Abone olduktan sonra readData yöntemini kullanarak verileri isteyin. Ardından, aşağıdaki kod snippet'inde gösterildiği gibi LocalDataReadRequest oluşturarak sonuçtaki LocalDataSet öğesinden LocalDataPoints elde edebilirsiniz:

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, veri koleksiyonunu sürekli olarak günceller. Dilediğiniz zaman en son rakamları almak için readData simgesini kullanabilirsiniz.

LocalRecordingClient simgesinin 10 günlük veriyi depoladığını unutmayın. Veri kaybı riskini azaltmak için WorkManager'ı kullanarak verileri arka planda düzenli olarak toplayabilirsiniz.

Fitness verileri aboneliğinden çıkma

Kaynakları boşaltmak için uygulamanızın artık ihtiyaç duymadığı durumlarda sensör verilerinin toplanması özelliğinin aboneliğini iptal ettiğinizden emin olmanız gerekir. E-posta listesinden çıkmak için unsubscribe yöntemini kullanın:

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