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

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

كمثال على العمل بفعالية باستخدام واجهة برمجة تطبيقات طبقة البيانات، اطلع على تطبيق Android DataLayer Sample

انتظار حالة استدعاءات طبقة البيانات

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

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

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

إذا كان الرمز قيد التشغيل في سلسلة واجهة المستخدم الرئيسية، فلا تجر استدعاءات محظورة إلى واجهة برمجة تطبيقات طبقة البيانات. إجراء المكالمات بشكل غير متزامن عن طريق إضافة طريقة معاودة الاتصال إلى كائن 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) {
  ...
}

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

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

للاستماع إلى أحداث طبقة البيانات، لديك خياران:

وباستخدام هذين الخيارين، يمكنك إلغاء طرق استدعاء حدث البيانات الأحداث التي تهتم بمعالجتها

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

استخدام WearableListenerService

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

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

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

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

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

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

لإنشاء WearableListenerService، يُرجى اتّباع الخطوات التالية:

  1. أنشِئ صفًا يمتد إلى WearableListenerService.
  2. يمكنك الاستماع إلى الأحداث التي تهمّك، مثل onDataChanged().
  3. يُرجى تعريف فلتر الأهداف في ملف بيان 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> عنصر البيان.

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

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

استخدام مستمع مباشر

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

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

  1. نفِّذ الواجهات المطلوبة.
  2. باستخدام طريقة onCreate() أو onResume()، يمكنك طلب Wearable.getDataClient(this).addListener(), MessageClient.addListener(), CapabilityClient.addListener()، أو ChannelClient.registerChannelCallback() لإرسال إشعار إلى Google Play والخدمات التي يهتم نشاطك بالاستماع إليها فيما يخص أحداث طبقة البيانات.
  3. في مجلد "onStop()" أو onPause()، إلغاء تسجيل أي مستمعين في DataClient.removeListener() MessageClient.removeListener(), CapabilityClient.removeListener()، أو ChannelClient.unregisterChannelCallback()
  4. إذا كان النشاط مهتمًا فقط بالأحداث التي تتضمّن بادئة مسار معيّنة، يمكنك إجراء ما يلي: إضافة أداة استماع ذات فلتر بادئة مناسب لتلقي البيانات ذات وثيق الصلة بحالة الطلب الحالية.
  5. تنفيذ 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());
            }
        }
    }
}

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

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

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