واجهة برمجة التطبيقات للتسجيل على الأجهزة الجوّالة

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

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

التفاصيل البارزة

هناك العديد من الميزات البارزة التي تخصّ Recording API على الأجهزة الجوّالة:

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

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

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

البدء

للبدء، أضِف التبعية التالية في ملف build.gradle:

لغة Kotlin المحددة من جهة العميل

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