تسجيل بيانات اللياقة البدنية باستخدام Recording API

تتيح واجهة برمجة التطبيقات Recording API على الأجهزة الجوّالة لتطبيقك تسجيل بيانات اللياقة البدنية من جهاز جوّال بطريقة فعّالة من حيث استهلاك البطارية. على سبيل المثال، يمكنك استخدام واجهة برمجة التطبيقات هذه لتسجيل الخطوات، على غرار عدّاد الخطوات الذي يسترد بيانات عدد الخطوات. لا تتطلّب واجهة برمجة التطبيقات هذه حسابًا، ما يعني أنّها لا تتطلّب حسابًا على Google لاستخدام الخدمة، ويتم تخزين البيانات على الجهاز.

يوضّح لك هذا الدليل كيفية استخدام Recording API على الأجهزة الجوّالة في تجارب الصحة واللياقة البدنية.

يمكنك الاطّلاع على نموذج Recording API على الأجهزة الجوّالة على GitHub للحصول على مثال.

تفاصيل بارزة

تتوفّر عدة ميزات بارزة في Recording API على الأجهزة الجوّالة فقط، وهي:

  • بعد بدء اشتراك التسجيل أو تجديده، يمكن الوصول إلى البيانات منذ آخر اشتراك لمدة تصل إلى 10 أيام.
  • لا تتوفّر البيانات إلا عند توفّر اشتراك نشط. إذا تمت إزالة اشتراك من خلال الاتصال بالرقم unsubscribe، لن يكون بالإمكان الوصول إلى البيانات التي تم جمعها.

أنواع البيانات

يمكن لواجهة برمجة التطبيقات Recording API على الأجهزة الجوّالة تسجيل أنواع البيانات التالية:

البدء

للبدء، أضِف التبعية التالية في ملف 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'
}

طلب الأذونات

لتسجيل البيانات باستخدام Recording API على الجهاز الجوّال، يجب أن يطلب تطبيقك الإذن التالي:

  • android.permission.ACTIVITY_RECOGNITION

إجراء فحص لإصدار "خدمات Play"

لاستخدام Recording API على الأجهزة الجوّالة، يجب أن يكون لدى المستخدم الإصدار LOCAL_RECORDING_CLIENT_MIN_VERSION_CODE من "خدمات Google Play". يمكنك التحقّق من ذلك باستخدام طريقة 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

بخلاف ذلك، إذا كان إصدار "خدمات Google Play" لدى المستخدم قديمًا جدًا، سيُصدر النظام استثناء ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED.

الاشتراك في بيانات اللياقة البدنية

لطلب جمع بيانات الخطوات في الخلفية، استخدِم طريقة subscribe، كما هو موضّح في مقتطف الرمز التالي:

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

قراءة بيانات اللياقة البدنية ومعالجتها

بعد الاشتراك، اطلب البيانات باستخدام طريقة readData. بعد ذلك، يمكنك الحصول على LocalDataPoints من LocalDataSet الناتج عن طريق إرسال LocalDataReadRequest، كما هو موضّح في مقتطف الرمز التالي:

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 مجموعة البيانات باستمرار. يمكنك استخدام readData للحصول على أحدث الأرقام في أي وقت.

يُرجى العِلم أنّ LocalRecordingClient يخزّن البيانات لمدة تصل إلى 10 أيام. لتقليل خطر فقدان البيانات، يمكنك استخدام WorkManager لجمع البيانات بشكل دوري في الخلفية.

إلغاء الاشتراك في بيانات اللياقة البدنية

لتحرير الموارد، عليك التأكّد من إلغاء الاشتراك في جمع بيانات المستشعر عندما لا يحتاج تطبيقك إليها. لإلغاء الاشتراك، استخدِم طريقة 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)
  }