إذا كنت تتطلّع إلى إنشاء تجربة لتتبُّع النوم في تطبيقك، يمكنك استخدام Health Connect لتنفيذ إجراءات مثل:
- كتابة بيانات جلسات النوم
- كتابة بيانات مرحلة النوم
- كتابة بيانات النوم، مثل معدّل نبضات القلب ونسبة الأكسجين في الدم ومعدّل التنفس
- قراءة بيانات النوم من تطبيقات أخرى
يوضّح هذا الدليل كيفية إنشاء ميزات النوم هذه، ويتناول أنواع البيانات والتنفيذ في الخلفية والأذونات وسير العمل المقترَح وأفضل الممارسات.
نظرة عامة: إنشاء أداة شاملة لتتبُّع النوم
يمكنك إنشاء تجربة شاملة لتتبُّع النوم باستخدام Health Connect من خلال اتّباع الخطوات الأساسية التالية:
- تنفيذ الأذونات بشكل صحيح استنادًا إلى "أذونات الصحة"
- تسجيل الجلسات باستخدام
SleepSessionRecord - كتابة أنواع البيانات، مثل مراحل النوم ومعدّل نبضات القلب ونسبة الأكسجين في الدم، بشكل منتظم خلال الجلسة.
- إدارة عملية التنفيذ في الخلفية بشكل صحيح للتحقّق من إمكانية تسجيل البيانات بشكل مستمر طوال الليل
- قراءة بيانات الجلسة للحصول على ملخّصات وتحليلات ما بعد النوم
تتيح سير العمل هذا إمكانية التشغيل التفاعلي مع تطبيقات Health Connect الأخرى، كما تتحقّق من إذن الوصول إلى البيانات الذي يتحكّم فيه المستخدم.
قبل البدء
قبل تنفيذ ميزات النوم، يُرجى مراعاة ما يلي:
- ادمج Health Connect باستخدام التبعية المناسبة.
- أنشئ مثيلاً من
HealthConnectClient. - تأكَّد من أنّ تطبيقك ينفّذ مسارات الأذونات في وقت التشغيل استنادًا إلى Health Permissions.
المفاهيم الرئيسية
يمثّل تطبيق Health Connect بيانات النوم باستخدام بعض المكوّنات الأساسية. يعمل SleepSessionRecord كسجلّ مركزي للنوم، ويحتوي على تفاصيل مثل أوقات البدء أو الانتهاء ومراحل النوم. أثناء الجلسة، يمكن تسجيل أنواع مختلفة من البيانات، مثل HeartRateRecord أو OxygenSaturationRecord.
جلسات النوم
يتم تمثيل بيانات النوم من خلال SleepSessionRecord. يسجّل كل سجلّ ما يلي:
startTimeendTimestages: قائمةSleepSessionRecord.Stageتتضمّن النوم العميق والخفيف ونوم حركة العين السريعة والنوم مع الاستيقاظ.- البيانات الوصفية الاختيارية للجلسة (العنوان والملاحظات)
يمكن أن تكتب التطبيقات أنواعًا متعددة من البيانات المرتبطة بجلسة.
أنواع البيانات
تشمل أنواع البيانات الشائعة التي يتم تسجيلها أثناء جلسة النوم ما يلي:
SleepSessionRecord: تسجّل هذه الفئة مدة النوم ومراحله، بما في ذلك النوم العميق والخفيف والنوم مع حركة العين السريعة (REM) واليقظة.-
HeartRateRecord: تسجّل هذه السمة معدّل نبضات القلب أثناء النوم. OxygenSaturationRecord: تسجّل نسبة الأكسجين في الدم (SpO2) أثناء النوم.RespiratoryRateRecord: تسجّل هذه السمة معدّل التنفس أثناء النوم.
يتم تخزين كل نوع من البيانات كسجلّ فردي.
اعتبارات التطوير
غالبًا ما تحتاج تطبيقات تتبُّع النوم إلى العمل لفترات طويلة، وكثيرًا ما تعمل في الخلفية عندما تكون الشاشة مطفأة. وعند إنشاء ميزات تتبُّع النوم، من المهم مراعاة كيفية إدارة التنفيذ في الخلفية وطلب الأذونات اللازمة لبيانات النوم.
التنفيذ في الخلفية
تعمل تطبيقات تتبُّع النوم عادةً طوال الليل مع إيقاف تشغيل الشاشة، وفي هذه الحالة، عليك استخدام ما يلي:
- الخدمات التي تعمل في المقدّمة لجمع البيانات
-
WorkManagerللكتابة المؤجّلة أو المزامنة - استراتيجيات تجميع البيانات لكتابة السجلات العادية للبيانات التفصيلية، مثل معدل ضربات القلب
الحفاظ على الاستمرارية من خلال إبقاء معرّف الجلسة متسقًا في جميع عمليات الكتابة
الأذونات
يجب أن يطلب تطبيقك أذونات Health Connect ذات الصلة قبل قراءة بيانات النوم أو كتابتها. للحصول على قائمة كاملة بأنواع البيانات، راجِع أنواع بيانات Health Connect. تشمل الأذونات الشائعة للنوم جلسات النوم ومقاييس مثل معدّل نبضات القلب أو نسبة الأكسجين في الدم.
يتم حماية إمكانية الوصول إلى بيانات النوم من خلال الأذونات التالية:
android.permission.health.READ_SLEEPandroid.permission.health.WRITE_SLEEP
لإضافة إمكانية تتبُّع النوم إلى تطبيقك، ابدأ بطلب أذونات لنوع البيانات SleepSession.
في ما يلي الإذن الذي يجب الإفصاح عنه لتتمكّن من كتابة بيانات النوم:
<application>
<uses-permission
android:name="android.permission.health.WRITE_SLEEP" />
...
</application>
لقراءة بيانات النوم، عليك طلب الأذونات التالية:
<application>
<uses-permission
android:name="android.permission.health.READ_SLEEP" />
...
</application>
يوضّح المثال التالي كيفية طلب أذونات لنومتك تتضمّن بيانات معدّل نبضات القلب ونسبة الأكسجين في الدم ومعدّل التنفس:
بعد إنشاء مثيل للعميل، يجب أن يطلب تطبيقك أذونات من المستخدم. يجب السماح للمستخدمين بمنح الأذونات أو رفضها في أي وقت. لإجراء ذلك، أنشئ مجموعة من الأذونات لأنواع البيانات المطلوبة. تأكَّد من أنّ الأذونات في المجموعة معرَّفة في ملف بيان Android أولاً.
val permissions = setOf( HealthPermission.getReadPermission(SleepSessionRecord::class), HealthPermission.getWritePermission(SleepSessionRecord::class), HealthPermission.getReadPermission(HeartRateRecord::class), HealthPermission.getWritePermission(HeartRateRecord::class), HealthPermission.getReadPermission(OxygenSaturationRecord::class), HealthPermission.getWritePermission(OxygenSaturationRecord::class), HealthPermission.getReadPermission(RespiratoryRateRecord::class), HealthPermission.getWritePermission(RespiratoryRateRecord::class) )
getGrantedPermissions
لمعرفة ما إذا كان تطبيقك قد حصل على الأذونات المطلوبة. إذا لم يكن الأمر كذلك، استخدِم
createRequestPermissionResultContract
لطلب هذه الأذونات. سيؤدي ذلك إلى عرض شاشة أذونات Health Connect.
val permissions = setOf( HealthPermission.getReadPermission(StepsRecord::class), HealthPermission.getWritePermission(StepsRecord::class), HealthPermission.getReadPermission(HeartRateRecord::class), HealthPermission.getWritePermission(HeartRateRecord::class) ) val requestPermissionsLauncher = rememberLauncherForActivityResult( contract = PermissionController.createRequestPermissionResultContract() ) { grantedPermissions -> if (grantedPermissions.containsAll(permissions)) { coroutineScope.launch { snackbarHostState.showSnackbar("Permissions granted!") } } else { coroutineScope.launch { snackbarHostState.showSnackbar("Permissions denied.") } } }
تنفيذ جلسة نوم
يوضّح هذا القسم سير العمل المقترَح لتسجيل بيانات النوم.
لمواءمة أنواع البيانات، مثل HeartRateRecord أو OxygenSaturationRecord، مع جلسة نوم، سجِّلها باستخدام الطوابع الزمنية التي تقع بين startTime وendTime للجلسة. لا يستخدم تطبيق Health Connect معرّف جلسة لربط جلسات النوم بالبيانات التفصيلية. بدلاً من ذلك، يكون الربط ضمنيًا من خلال الفواصل الزمنية المتداخلة. عند قراءة بيانات النوم، يمكنك استخدام النطاق الزمني لجلسة معيّنة للاستعلام عن أنواع البيانات المرتبطة بها، كما هو موضّح في قراءة بيانات النوم.
كتابة جلسة
مع أنّه يمكن تسجيل بيانات تفصيلية، مثل معدّل نبضات القلب، طوال جلسة النوم، يجب ألا تتم كتابة SleepSessionRecord نفسها في Health Connect إلا بعد انتهاء الجلسة، مثلاً عندما يستيقظ المستخدم. يجب أن يتضمّن السجلّ startTime وendTime للجلسة وقائمة بعناصر SleepSessionRecord.Stage المسجّلة أثناء الجلسة، لأنّ SleepSessionRecord يتطلّب أن يكون endTime بعد startTime.
لكتابة بيانات جلسة نوم، اتّبِع الخطوات التالية:
- أنشئ معرّفًا فريدًا لسجلّ العميل.
- عندما يستيقظ المستخدم أو يتم إيقاف ميزة تتبُّع النوم، يتم جمع جميع مراحل النوم وإنشاء
SleepSessionRecord. - أدرِج السجلّ باستخدام
insertRecords.
مثال:
val clientRecordId = UUID.randomUUID().toString()
val sessionStartTime = LocalDateTime.of(2023, 10, 30, 22, 0).toInstant(ZoneOffset.UTC)
val sessionEndTime = LocalDateTime.of(2023, 10, 31, 7, 0).toInstant(ZoneOffset.UTC)
val stages = mutableListOf<SleepSessionRecord.Stage>()
// Add recorded stages, for example:
stages.add(SleepSessionRecord.Stage(
startTime = sessionStartTime.plusSeconds(3600),
endTime = sessionStartTime.plusSeconds(7200),
stage = SleepSessionRecord.STAGE_TYPE_LIGHT)
)
stages.add(SleepSessionRecord.Stage(
startTime = sessionStartTime.plusSeconds(7200),
endTime = sessionStartTime.plusSeconds(10800),
stage = SleepSessionRecord.STAGE_TYPE_DEEP)
)
// ... other stages
val session = SleepSessionRecord(
startTime = sessionStartTime,
startZoneOffset = ZoneOffset.UTC,
endTime = sessionEndTime,
endZoneOffset = ZoneOffset.UTC,
stages = stages,
metadata = Metadata(clientRecordId = clientRecordId)
)
healthConnectClient.insertRecords(listOf(session))
قراءة بيانات النوم
يمكن للتطبيقات قراءة جلسات النوم والبيانات المرتبطة بها لتلخيص النشاط أو تقديم إحصاءات صحية أو مزامنة البيانات مع خادم خارجي. على سبيل المثال، يمكنك قراءة SleepSessionRecord ثم طلب البحث عن HeartRateRecord الذي حدث خلال الفترة الزمنية نفسها.
جلسة القراءة مع البيانات المرتبطة بها
يمكنك قراءة جلسات النوم باستخدام ReadRecordsRequest مع تحديد SleepSessionRecord كنوع البيانات، مع فلترة البيانات حسب النطاق الزمني. لقراءة البيانات المرتبطة بجلسة معيّنة، أرسِل طلبًا ثانيًا لنوع البيانات المحدّد، مثل HeartRateRecord، مع الفلترة حسب startTime وendTime لجلسة النوم.
يوضّح المثال التالي كيفية قراءة جلسات النوم التي تتضمّن بيانات معدّل ضربات القلب المرتبطة بها خلال نطاق زمني محدّد:
suspend fun readSleepSessionsWithAssociatedData(
healthConnectClient: HealthConnectClient,
startTime: Instant,
endTime: Instant
) {
val response = healthConnectClient.readRecords(
ReadRecordsRequest(
recordType = SleepSessionRecord::class,
timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
)
)
for (sleepRecord in response.records) {
// Process each session
val stages = sleepRecord.stages
val notes = sleepRecord.notes
// To read specific granular data (like heart rate) that occurred during
// this session, use the session's startTime and endTime to filter
// the request for that data type.
val hrResponse = healthConnectClient.readRecords(
ReadRecordsRequest(
recordType = HeartRateRecord::class,
timeRangeFilter = TimeRangeFilter.between(
sleepRecord.startTime,
sleepRecord.endTime
)
)
)
for (heartRateRecord in hrResponse.records) {
for (sample in heartRateRecord.samples) {
val bpm = sample.beatsPerMinute
}
}
}
}
أفضل الممارسات
اتّبِع الإرشادات التالية لتحسين موثوقية البيانات وتجربة المستخدم:
- الكتابة بشكل متكرّر أثناء التتبُّع النشط: بالنسبة إلى التتبُّع النشط، اكتب البيانات فور توفّرها أو بفاصل زمني أقصاه 15 دقيقة.
- استخدام WorkManager للمزامنة في الخلفية: استخدِم
WorkManagerلعمليات الكتابة المؤجّلة. استهدِف فاصلًا زمنيًا مدته 15 دقيقة لتحقيق التوازن بين البيانات في الوقت الفعلي وكفاءة البطارية. - طلبات الكتابة على دُفعات: لا تكتب كل حدث من أحداث المستشعر بشكل فردي، بل قسِّم طلباتك إلى أجزاء. يمكن لتطبيق Health Connect معالجة ما يصل إلى 1,000 سجلّ لكل طلب كتابة.
- الحفاظ على ثبات معرّفات الجلسات وفرادتها: استخدِم معرّفات متّسقة لجلساتك، فإذا تم تعديل جلسة أو تحديثها، سيؤدي استخدام المعرّف نفسه إلى منع التعامل معها كجلسة جديدة منفصلة.
- استخدام التجميع لأنواع البيانات: لتقليل الحمل الزائد للإدخال/الإخراج والحفاظ على عمر البطارية، يمكنك تجميع نقاط البيانات في طلب
insertRecordsواحد بدلاً من كتابة كل نقطة على حدة. - تجنُّب كتابة بيانات مكرّرة: استخدام معرّفات العملاء: عند إنشاء سجلّات، اضبط
metadata.clientRecordId. يستخدم Health Connect هذا المعرّف لتحديد السجلّات الفريدة. إذا حاولت كتابة سجلّ يتضمّنclientRecordIdسبق أن تم استخدامه، سيتجاهل Health Connect السجلّ المكرّر أو يعدّل السجلّ الحالي بدلاً من إنشاء سجلّ جديد. ويُعدّ ضبطmetadata.clientRecordIdالطريقة الأكثر فعالية لمنع تكرار السجلّات أثناء عمليات إعادة محاولة المزامنة أو إعادة تثبيت التطبيق.val record = StepsRecord( count = 100, startTime = startTime, endTime = endTime, startZoneOffset = ZoneOffset.UTC, endZoneOffset = ZoneOffset.UTC, metadata = Metadata( // Use a unique ID from your own database clientRecordId = "daily_steps_2023_10_27_user_123" ) )
- التحقّق من البيانات الحالية: قبل المزامنة، استعلم عن النطاق الزمني لمعرفة ما إذا كانت السجلات من تطبيقك متوفّرة من قبل.
- التأكّد من عدم تداخل الطوابع الزمنية: تأكَّد من أنّ جلسة جديدة لا تبدأ قبل انتهاء الجلسة السابقة، لأنّ الجلسات المتداخلة يمكن أن تتسبّب في حدوث تعارضات في لوحات بيانات اللياقة البدنية واحتسابات الملخّص.
- تقديم أسباب واضحة للحصول على الإذن: استخدِم مسار
Permission.createIntentلتوضيح سبب حاجة تطبيقك إلى الوصول إلى البيانات الصحية، على سبيل المثال: "لمراقبة مؤشرات ضغط الدم وتقديم إحصاءات". - اختبار الجلسات الطويلة: راقِب استهلاك البطارية خلال الجلسات التي تستغرق عدة ساعات للتأكّد من أنّ الفاصل الزمني لتجميع البيانات واستخدام المستشعر لا يستنزفان البطارية.
- مواءمة الطوابع الزمنية مع معدّلات أجهزة الاستشعار: يمكنك مطابقة الطوابع الزمنية للتسجيل مع معدّل تكرار أجهزة الاستشعار الفعلي للحفاظ على دقة البيانات العالية.
الاختبار
للتحقّق من صحة البيانات وتوفير تجربة عالية الجودة للمستخدم، اتّبِع استراتيجيات الاختبار التالية وراجِع مستند أهم حالات الاستخدام للاختبار الرسمي.
أدوات التحقّق
- مجموعة أدوات Health Connect: استخدِم هذا التطبيق المصاحب لفحص السجلات يدويًا وحذف بيانات الاختبار ومحاكاة التغييرات في قاعدة البيانات. هذه هي أفضل طريقة للتأكّد من تخزين السجلات بشكل صحيح.
- اختبار الوحدات باستخدام
FakeHealthConnectClient: استخدِم مكتبة الاختبار للتحقّق من طريقة تعامل تطبيقك مع الحالات الحدّية، مثل إلغاء الإذن أو استثناءات واجهة برمجة التطبيقات، بدون الحاجة إلى جهاز فعلي.
قائمة التحقّق من الجودة
البنية النموذجية
يتضمّن تنفيذ ميزة تتبُّع النوم عادةً ما يلي:
| المكوّن | يدير |
|---|---|
| وحدة التحكّم في الجلسة | حالة الجلسة المؤقّت منطق تجميع البيانات عناصر التحكّم في أنواع البيانات جمع البيانات |
| طبقة المستودع (تتضمّن عمليات Health Connect): | إدراج جلسة إدراج أنواع البيانات إدراج مراحل النوم قراءة ملخّصات الجلسات |
| طبقة واجهة المستخدم (شاشات العرض): | المدة أنواع البيانات المباشرة تصوّر مراحل النوم |
تحديد المشاكل وحلّها
| المشكلة | السبب المحتمل | درجة الدقة |
|---|---|---|
| أنواع البيانات غير متوفّرة (مثل معدّل نبضات القلب) | عدم توفّر أذونات الكتابة أو فلاتر الوقت غير صحيحة | تأكَّد من أنّك طلبت إذن الوصول إلى نوع البيانات المحدّد وأنّ المستخدم منحه لك. وتأكَّد من أنّ ReadRecordsRequest يستخدم TimeRangeFilter مطابقًا للجلسة. اطّلِع على الأذونات. |
| تعذُّر كتابة الجلسة | طوابع زمنية متداخلة | قد يرفض Health Connect السجلّات التي تتداخل مع البيانات الحالية من التطبيق نفسه. تأكَّد من أنّ startTime جلسة جديدة يقع بعد endTime الجلسة السابقة. |
| لم يتم تسجيل أي بيانات من أجهزة الاستشعار أثناء النوم | تم إيقاف الخدمة التي تعمل في المقدّمة أو كانت غير نشطة. | لجمع بيانات المستشعر طوال الليل أثناء إيقاف الشاشة، يمكنك استخدام خدمة تعمل في المقدّمة مع foregroundServiceType="health". |
| تظهر السجلات المكررة | السمة clientRecordId غير متوفّرة. |
عيِّن clientRecordId فريدًا في Metadata لكل سجلّ. يتيح ذلك لتطبيق Health Connect إزالة التكرار إذا تمت كتابة البيانات نفسها مرتين أثناء إعادة محاولة المزامنة. اطّلِع على أفضل الممارسات. |
خطوات تصحيح الأخطاء الشائعة
| التحقّق من حالة الإذن | يجب دائمًا طلب الإذن باستخدام getPermissionStatus() قبل محاولة إجراء عملية قراءة أو كتابة، إذ يمكن للمستخدمين إلغاء الأذونات في إعدادات النظام في أي وقت. |
| تحقَّق من وضع التنفيذ. | إذا كان تطبيقك لا يجمع البيانات في الخلفية، تأكَّد من أنّك قد أدرجت الأذونات الصحيحة في ملف AndroidManifest.xml وأنّ المستخدم لم يضع التطبيق في وضع "تقييد استخدام البطارية". |