مزامنة البيانات

يتوافق هذا الدليل مع الإصدار 1.1.0-alpha12 من Health Connect.

تتضمّن معظم التطبيقات التي تتكامل مع Health Connect مخزن بيانات خاصًا بها يعمل كمصدر موثوق. يوفر Health Connect طرقًا للحفاظ على مزامنة تطبيقك.

بناءً على بنية تطبيقك، قد تتضمّن عملية المزامنة بعض الإجراءات التالية أو جميعها:

  • نقل البيانات الجديدة أو المعدَّلة من مخزن بيانات تطبيقك إلى Health Connect
  • جلب التغييرات في البيانات من Health Connect إلى مخزن بيانات تطبيقك
  • حذف البيانات من Health Connect عند حذفها في مخزن بيانات تطبيقك

في كل حالة، تأكَّد من أنّ عملية المزامنة تحافظ على اتساق بيانات Health Connect ومخزن بيانات تطبيقك.

نقل البيانات إلى Health Connect

الجزء الأول من عملية المزامنة هو نقل البيانات من مخزن بيانات تطبيقك إلى مخزن بيانات Health Connect.

تجهيز بياناتك

عادةً ما تتضمّن السجلات في مخزن بيانات تطبيقك التفاصيل التالية:

  • مفتاح فريد، مثل UUID
  • إصدار أو طابع زمني

عند مزامنة البيانات مع Health Connect، حدِّد البيانات التي تم إدراجها أو تعديلها أو حذفها منذ آخر مزامنة وانقلها فقط.

كتابة البيانات في Health Connect

لنقل البيانات إلى Health Connect، اتّبِع الخطوات التالية:

  1. احصل على قائمة بالإدخالات الجديدة أو المعدَّلة أو المحذوفة من مخزن بيانات تطبيقك.
  2. لكل إدخال، أنشئ عنصر Record مناسبًا لنوع البيانات هذا. على سبيل المثال، أنشئ عنصر WeightRecord للبيانات المتعلقة بالوزن.
  3. حدِّد عنصر Metadata مع كل Record. يشمل ذلك clientRecordId، وهو معرّف من مخزن بيانات تطبيقك يمكنك استخدامه لتحديد السجلّ بشكل فريد. يمكنك استخدام مفتاحك الفريد الحالي لهذا الغرض. إذا كانت بياناتك تتضمّن إصدارات، عليك أيضًا تقديم clientRecordVersion يتوافق مع نظام تحديد الإصدارات المستخدَم في بياناتك. إذا لم تكن البيانات تتضمّن إصدارات، يمكنك استخدام قيمة Long للطابع الزمني الحالي كبديل.

    val recordVersion = 0L
    // Specify as needed
    // The clientRecordId is an ID that you choose for your record. This
    // is often the same ID you use in your app's datastore.
    val clientRecordId = "<your-record-id>"
    
    val record = WeightRecord(
        metadata = Metadata(
            clientRecordId = clientRecordId,
            clientRecordVersion = recordVersion,
            device = Device(type = Device.TYPE_SCALE)
        ),
        weight = Mass.kilograms(62.0),
        time = Instant.now(),
        zoneOffset = ZoneOffset.UTC,
    )
    healthConnectClient.insertRecords(listOf(record))

  4. أدرِج البيانات في Health Connect أو عدِّلها باستخدام insertRecords. يعني إدراج البيانات أو تعديلها أنّه يتم استبدال أي بيانات حالية في Health Connect طالما أنّ قيم clientRecordId موجودة في مخزن بيانات Health Connect، وأنّ clientRecordVersion أعلى من القيمة الحالية. بخلاف ذلك، يتم كتابة البيانات التي تم إدراجها أو تعديلها كبيانات جديدة.

    healthConnectClient.insertRecords(arrayListOf(record))

للتعرّف على الاعتبارات العملية لنقل البيانات، اطّلِع على أفضل الممارسات لكتابة البيانات.

تخزين معرّفات Health Connect

إذا كان تطبيقك يقرأ أيضًا البيانات من Health Connect، عليك تخزين id سجلّات Health Connect بعد إدراجها أو تعديلها. تحتاج إلى هذا id لمعالجة عمليات الحذف عند جلب التغييرات في البيانات من Health Connect.

تعرض الدالة insertRecords عنصر InsertRecordsResponse يحتوي على قائمة بقيم id. استخدِم الردّ للحصول على معرّفات السجلات وتخزينها.

val response = healthConnectClient.insertRecords(listOf(record))
for (recordId in response.recordIdsList) {
    // Store recordId to your app's datastore
}

جلب البيانات من Health Connect

الجزء الثاني من عملية المزامنة هو جلب أي تغييرات في البيانات من Health Connect إلى مخزن بيانات تطبيقك. يمكن أن تشمل التغييرات في البيانات عمليات التعديل والحذف.

الحصول على رمز مميّز للتغييرات

للحصول على قائمة بالتغييرات التي يجب جلبها من Health Connect، يحتاج تطبيقك إلى تتبُّع الرموز المميّزة للتغييرات. يمكنك استخدامها عند طلب التغييرات لعرض كل من قائمة بالتغييرات في البيانات ورمز مميّز جديد للتغييرات لاستخدامه في المرة التالية.

للحصول على رمز مميّز للتغييرات، اتّصِل بالدالة getChangesToken وقدِّم أنواع البيانات المطلوبة.

val changesToken = healthConnectClient.getChangesToken(
    ChangesTokenRequest(recordTypes = setOf(WeightRecord::class))
)

التحقّق من التغييرات في البيانات

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

  1. اتّصِل بالدالة getChanges باستخدام الرمز المميّز للحصول على قائمة بالتغييرات.
  2. تحقَّق من كل تغيير لمعرفة ما إذا كان نوع التغيير an UpsertionChange or a DeletionChange، و نفِّذ العمليات اللازمة.
    • بالنسبة إلى UpsertionChange، لا تقبل إلا التغييرات التي لم تأتِ من التطبيق الذي اتّصل بالدالة للتأكّد من عدم إعادة استيراد البيانات.
  3. عيِّن الرمز المميّز التالي للتغييرات كرمز مميّز جديد.
  4. كرِّر الخطوات من 1 إلى 3 إلى أن لا يتبقّى أي تغييرات.
  5. خزِّن الرمز المميّز التالي واحتفِظ به لعملية استيراد مستقبلية.

suspend fun processChanges(context: Context, token: String): String {
    var nextChangesToken = token
    do {
        val response = healthConnectClient.getChanges(nextChangesToken)
        response.changes.forEach { change ->
            when (change) {
                is UpsertionChange ->
                    if (change.record.metadata.dataOrigin.packageName != context.packageName) {
                        processUpsertionChange(change)
                    }
                is DeletionChange -> processDeletionChange(change)
            }
        }
        nextChangesToken = response.nextChangesToken
    } while (response.hasMore)
    // Return and store the changes token for use next time.
    return nextChangesToken
}

للتعرّف على الاعتبارات العملية لجلب البيانات، اطّلِع على أفضل الممارسات لمزامنة البيانات.

معالجة التغييرات في البيانات

اعرض التغييرات في مخزن بيانات تطبيقك. بالنسبة إلى UpsertionChange، استخدِم id وlastModifiedTime من metadata لـ إدراج السجلّ أو تعديله. بالنسبة إلى DeletionChange، استخدِم id المقدَّم لـ حذف السجلّ. يتطلّب ذلك أن تكون قد خزّنت السجلّ id كما هو موضّح في تخزين معرّفات Health Connect.

حذف البيانات من Health Connect

عندما يحذف المستخدم بياناته من تطبيقك، تأكَّد من إزالة البيانات أيضًا أيضًا من Health Connect. استخدِم deleteRecords لإجراء ذلك. تأخذ هذه الدالة نوع سجلّ وقائمة بقيم id وclientRecordId، ما يسهّل تجميع بيانات متعددة لحذفها. يتوفّر أيضًا بديل deleteRecords يأخذ timeRangeFilter

مزامنة البيانات من الأجهزة القابلة للارتداء بزمن انتقال منخفض

لمزامنة البيانات من جهاز لياقة بدنية قابل للارتداء مع Health Connect بزمن انتقال منخفض، استخدِم CompanionDeviceService. تنجح هذه الطريقة مع الأجهزة التي تتيح إشعارات أو مؤشرات BLE GATT وتستهدف الإصدار Android 8.0 (المستوى 26 من واجهة برمجة التطبيقات) أو الإصدارات الأحدث. تسمح CompanionDeviceService لتطبيقك بتلقّي البيانات من الأجهزة القابلة للارتداء وكتابتها في Health Connect، حتى عندما لا يكون التطبيق قيد التشغيل. لمزيد من التفاصيل حول أفضل ممارسات BLE، اطّلِع على نظرة عامة على بلوتوث منخفض الطاقة.

ربط الجهاز

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

تعريف الخدمة في ملف البيان

بعد ذلك، عرِّف CompanionDeviceService في ملف بيان تطبيقك. أضِف ما يلي إلى AndroidManifest.xml:

<manifest ...>
   <application ...>
       <service
           android:name=".MyWearableService"
           android:exported="true"
           android:permission="android.permission.BIND_COMPANION_DEVICE_SERVICE">
           <intent-filter>
               <action android:name="android.companion.CompanionDeviceService" />
           </intent-filter>
       </service>
   </application>
</manifest>

إنشاء CompanionDeviceService

أخيرًا، أنشئ فئة توسِّع CompanionDeviceService. تتعامل هذه الخدمة مع الاتصال بالجهاز القابل للارتداء وتتلقّى البيانات من خلال معاودة الاتصال بـ BLE GATT. عند تلقّي بيانات جديدة، تتم كتابتها على الفور في Health Connect.

private val serviceScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
private var healthConnectClient: HealthConnectClient? = null
private var bluetoothGatt: BluetoothGatt? = null

override fun onDeviceAppeared(address: String) {
    super.onDeviceAppeared(address)
    healthConnectClient = HealthConnectClient.getOrCreate(this)

    serviceScope.launch {
        val granted = healthConnectClient?.permissionController?.getGrantedPermissions()

        // 1. Check permissions ONCE when the device connects
        if (granted?.contains(HealthPermission.getWritePermission(HeartRateRecord::class)) ?: false) {
            // This is where you'd actually start the Bluetooth connection
            // bluetoothGatt = gattCallback.connect(...)
        }

        // 2. Do your initial database read
        readExerciseSessionAndRoute()
    }
}

private val gattCallback = object : BluetoothGattCallback() {
    override fun onCharacteristicChanged(
        gatt: BluetoothGatt,
        characteristic: BluetoothGattCharacteristic,
        value: ByteArray
    ) {
        super.onCharacteristicChanged(gatt, characteristic, value)

        // 3. ONLY process the incoming data here
        val rawData = value

        serviceScope.launch {
            // parseWearableData(rawData)
            // insertExerciseRoute() or writeToHealthConnect()
        }
    }
}

أفضل الممارسات لمزامنة البيانات

تؤثّر العوامل التالية في عملية المزامنة.

انتهاء صلاحية الرمز المميّز

بما أنّ الرمز المميّز للتغييرات غير المستخدَم تنتهي صلاحيته خلال 30 يومًا، عليك استخدام استراتيجية مزامنة تتجنّب فقدان المعلومات في هذه الحالة. يمكن أن تتضمّن استراتيجيتك الطرق التالية:

  • ابحث في مخزن بيانات تطبيقك عن السجلّ الذي تم استخدامه مؤخرًا والذي يحتوي أيضًا على id من Health Connect.
  • اطلب سجلّات من Health Connect تبدأ بطابع زمني معيّن، ثم أدرِجها أو عدِّلها في مخزن بيانات تطبيقك.
  • اطلب رمزًا مميّزًا للتغييرات واحتفِظ به لاستخدامه في المرة التالية التي تحتاج إليه.

الاستراتيجيات المقترَحة لإدارة التغييرات

في حال كان تطبيقك يحصل على رموز مميّزة للتغييرات غير صالحة أو منتهية الصلاحية، ننصحك باتّباع استراتيجيات الإدارة التالية بناءً على تطبيقها في منطقك:

  • قراءة جميع البيانات وإزالة البيانات المكرّرة : هذه هي الاستراتيجية الأكثر مثالية.
    • خزِّن الطابع الزمني لآخر مرة قرأ فيها المستخدمون البيانات من Health Connect.
    • عند انتهاء صلاحية الرمز المميّز، أعِد قراءة جميع البيانات من أحدث طابع زمني أو لآخر 30 يومًا. بعد ذلك، أزِل البيانات المكرّرة مقارنةً بالبيانات التي تمت قراءتها سابقًا باستخدام المعرّفات.
    • من الأفضل تنفيذ معرّفات العملاء لأنّها مطلوبة لتعديل البيانات.
  • قراءة البيانات فقط منذ آخر طابع زمني للقراءة : يؤدي ذلك إلى بعض التناقضات في البيانات في وقت انتهاء صلاحية الرمز المميّز للتغييرات، ولكن الفترة الزمنية أقصر وقد تستغرق بضع ساعات إلى يومين.
    • خزِّن الطابع الزمني لآخر مرة قرأ فيها المستخدمون البيانات من Health Connect.
    • عند انتهاء صلاحية الرمز المميّز، اقرأ جميع البيانات من هذا الطابع الزمني فصاعدًا.
  • حذف البيانات ثم قراءتها لآخر 30 يومًا : يتوافق ذلك بشكل أوثق مع ما يحدث في عملية التكامل الأولى.
    • احذف جميع البيانات التي قرأها التطبيق من Health Connect لآخر 30 يومًا.
    • بعد حذف هذه البيانات، أعِد قراءتها كلها.
  • قراءة البيانات لآخر 30 يومًا بدون إزالة البيانات المكرّرة : هذه هي الاستراتيجية الأقل مثالية، وتؤدي إلى عرض بيانات مكرّرة للمستخدمين.
    • احذف جميع البيانات التي قرأها التطبيق من Health Connect لآخر 30 يومًا.
    • اسمح بالإدخالات المكرّرة.

الرموز المميّزة للتغييرات في نوع البيانات

إذا كان تطبيقك يستخدم أكثر من نوع بيانات بشكل مستقل، استخدِم رموزًا مميّزة منفصلة للتغييرات لكل نوع بيانات. لا تستخدِم قائمة بأنواع بيانات متعددة مع Changes Sync API إلا إذا كان يتم استخدام أنواع البيانات هذه معًا أو لا يتم استخدامها على الإطلاق.

عمليات القراءة في المقدّمة

لا يمكن للتطبيقات قراءة البيانات من Health Connect إلا أثناء عملها في المقدّمة. عند مزامنة البيانات من Health Connect، قد يتم في أي وقت مقاطعة الوصول إلى Health Connect. على سبيل المثال، يجب أن يتعامل تطبيقك مع المقاطعات في منتصف عملية المزامنة عند قراءة كمية كبيرة من البيانات من Health Connect، وأن يواصل العملية في المرة التالية التي يتم فيها فتح التطبيق.

عمليات القراءة في الخلفية

يمكنك أن تطلب تشغيل تطبيقك في الخلفية وقراءة البيانات من Health Connect. إذا طلبت إذن Background Read، يمكن للمستخدم منح تطبيقك إذن قراءة البيانات في الخلفية.

أوقات الاستيراد

بما أنّه لا يمكن إعلام تطبيقك بالبيانات الجديدة، تحقَّق من البيانات الجديدة في نقطتين:

  • في كل مرة يصبح فيها تطبيقك نشطًا في المقدّمة في هذه الحالة، استخدِم أحداث مراحل النشاط.
  • دوريًا، أثناء بقاء تطبيقك في المقدّمة أبلِغ المستخدمين عند توفّر بيانات جديدة، ما يسمح لهم بتحديث شاشتهم لعرض التغييرات.