التعامل مع أحداث طبقة البيانات على Wear

عند إجراء طلب إلى Data Layer API، يمكنك تلقّي حالة الطلب عند اكتماله. يمكنك أيضًا الاستماع إلى أحداث البيانات الناتجة عن تغييرات البيانات التي يجريها تطبيقك في أي مكان على شبكة Wear OS by Google.

للاطّلاع على مثال حول كيفية استخدام Data Layer API بفعالية، راجِع تطبيق نموذج DataLayer على Android.

انتظار حالة طلبات طبقة البيانات

تُرجع الطلبات التي يتم إرسالها إلى Data Layer API، مثل الطلب الذي يستخدم الطريقة putDataItem للفئة DataClient، أحيانًا العنصر Task<ResultType>. وبمجرد إنشاء عنصر Task، يتم وضع العملية في قائمة الانتظار في الخلفية. إذا لم تتّخذ أي إجراء آخر بعد ذلك، سيتم إكمال العملية في النهاية بدون إشعار.

ومع ذلك، عادةً ما تريد تنفيذ إجراء ما على النتيجة بعد اكتمال العملية، لذا يتيح لك العنصر Task انتظار حالة النتيجة، إما بشكل غير متزامن أو بشكل متزامن.

المكالمات غير المتزامنة

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

// Using Kotlin function references
task.addOnSuccessListener(::handleDataItem)
task.addOnFailureListener(::handleDataItemError)
task.addOnCompleteListener(::handleTaskComplete)
...
fun handleDataItem(dataItem: DataItem) { ... }
fun handleDataItemError(exception: Exception) { ... }
fun handleTaskComplete(task: Task<DataItem>) { ... }

راجِع Task API للاطّلاع على إمكانات أخرى، بما في ذلك ربط تنفيذ المهام المختلفة.

المكالمات المتزامنة

إذا كان الرمز البرمجي يعمل على سلسلة معالجة منفصلة في خدمة تعمل في الخلفية، مثل WearableListenerService، فلا بأس في حظر المكالمات. في هذه الحالة، يمكنك استدعاء Tasks.await() على العنصر Task، ما يؤدي إلى حظر العنصر إلى أن يكتمل الطلب ويتم عرض العنصر Result. يظهر ذلك في المثال التالي.

ملاحظة: لا تستدعِ هذه الدالة أثناء استخدام سلسلة التعليمات الرئيسية.

try {
    Tasks.await(dataItemTask).apply {
        Log.d(TAG, "Data item set: $uri")
    }
}
catch (e: ExecutionException) { ... }
catch (e: InterruptedException) { ... }

الاستماع إلى أحداث طبقة البيانات

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

لرصد أحداث طبقة البيانات، لديك خياران:

باستخدام أيّ من هذين الخيارَين، يمكنك تجاهل طرق معاودة الاتصال الخاصة بأحداث البيانات للأحداث التي يهمّك التعامل معها.

ملاحظة: يجب مراعاة استهلاك تطبيقك للبطارية عند اختيار طريقة تنفيذ أداة معالجة الأحداث. يتم تسجيل WearableListenerService في بيان التطبيق ويمكنه تشغيل التطبيق إذا لم يكن قيد التشغيل. إذا كنت بحاجة فقط إلى الاستماع إلى الأحداث عندما يكون تطبيقك قيد التشغيل، وهو ما يحدث غالبًا مع التطبيقات التفاعلية، فلا تستخدم WearableListenerService. بدلاً من ذلك، سجِّل أداة معالجة حدث مباشر. على سبيل المثال، استخدِم طريقة addListener للفئة DataClient. ويمكن أن يؤدي ذلك إلى تقليل الحِمل على النظام وتقليل استهلاك البطارية.

استخدام WearableListenerService

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

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

في ما يلي بعض الأحداث التي يمكنك الاستماع إليها باستخدام WearableListenerService:

  • onDataChanged(): عندما يتم إنشاء عنصر بيانات أو حذفه أو تغييره، يشغّل النظام عملية رد الاتصال هذه على جميع العُقد المتصلة.
  • onMessageReceived(): يتم تشغيل عملية الاسترجاع هذه على العقدة المستهدَفة عندما يتم إرسال رسالة من عقدة.
  • onCapabilityChanged(): عندما تصبح إحدى الميزات التي يعلن عنها مثيل تطبيقك متاحة على الشبكة، يؤدي هذا الحدث إلى تشغيل هذا الرمز البرمجي. إذا كنت تبحث عن عقدة مجاورة، يمكنك طلب البحث باستخدام طريقة isNearby() للعُقد المقدَّمة في رد الاتصال.

يمكنك أيضًا الاستماع إلى الأحداث من ChannelClient.ChannelCallback، مثل onChannelOpened().

يتم تنفيذ جميع الأحداث السابقة في سلسلة محادثات في الخلفية، وليس في سلسلة المحادثات الرئيسية.

لإنشاء WearableListenerService، اتّبِع الخطوات التالية:

  1. أنشئ فئة تتضمّن WearableListenerService.
  2. استمع إلى الأحداث التي تهمّك، مثل onDataChanged().
  3. عليك تعريف فلتر أهداف في ملف البيان لنظام التشغيل Android لإعلام النظام WearableListenerService. يتيح هذا البيان للنظام ربط خدمتك عند الحاجة.

يوضّح المثال التالي كيفية تنفيذ WearableListenerService:

class DataLayerListenerService : WearableListenerService() {

    override fun onDataChanged(dataEvents: DataEventBuffer) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "onDataChanged: $dataEvents")
        }

        // Loop through the events and send a message
        // to the node that created the data item.
        dataEvents
            .map { it.dataItem.uri }
            .forEach { uri ->
                // Get the node ID from the host value of the URI.
                val nodeId: String = uri.host!!
                // Set the data of the message to be the bytes of the URI.
                val payload: ByteArray = uri.toString().toByteArray()

                // Send the RPC.
                Wearable.getMessageClient(this)
                    .sendMessage(
                        nodeId,
                        DATA_ITEM_RECEIVED_PATH,
                        payload
                    )
            }
    }
}

يوضّح القسم التالي كيفية استخدام فلتر الأهداف مع أداة معالجة الأحداث هذه.

استخدام الفلاتر مع WearableListenerService

قد يبدو فلتر الأهداف الخاص بالمثال WearableListenerService الموضّح في القسم السابق على النحو التالي:

<service
    android:name=".snippets.datalayer.DataLayerListenerService"
    android:exported="true"
    tools:ignore="ExportedService" >
    <intent-filter>
        <action android:name="com.google.android.gms.wearable.DATA_CHANGED" />
        <data
            android:scheme="wear"
            android:host="*"
            android:path="/start-activity" />
    </intent-filter>
</service>

يُعلم فلتر الإجراء DATA_CHANGED النظام بأنّ تطبيقك مهتم بأحداث طبقة البيانات.

في هذا المثال، تستمع الساعة إلى عنصر البيانات /start-activity، ويستمع الهاتف إلى رد الرسالة /data-item-received (DATA_ITEM_RECEIVED_PATH).

تنطبق قواعد مطابقة فلاتر Android العادية. يمكنك تحديد خدمات متعددة لكل بيان، وفلاتر أهداف متعددة لكل خدمة، وإجراءات متعددة لكل فلتر، ومقاطع بيانات متعددة لكل فلتر. يمكن أن تتطابق الفلاتر مع مضيف بدل أو مضيف محدّد. للحصول على تطابق مع مضيف يستخدم حرف بدل، استخدِم host="*". للمطابقة مع مضيف معيّن، حدِّد host=<node_id>.

يمكنك أيضًا مطابقة مسار حرفي أو بادئة مسار. لإجراء ذلك، يجب تحديد حرف بدل أو مضيف معيّن. وفي ما عدا ذلك، يتجاهل النظام المسار الذي تحدّده.

لمزيد من المعلومات حول أنواع الفلاتر التي يتيحها Wear OS، اطّلِع على مستندات مرجع واجهة برمجة التطبيقات الخاصة بـ WearableListenerService.

لمزيد من المعلومات عن فلاتر البيانات وقواعد المطابقة، يُرجى الاطّلاع على مستندات مرجع واجهة برمجة التطبيقات الخاصة بعنصر البيان <data>.

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

  • إذا لم يتم تحديد أي مخطط لفلتر الأهداف، سيتجاهل النظام جميع سمات معرّف الموارد المنتظم (URI) الأخرى.
  • في حال عدم تحديد مضيف للفلتر، يتجاهل النظام جميع سمات المسار.

استخدام ميزة "الاستماع المباشر"

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

لإنشاء نشاط يستمع إلى أحداث البيانات، اتّبِع الخطوات التالية:

  1. تنفيذ الواجهات المطلوبة
  2. في الطريقتَين onCreate() أو onResume()، استخدِم الدالة Wearable.getDataClient(this).addListener() أو MessageClient.addListener() أو CapabilityClient.addListener() أو ChannelClient.registerChannelCallback() لإعلام &quot;خدمات Google Play&quot; بأنّ نشاطك مهتم بأحداث طبقة البيانات.
  3. في onStop() أو onPause()، ألغِ تسجيل أي أدوات معالجة أحداث باستخدام DataClient.removeListener() أو MessageClient.removeListener() أو CapabilityClient.removeListener() أو ChannelClient.unregisterChannelCallback().
  4. إذا كان النشاط يحتاج فقط إلى تلقّي أحداث تتضمّن بادئة مسار معيّنة، أضِف أداة معالجة تتضمّن فلتر بادئة لتلقّي البيانات ذات الصلة بحالة التطبيق الحالية فقط.
  5. نفِّذ onDataChanged() أو onMessageReceived() أو onCapabilityChanged() أو طرقًا من ChannelClient.ChannelCallback، استنادًا إلى الواجهات التي نفّذتها. يتم استدعاء هذه الطرق في سلسلة التعليمات الرئيسية، أو يمكنك تحديد Looper مخصّص باستخدام WearableOptions.

في ما يلي مثال على تنفيذ DataClient.OnDataChangedListener:

class MainActivity : Activity(), DataClient.OnDataChangedListener {

    public override fun onResume() {
        super.onResume()
        Wearable.getDataClient(this).addListener(this)
    }

    override fun onPause() {
        super.onPause()
        Wearable.getDataClient(this).removeListener(this)
    }

    override fun onDataChanged(dataEvents: DataEventBuffer) {
        dataEvents.forEach { event ->
            if (event.type == DataEvent.TYPE_DELETED) {
                Log.d(TAG, "DataItem deleted: " + event.dataItem.uri)
            } else if (event.type == DataEvent.TYPE_CHANGED) {
                Log.d(TAG, "DataItem changed: " + event.dataItem.uri)
            }
        }
    }
}

تنبيه: قبل استخدام واجهة برمجة التطبيقات Wearable Data Layer API، تأكَّد من أنّها متاحة على الجهاز، وإلا سيحدث استثناء. استخدِم الفئة GoogleApiAvailability، كما هو موضّح في Horologist.

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

كما ذكرنا سابقًا، يمكنك تحديد فلاتر الأهداف لعناصر WearableListenerService المستندة إلى ملف البيان، ويمكنك أيضًا استخدام فلاتر الأهداف عند تسجيل أداة معالجة مباشرة من خلال Wearable API. تنطبق القواعد نفسها على كلّ من أدوات معالجة الأحداث المباشرة المستندة إلى واجهة برمجة التطبيقات وأدوات معالجة الأحداث المستندة إلى ملف البيان.

يتم عادةً تسجيل أداة معالجة باستخدام مسار أو بادئة مسار محدّدة في طريقة onResume() الخاصة بنشاط معيّن، ثم تتم إزالة أداة المعالجة في طريقة onPause() الخاصة بالنشاط. يؤدي تنفيذ أدوات المعالجة بهذه الطريقة إلى تلقّي تطبيقك للأحداث بشكل أكثر انتقائية، ما يحسّن من تصميمه وكفاءته.