عند إجراء طلب إلى Data Layer API، يمكنك تلقّي حالة الطلب عند اكتماله. يمكنك أيضًا الاستماع إلى أحداث البيانات الناتجة عن تغييرات البيانات التي يجريها تطبيقك في أي مكان على شبكة Wear OS by Google.
للاطّلاع على مثال حول كيفية استخدام Data Layer API بفعالية، يمكنك تجربة تطبيق Android DataLayer Sample.
انتظار حالة طلبات طبقة البيانات
تُرجع طلبات البيانات من واجهة برمجة التطبيقات الخاصة بطبقة البيانات، مثل طلب باستخدام طريقة putDataItem
للفئة
DataClient
، أحيانًا الكائن
Task<ResultType>
. فور إنشاء الكائن Task
، يتم وضع العملية في قائمة الانتظار في الخلفية. إذا لم تتّخذ أي إجراء آخر بعد ذلك، سيتم إكمال العملية في النهاية بدون أي إشعار.
ومع ذلك، عادةً ما تريد تنفيذ إجراء ما باستخدام النتيجة بعد اكتمال العملية، لذا يتيح لك العنصر Task
انتظار حالة النتيجة، إما بشكل غير متزامن أو بشكل متزامن.
المكالمات غير المتزامنة
إذا كان الرمز البرمجي يعمل على سلسلة التعليمات الرئيسية لواجهة المستخدم، لا تُجرِ طلبات حظر إلى Data Layer API. يمكنك تنفيذ عمليات الاستدعاء بشكل غير متزامن من خلال إضافة طريقة ردّ اتصال إلى الكائن Task
، ويتم تشغيل هذه الطريقة عند اكتمال العملية:
Kotlin
// 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>) { ... }
Java
// Using Java 8 Lambdas. task.addOnSuccessListener(dataItem -> handleDataItem(dataItem)); task.addOnFailureListener(exception -> handleDataItemError(exception)); task.addOnCompleteListener(task -> handleTaskComplete(task));
يمكنك الاطّلاع على Task API لمعرفة الاحتمالات الأخرى، بما في ذلك ربط تنفيذ مهام مختلفة.
المكالمات المتزامنة
إذا كان الرمز البرمجي يعمل على سلسلة معالجة منفصلة في خدمة تعمل في الخلفية، مثل
WearableListenerService
، فلا بأس من حظر المكالمات. في هذه الحالة، يمكنك استدعاء Tasks.await()
على عنصر Task
، ما يؤدي إلى الحظر إلى أن يكتمل الطلب ويتم عرض عنصر Result
. يظهر ذلك في المثال التالي.
ملاحظة: احرص على عدم استدعاء هذا الإجراء أثناء استخدام سلسلة التعليمات الرئيسية.
Kotlin
try { Tasks.await(dataItemTask).apply { Log.d(TAG, "Data item set: $uri") } } catch (e: ExecutionException) { ... } catch (e: InterruptedException) { ... }
Java
try { DataItem item = Tasks.await(dataItemTask); Log.d(TAG, "Data item set: " + item.getUri()); } catch (ExecutionException | InterruptedException e) { ... }
الاستماع إلى أحداث طبقة البيانات
بما أنّ طبقة البيانات تعمل على مزامنة البيانات وإرسالها بين الأجهزة المحمولة وأجهزة Wearable، عليك عادةً الاستماع إلى الأحداث المهمة، مثل إنشاء عناصر البيانات وتلقّي الرسائل.
لرصد أحداث طبقة البيانات، لديك خياران:
- أنشئ خدمة توسّع
WearableListenerService
. - أنشئ نشاطًا أو فئة تنفّذ واجهة
DataClient.OnDataChangedListener
.
باستخدام أيّ من هذين الخيارَين، يمكنك تجاهل طرق معاودة الاتصال ببيانات الأحداث للأحداث التي يهمّك التعامل معها.
ملاحظة: يجب مراعاة استهلاك تطبيقك للبطارية عند اختيار طريقة تنفيذ أداة معالجة الأحداث. يتم تسجيل WearableListenerService
في بيان التطبيق ويمكنه تشغيل التطبيق إذا لم يكن قيد التشغيل. إذا كنت بحاجة إلى الاستماع إلى الأحداث فقط عندما يكون تطبيقك قيد التشغيل، وهو ما يحدث غالبًا مع التطبيقات التفاعلية، لا تستخدِم WearableListenerService
. بدلاً من ذلك، سجِّل مستمعًا مباشرًا.
على سبيل المثال، استخدِم طريقة addListener
من فئة DataClient
. يمكن أن يؤدي ذلك إلى تقليل الحمل على النظام وتقليل استهلاك البطارية.
استخدام WearableListenerService
يمكنك عادةً إنشاء مثيلات من
WearableListenerService
في كل من تطبيقات الأجهزة القابلة للارتداء وتطبيقات الأجهزة الجوّالة. ومع ذلك، إذا لم تكن مهتمًا بأحداث البيانات في أحد التطبيقات، لن تحتاج إلى تنفيذ الخدمة في هذا التطبيق.
على سبيل المثال، يمكنك إنشاء تطبيق على جهاز محمول يضبط ويحصل على عناصر بيانات وتطبيق على جهاز قابل للارتداء يستمع إلى هذه التعديلات لتعديل واجهة المستخدم. لا يحدّث تطبيق الأجهزة القابلة للارتداء أيًا من عناصر البيانات، لذا لا يستمع تطبيق الأجهزة الجوّالة إلى أي أحداث بيانات من تطبيق الأجهزة القابلة للارتداء.
في ما يلي بعض الأحداث التي يمكنك الاستماع إليها باستخدام
WearableListenerService
:
-
onDataChanged()
: عندما يتم إنشاء عنصر بيانات أو حذفه أو تغييره، يشغّل النظام وظيفة معاودة الاتصال هذه على جميع العُقد المتصلة. -
onMessageReceived()
: يتم تشغيل هذا الإجراء عند تلقّي رسالة من عقدة تؤدي إلى تشغيل الإجراء على العقدة المستهدَفة. -
onCapabilityChanged()
: عندما تصبح إحدى الميزات التي يعلن عنها مثيل تطبيقك متاحة على الشبكة، يؤدي هذا الحدث إلى تشغيل وظيفة رد الاتصال هذه. إذا كنت تبحث عن عقدة مجاورة، يمكنك طلب البحث باستخدام طريقةisNearby()
للعُقد المقدَّمة في ردّ الاتصال.
يمكنك أيضًا الاستماع إلى الأحداث من
ChannelClient.ChannelCallback
، مثل onChannelOpened()
.
يتم تنفيذ جميع الأحداث السابقة في سلسلة محادثات في الخلفية، وليس في سلسلة المحادثات الرئيسية.
لإنشاء WearableListenerService
، اتّبِع الخطوات التالية:
- أنشئ فئة تتضمّن
WearableListenerService
. - استمع إلى الأحداث التي تهمّك، مثل
onDataChanged()
. - عليك تعريف فلتر الأهداف في ملف البيان لنظام Android لإعلام النظام بشأن
WearableListenerService
. يتيح هذا البيان للنظام ربط خدمتك عند الحاجة.
يوضّح المثال التالي كيفية تنفيذ WearableListenerService
بسيط:
Kotlin
private const val TAG = "DataLayerSample" private const val START_ACTIVITY_PATH = "/start-activity" private const val DATA_ITEM_RECEIVED_PATH = "/data-item-received" 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) } } }
Java
public class DataLayerListenerService extends WearableListenerService { private static final String TAG = "DataLayerSample"; private static final String START_ACTIVITY_PATH = "/start-activity"; private static final String DATA_ITEM_RECEIVED_PATH = "/data-item-received"; @Override public void onDataChanged(DataEventBuffer dataEvents) { 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. for (DataEvent event : dataEvents) { Uri uri = event.getDataItem().getUri(); // Get the node ID from the host value of the URI. String nodeId = uri.getHost(); // Set the data of the message to be the bytes of the URI. byte[] payload = uri.toString().getBytes(); // Send the RPC. Wearable.getMessageClient(this).sendMessage( nodeId, DATA_ITEM_RECEIVED_PATH, payload); } } }
يوضّح القسم التالي كيفية استخدام فلتر الأهداف مع أداة الاستماع هذه.
استخدام الفلاتر مع WearableListenerService
قد يبدو فلتر الأهداف الخاص بالمثال WearableListenerService
الموضّح في القسم السابق على النحو التالي:
<service android:name=".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
محل الإجراء BIND_LISTENER
الذي كان يُنصح به سابقًا، وذلك لكي تؤدي أحداث معيّنة فقط إلى تنشيط تطبيقك أو تشغيله. ويؤدي هذا التغيير إلى تحسين كفاءة النظام وتقليل استهلاك البطارية والنفقات العامة الأخرى المرتبطة بتطبيقك. في هذا المثال، تستمع الساعة إلى عنصر البيانات /start-activity
، ويستمع الهاتف إلى استجابة الرسالة /data-item-received
.
تنطبق قواعد مطابقة فلاتر Android العادية. يمكنك تحديد خدمات متعددة لكل ملف بيان، وفلاتر أهداف متعددة لكل خدمة، وإجراءات متعددة لكل فلتر، ومقاطع بيانات متعددة لكل فلتر. يمكن أن تتطابق الفلاتر مع مضيف حرف بدل أو مضيف محدّد. للمطابقة على مضيف حرف بدل، استخدِم host="*"
. للمطابقة مع مضيف معيّن، حدِّد host=<node_id>
.
يمكنك أيضًا مطابقة مسار حرفي أو بادئة مسار. لإجراء ذلك، يجب تحديد حرف بدل أو مضيف معيّن. وفي ما عدا ذلك، يتجاهل النظام المسار الذي تحدّده.
لمزيد من المعلومات حول أنواع الفلاتر التي تتوافق مع Wear OS، يُرجى الاطّلاع على مستندات مرجع واجهة برمجة التطبيقات الخاصة بـ
WearableListenerService
.
لمزيد من المعلومات عن فلاتر البيانات وقواعد المطابقة، يُرجى الاطّلاع على مستندات مرجع واجهة برمجة التطبيقات الخاصة بعنصر البيان <data>
.
عند مطابقة فلاتر الأهداف، تذكَّر قاعدتَين مهمتَين:
- في حال عدم تحديد أي مخطط لفلتر الهدف، يتجاهل النظام جميع سمات معرّف الموارد المنتظم الأخرى.
- في حال عدم تحديد أي مضيف للفلتر، يتجاهل النظام جميع سمات المسار.
استخدام ميزة "الاستماع المباشر"
إذا كان تطبيقك يهتم فقط بأحداث طبقة البيانات عندما يتفاعل المستخدم مع التطبيق، قد لا يحتاج إلى خدمة طويلة الأمد للتعامل مع كل تغيير في البيانات. في هذه الحالة، يمكنك الاستماع إلى الأحداث في نشاط من خلال تنفيذ واجهة واحدة أو أكثر من الواجهات التالية:
DataClient.OnDataChangedListener
MessageClient.OnMessageReceivedListener
CapabilityClient.OnCapabilityChangedListener
ChannelClient.ChannelCallback
لإنشاء نشاط يستمع إلى أحداث البيانات، اتّبِع الخطوات التالية:
- نفِّذ الواجهات المطلوبة.
- في الطريقتَين
onCreate()
أوonResume()
، استخدِمWearable.getDataClient(this).addListener()
أوMessageClient.addListener()
أوCapabilityClient.addListener()
أوChannelClient.registerChannelCallback()
لإعلام "خدمات Google Play" بأنّ نشاطك مهتم بتلقّي إشعارات بشأن أحداث طبقة البيانات. - في
onStop()
أوonPause()
، ألغِ تسجيل أي أدوات معالجة أحداث باستخدامDataClient.removeListener()
أوMessageClient.removeListener()
أوCapabilityClient.removeListener()
أوChannelClient.unregisterChannelCallback()
. - إذا كان أحد الأنشطة مهتمًا فقط بالأحداث التي تتضمّن بادئة مسار معيّنة، يمكنك إضافة أداة معالجة تتضمّن فلتر بادئة مناسبًا لتلقّي البيانات ذات الصلة بحالة التطبيق الحالية فقط.
- نفِّذ
onDataChanged()
أوonMessageReceived()
أوonCapabilityChanged()
أو طرقًا منChannelClient.ChannelCallback
، وذلك حسب الواجهات التي نفّذتها. يتم استدعاء هذه الطرق في سلسلة التعليمات الرئيسية، أو يمكنك تحديدLooper
مخصّص باستخدامWearableOptions
.
في ما يلي مثال على استخدام السمة DataClient.OnDataChangedListener
:
Kotlin
class MainActivity : Activity(), DataClient.OnDataChangedListener { public override fun onResume() { Wearable.getDataClient(this).addListener(this) } override fun 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) } } } }
Java
public class MainActivity extends Activity implements DataClient.OnDataChangedListener { @Override public void onResume() { Wearable.getDataClient(this).addListener(this); } @Override protected void onPause() { Wearable.getDataClient(this).removeListener(this); } @Override public void onDataChanged(DataEventBuffer dataEvents) { for (DataEvent event : dataEvents) { if (event.getType() == DataEvent.TYPE_DELETED) { Log.d(TAG, "DataItem deleted: " + event.getDataItem().getUri()); } else if (event.getType() == DataEvent.TYPE_CHANGED) { Log.d(TAG, "DataItem changed: " + event.getDataItem().getUri()); } } } }
تنبيه:
قبل استخدام Wearable Data Layer API، تأكَّد من توفّرها على
جهاز، وإلا سيحدث استثناء. استخدِم فئة GoogleApiAvailability
، كما هو موضّح في Horologist.
استخدام الفلاتر مع المستمعين المباشرين
كما ذكرنا سابقًا، يمكنك تحديد فلاتر الأهداف لكائنات WearableListenerService
المستندة إلى ملف البيان، ويمكنك أيضًا استخدام فلاتر الأهداف عند تسجيل أداة معالجة مباشرة من خلال
Wearable
API. تنطبق القواعد نفسها على كل من المستمعين المباشرين المستندين إلى واجهة برمجة التطبيقات والمستمعين المستندين إلى ملف البيان.
يتم عادةً تسجيل أداة معالجة باستخدام مسار أو بادئة مسار محدّدة
في طريقة onResume()
ضمن نشاط، ثم تتم إزالة أداة المعالجة في طريقة
onPause()
ضمن النشاط.
يسمح تنفيذ أدوات معالجة الأحداث بهذه الطريقة لتطبيقك بتلقّي الأحداث بشكل أكثر انتقائية، ما يحسّن من تصميمه وكفاءته.