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

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

برای مثالی از کار مؤثر با API لایه داده، به برنامه نمونه لایه داده اندروید مراجعه کنید.

منتظر وضعیت فراخوانی‌های لایه داده باشید

فراخوانی‌های API لایه داده - مانند فراخوانی با استفاده از متد putDataItem از کلاس DataClient - گاهی اوقات یک شیء Task<ResultType> را برمی‌گردانند. به محض ایجاد شیء Task ، عملیات در پس‌زمینه در صف قرار می‌گیرد. اگر بعد از این کار دیگری انجام ندهید، عملیات در نهایت به طور بی‌صدا تکمیل می‌شود.

با این حال، شما معمولاً می‌خواهید پس از اتمام عملیات، کاری با نتیجه انجام دهید، بنابراین شیء Task به شما امکان می‌دهد تا منتظر وضعیت نتیجه باشید، چه به صورت ناهمگام و چه به صورت همگام.

فراخوانی‌های ناهمزمان

اگر کد شما روی نخ اصلی رابط کاربری (UI thread) اجرا می‌شود، فراخوانی‌های مسدودکننده (blocking) را به API لایه داده (Data Layer API) انجام ندهید. فراخوانی‌ها را به صورت غیرهمزمان با اضافه کردن یک متد callback به شیء 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>) { ... }

برای سایر امکانات، از جمله زنجیره‌سازی اجرای وظایف مختلف، به 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. یک فیلتر intent در مانیفست اندروید خود تعریف کنید تا سیستم را از WearableListenerService خود مطلع کند. این تعریف به سیستم اجازه می‌دهد تا در صورت نیاز، سرویس شما را bind کند.

مثال زیر نحوه پیاده‌سازی 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
                    )
            }
    }
}

بخش زیر نحوه استفاده از فیلتر intent با این شنونده را توضیح می‌دهد.

استفاده از فیلترها با WearableListenerService

یک فیلتر intent برای مثال 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 )‎ است.

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

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

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

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

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

  • اگر هیچ طرحی برای فیلتر intent مشخص نشده باشد، سیستم تمام ویژگی‌های دیگر URI را نادیده می‌گیرد.
  • اگر هیچ میزبانی برای فیلتر مشخص نشده باشد، سیستم تمام ویژگی‌های مسیر را نادیده می‌گیرد.

از یک شنونده زنده استفاده کنید

اگر برنامه شما فقط به رویدادهای لایه داده در هنگام تعامل کاربر با برنامه اهمیت می‌دهد، ممکن است به یک سرویس طولانی مدت برای مدیریت هر تغییر داده نیاز نداشته باشد. در چنین حالتی، می‌توانید با پیاده‌سازی یک یا چند رابط زیر، به رویدادها در یک فعالیت گوش دهید:

برای ایجاد یک فعالیت که به رویدادهای داده گوش می‌دهد، این مراحل را دنبال کنید:

  1. رابط‌های مورد نیاز را پیاده‌سازی کنید.
  2. در متدهای onCreate() یا onResume() ، Wearable.getDataClient(this).addListener() ، MessageClient.addListener() ، CapabilityClient.addListener() یا ChannelClient.registerChannelCallback() را فراخوانی کنید تا به سرویس‌های گوگل پلی اطلاع دهید که فعالیت شما به رویدادهای لایه داده علاقه‌مند است.
  3. در onStop() یا onPause() ، با استفاده از DataClient.removeListener() ، MessageClient.removeListener() ، CapabilityClient.removeListener() یا ChannelClient.unregisterChannelCallback() ، هر شنونده‌ای را از حالت ثبت خارج کنید.
  4. اگر یک فعالیت فقط نیاز به دریافت رویدادهایی با پیشوند مسیر خاص دارد، یک شنونده با فیلتر پیشوند اضافه کنید تا فقط داده‌های مربوط به وضعیت فعلی برنامه را دریافت کند.
  5. بسته به رابط‌هایی که پیاده‌سازی کرده‌اید، onDataChanged() ، onMessageReceived() ، onCapabilityChanged() یا متدهایی از ChannelClient.ChannelCallback را پیاده‌سازی کنید. این متدها در نخ اصلی فراخوانی می‌شوند، یا می‌توانید با استفاده WearableOptions یک Looper سفارشی مشخص کنید.

در اینجا مثالی آورده شده است که 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)
            }
        }
    }
}

هشدار: قبل از استفاده از API لایه داده‌های پوشیدنی، بررسی کنید که آیا روی دستگاه موجود است یا خیر؛ در غیر این صورت، یک استثنا رخ می‌دهد. از کلاس GoogleApiAvailability ، همانطور که در Horologist پیاده‌سازی شده است، استفاده کنید.

استفاده از فیلترها با شنوندگان زنده

همانطور که قبلاً ذکر شد، همانطور که می‌توانید فیلترهای intent را برای اشیاء WearableListenerService مبتنی بر مانیفست مشخص کنید، می‌توانید هنگام ثبت یک شنونده زنده از طریق Wearable API از فیلترهای intent استفاده کنید. قوانین یکسانی هم برای شنونده‌های زنده مبتنی بر API و هم برای شنونده‌های مبتنی بر مانیفست اعمال می‌شود.

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