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

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

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

تفاصيل بارزة

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

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

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

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

البدء

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

لغة Kotlin DSL

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

...

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

DSL رائعة

apply plugin: 'com.android.application'

...

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

طلب الأذونات

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

  • android.permission.ACTIVITY_RECOGNITION

التحقق من إصدار "خدمات Play"

لاستخدام واجهة برمجة التطبيقات للتسجيل على الجهاز الجوّال، يجب أن يكون لدى المستخدم خدمات 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، كما هو موضح في الرمز التالي snippet:

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