رویدادهای لایه داده را در Wear مدیریت کنید

هنگامی که با Data Layer API تماس می گیرید، می توانید وضعیت تماس را پس از اتمام آن دریافت کنید. همچنین می‌توانید به رویدادهای داده ناشی از تغییرات داده‌ای که برنامه شما در هر نقطه از شبکه Wear OS by Google ایجاد می‌کند گوش دهید.

برای مثالی از کار موثر با API لایه داده، برنامه Android DataLayer Sample را بررسی کنید.

منتظر وضعیت تماس های لایه داده باشید

فراخوانی به 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>) { ... }

جاوا

// 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 برمی‌گرداند. این در مثال زیر نشان داده شده است.

توجه: مطمئن شوید که وقتی در تاپیک اصلی هستید این را صدا نکنید.

کاتلین

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

جاوا

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() گره‌های ارائه شده در callback را پرس و جو کنید.

همچنین می‌توانید رویدادها را از ChannelClient.ChannelCallback ، مانند onChannelOpened() گوش دهید.

همه رویدادهای قبلی در یک رشته پس‌زمینه اجرا می‌شوند، نه در رشته اصلی.

برای ایجاد WearableListenerService ، این مراحل را دنبال کنید:

  1. کلاسی ایجاد کنید که WearableListenerService را گسترش دهد.
  2. به رویدادهایی که به آنها علاقه دارید، مانند onDataChanged() گوش دهید.
  3. یک فیلتر قصد در مانیفست Android خود اعلام کنید تا سیستم را در مورد WearableListenerService خود مطلع کنید. این اعلان به سیستم اجازه می‌دهد سرویس شما را در صورت لزوم متصل کند.

مثال زیر نحوه پیاده سازی WearableListenerService ساده را نشان می دهد:

کاتلین

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)
                }
    }
}

جاوا

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 گوش می دهد.

قوانین استاندارد مطابقت فیلتر اندروید اعمال می شود. می‌توانید چندین سرویس در هر مانیفست، چندین فیلتر هدف در هر سرویس، چندین عمل در هر فیلتر، و چند بند داده در هر فیلتر مشخص کنید. فیلترها می توانند بر روی یک میزبان عام یا در یک میزبان خاص مطابقت داشته باشند. برای تطبیق در یک میزبان عام، از host="*" استفاده کنید. برای مطابقت در یک میزبان خاص، host=<node_id> را مشخص کنید.

شما همچنین می توانید یک مسیر تحت اللفظی یا پیشوند مسیر را مطابقت دهید. برای انجام این کار، باید یک عام یا هاست خاص را مشخص کنید. در غیر این صورت، سیستم مسیری که شما مشخص کرده اید را نادیده می گیرد.

برای اطلاعات بیشتر در مورد انواع فیلترهایی که Wear OS پشتیبانی می کند، به مستندات مرجع API برای WearableListenerService مراجعه کنید.

برای اطلاعات بیشتر درباره فیلترهای داده و قوانین تطبیق، به مستندات مرجع API برای عنصر مانیفست <data> مراجعه کنید.

هنگام تطبیق فیلترهای هدف، دو قانون مهم را به خاطر بسپارید:

  • اگر هیچ طرحی برای فیلتر intent مشخص نشده باشد، سیستم تمام ویژگی های 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 را پیاده سازی می کند:

کاتلین

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)
            }
        }
    }
}

جاوا

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 مبتنی بر مانیفست تعیین کنید، می توانید هنگام ثبت شنونده زنده از طریق Wearable API از فیلترهای هدف استفاده کنید. قوانین یکسانی برای شنوندگان زنده مبتنی بر API و شنوندگان مبتنی بر مانیفست اعمال می شود.

یک الگوی رایج این است که یک شنونده را با یک مسیر یا پیشوند مسیر خاص در متد onResume() یک فعالیت ثبت کنید و سپس شنونده را در متد onPause() فعالیت حذف کنید. اجرای شنوندگان به این روش به برنامه شما امکان می دهد رویدادها را به صورت انتخابی دریافت کند و طراحی و کارایی آن را بهبود بخشد.