تكون تعديلات البيانات غير النشطة مناسبة للتطبيقات التي تحتاج إلى مراقبة بيانات "خدمات الصحة" في الخلفية. وهي مخصّصة لحالات الاستخدام التي تمتد لساعات أو أيام أو حتى لفترة أطول. إذا كنت بحاجة إلى تخزين بيانات الصحة واللياقة البدنية أو معالجتها عندما لا يكون تطبيقك قيد التشغيل ولم يشارك المستخدم بشكل صريح في تمرين، استخدِم عميل Health Service غير النشط.
للاطّلاع على أمثلة حول استخدام البيانات غير النشطة، راجِع نماذج البيانات غير النشطة والأهداف غير النشطة على GitHub.
إضافة عناصر تابعة
لإضافة اعتمادية على "خدمات الصحة"، يجب تضمين مستودع Google Maven في مشروعك. لمزيد من المعلومات، راجِع مستودع Maven من Google.
في ملف build.gradle
على مستوى الوحدة، أضِف التبعية التالية:
رائع
dependencies { implementation "androidx.health:health-services-client:1.1.0-alpha05" }
Kotlin
dependencies { implementation("androidx.health:health-services-client:1.1.0-alpha05") }
التحقّق من الإمكانات
قبل التسجيل لتلقّي إشعارات بتعديلات البيانات، تأكَّد من أنّ الجهاز يمكنه توفير نوع البيانات التي يحتاجها تطبيقك. تتيح لك إمكانية التحقّق من الإمكانات تفعيل ميزات معيّنة أو إيقافها أو تعديل واجهة مستخدم تطبيقك للتعويض عن الميزات غير المتاحة.
val healthClient = HealthServices.getClient(this /*context*/)
val passiveMonitoringClient = healthClient.passiveMonitoringClient
lifecycleScope.launchWhenCreated {
val capabilities = passiveMonitoringClient.capabilities.await()
// Supported types for passive data collection
supportsHeartRate =
DataType.HEART_RATE_BPM in capabilities.supportedDataTypesPassiveMonitoring
// Supported types for PassiveGoals
supportsStepsGoal =
DataType.STEPS_DAILY in capabilities.supportedDataTypesPassiveGoals
}
التسجيل للحصول على البيانات غير النشطة
يمكنك تلقّي البيانات غير النشطة من خلال خدمة أو دالة رد الاتصال أو كليهما. تتيح الخدمة لتطبيقك تلقّي البيانات في الخلفية عندما لا يظهر أي جزء من تطبيقك في المقدّمة. عند تلقّي البيانات في الخلفية، يتم تسليمها على شكل دفعات. يتلقّى رد الاتصال البيانات بمعدّل أسرع قليلاً، ولكن فقط أثناء تشغيل التطبيق وإعلام رد الاتصال بنجاح.
أيًا كانت الطريقة التي تستخدمها، عليك أولاً إنشاء PassiveListenerConfig
يحدّد أنواع البيانات التي سيتم تلقّيها، كما هو موضّح في المثال التالي:
val passiveListenerConfig = PassiveListenerConfig.builder()
.setDataTypes(setOf(DataType.HEART_RATE_BPM))
.build()
لتلقّي البيانات باستخدام دالة ردّ الاتصال، حدِّد دالة ردّ الاتصال وسجِّلها، كما هو موضّح في المثال التالي:
val passiveListenerCallback: PassiveListenerCallback = object : PassiveListenerCallback {
override fun onNewDataPointsReceived(dataPoints: DataPointContainer) {
// TODO: Do something with dataPoints
}
}
passiveMonitoringClient.setPassiveListenerCallback(
passiveListenerConfig,
passiveListenerCallback
)
// To remove the listener
passiveMonitoringClient.clearPassiveListenerCallbackAsync()
استخدام خدمة مشابه، ولكن بدلاً من إنشاء فئة مشتقة من
PassiveListenerCallback
، اشتقّ من PassiveListenerService
، كما هو موضّح في
المثال التالي:
class PassiveDataService : PassiveListenerService() {
override fun onNewDataPointsReceived(dataPoints: DataPointContainer) {
// TODO: Do something with dataPoints
}
}
passiveMonitoringClient.setPassiveListenerServiceAsync(
PassiveDataService::class.java,
passiveListenerConfig
)
بعد ذلك، عرِّف الخدمة في ملف AndroidManifest.xml
. يجب طلب إذن Health
Services، الذي يتيح التحقّق من أنّ "خدمات الصحة" فقط هي التي يمكنها الربط
بالخدمة:
<service android:name=".PassiveDataService"
android:permission="com.google.android.wearable.healthservices.permission.PASSIVE_DATA_BINDING"
android:exported="true" />
تفسير الوقت
يتم تجميع البيانات التي تتلقّاها من "خدمات الصحة" في حِزم، لذا قد تتلقّى نقاط بيانات من أنواع مختلفة أو نقاط بيانات متعددة من النوع نفسه في الحزمة نفسها. استخدِم الطوابع الزمنية المضمّنة في هذه العناصر بدلاً من الوقت الذي تلقّى فيه تطبيقك هذه العناصر لتحديد الترتيب الصحيح للأحداث.
احصل على الطوابع الزمنية لكل DataPoint
من خلال احتساب الطابع الزمني للتشغيل أولاً،
كما هو موضّح في المثال التالي:
val bootInstant =
Instant.ofEpochMilli(System.currentTimeMillis() - SystemClock.elapsedRealtime())
يمكن بعد ذلك تمرير هذه القيمة إلى
getStartInstant()
أو
getEndInstant()
.
استعادة عمليات التسجيل بعد إعادة التشغيل
لا تستمر عمليات تسجيل البيانات غير النشطة بعد إعادة التشغيل. لتلقّي البيانات بعد إعادة تشغيل الجهاز، أعِد إنشاء عمليات التسجيل باستخدام BroadcastReceiver
الذي يستمع إلى البث العام للنظام ACTION_BOOT_COMPLETED
.
في جهاز الاستقبال، لا تحاول استعادة عمليات التسجيل مباشرةً. بدلاً من ذلك، يمكنك تفويض هذه الوظيفة إلى عامل WorkManager
. عند بدء تشغيل الجهاز، قد تستغرق "خدمات الصحة" 10 ثوانٍ أو أكثر للرد على طلب تسجيل البيانات غير النشطة، وقد يتجاوز ذلك وقت التنفيذ المسموح به BroadcastReceiver
. في المقابل، WorkManager
يخضع العاملون لحد 10 دقائق للتنفيذ.
يوضّح المقتطف التالي الشكل الذي قد يبدو عليه BroadcastReceiver
:
class StartupReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (intent.action != Intent.ACTION_BOOT_COMPLETED) return
// TODO: Check permissions first
WorkManager.getInstance(context).enqueue(
OneTimeWorkRequestBuilder<RegisterForPassiveDataWorker>().build()
)
}
}
class RegisterForPassiveDataWorker(
private val appContext: Context,
workerParams: WorkerParameters
) : Worker(appContext, workerParams) {
override fun doWork(): Result {
runBlocking {
HealthServices.getClient(appContext)
.passiveMonitoringClient
.setPassiveListenerCallback(...)
}
return Result.success()
}
}
لترتيب تنفيذ النظام لهذا الرمز عند تشغيل الجهاز، عليك إجراء تعديلَين على ملف AndroidManifest.xml
.
أولاً، أضِف الإذن التالي كعنصر ثانوي من <manifest>
:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
ثانيًا، أضِف فلتر intent الخاص بالمستلِم التالي كعنصر ثانوي من <application>
:
<receiver
android:name=".StartupReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
حالة النشاط
يمكن أن يقدّم العميل غير النشط أيضًا معلومات شاملة عن حالة المستخدم، مثل ما إذا كان نائمًا. لتلقّي هذه الإشعارات، اتّبِع الخطوات التالية:
- اطلب الإذن
ACTIVITY_RECOGNITION
. - الاتصال بـ
setShouldUserActivityInfoBeRequested(true)
في أداة إنشاءPassiveListenerConfig
يمكنك إلغاء طريقة onUserActivityInfoReceived()
في رد الاتصال أو الخدمة
واستخدام UserActivityInfo
الذي تم عرضه، كما هو موضّح في المثال
التالي:
override fun onUserActivityInfoReceived(info: UserActivityInfo) {
val stateChangeTime: Instant = info.stateChangeTime // may be in the past!
val userActivityState: UserActivityState = info.userActivityState
if (userActivityState == UserActivityState.USER_ACTIVITY_ASLEEP) {
// ...
}
}
الأهداف غير المباشرة
يمكنك ضبط عميل غير نشط لإرسال إشعار إلى التطبيق عند تحقيق الأهداف غير النشطة، مثل إكمال المستخدم 10,000 خطوة في اليوم.
لإجراء ذلك، أنشئ هدفًا كما هو موضّح في المثال التالي:
val dailyStepsGoal by lazy {
val condition = DataTypeCondition(
dataType = DataType.STEPS_DAILY,
threshold = 10_000, // Trigger every 10000 steps
comparisonType = ComparisonType.GREATER_THAN_OR_EQUAL
)
PassiveGoal(condition)
}
أضِف هذا الهدف إلى PassiveListenerConfig
، كما هو موضّح في المثال التالي:
val passiveListenerConfig = PassiveListenerConfig.builder()
.setDailyGoals(setOf(dailyStepsGoal))
.build()
يمكنك تجاهل طريقة onGoalCompleted()
في رد الاتصال أو الخدمة
واستخدام PassiveGoal
الذي تم عرضه، كما هو موضّح في المثال التالي:
override fun onGoalCompleted(goal: PassiveGoal) {
when (goal.dataTypeCondition.dataType) {
DataType.STEPS_DAILY -> {
// ...
}
}
}
أفلام مُقترَحة لك
- ملاحظة: يتم عرض نص الرابط عندما تكون JavaScript غير مفعّلة
- البيانات والتمارين النشطة
- بدء استخدام المربّعات
- إضافة شاشة البداية