Data Layer API को कॉल करने पर, कॉल पूरा होने के बाद आपको कॉल का स्टेटस मिल सकता है. इसके अलावा, Wear OS by Google नेटवर्क पर कहीं भी आपके ऐप्लिकेशन के डेटा में हुए बदलावों से जुड़े डेटा इवेंट भी सुने जा सकते हैं.
डेटा लेयर एपीआई का असरदार तरीके से इस्तेमाल करने का उदाहरण देखने के लिए, Android DataLayer Sample ऐप्लिकेशन देखें.
डेटा लेयर कॉल के स्टेटस का इंतज़ार करना
डेटा लेयर एपीआई को किए गए कॉल, जैसे कि DataClient क्लास के putDataItem तरीके का इस्तेमाल करके किया गया कॉल, कभी-कभी Task<ResultType> ऑब्जेक्ट दिखाता है. Task ऑब्जेक्ट के बनते ही, ऑपरेशन को बैकग्राउंड में कतार में लगा दिया जाता है.
इसके बाद, कोई कार्रवाई न करने पर यह प्रोसेस अपने-आप पूरी हो जाती है.
हालांकि, आम तौर पर ऑपरेशन पूरा होने के बाद, आपको नतीजे के साथ कुछ करना होता है. इसलिए, Task ऑब्जेक्ट की मदद से, नतीजे की स्थिति का इंतज़ार किया जा सकता है. ऐसा एसिंक्रोनस या सिंक्रोनस तरीके से किया जा सकता है.
एसिंक्रोनस कॉल
अगर आपका कोड मुख्य यूज़र इंटरफ़ेस (यूआई) थ्रेड पर चल रहा है, तो डेटा लेयर एपीआई को ब्लॉक करने वाली कॉल न करें. साथ ही, putDataItem को कॉल करने के लिए कोरूटीन का इस्तेमाल करें:
private suspend fun Context.sendDataAsync(count: Int) { try { val putDataReq: PutDataRequest = PutDataMapRequest.create("/count").run { dataMap.putInt("count_key", count) asPutDataRequest() } val dataItem = Wearable.getDataClient(this).putDataItem(putDataReq).await() handleDataItem(dataItem) } catch (e: Exception) { handleDataItemError(e) } finally { handleTaskComplete() } } private fun handleDataItem(dataItem: DataItem) { } private fun handleDataItemError(exception: Exception) { } private fun handleTaskComplete() { }
अलग-अलग टास्क को एक साथ चलाने के साथ-साथ अन्य विकल्पों के बारे में जानने के लिए, Task API देखें.
सिंक्रोनस कॉल
अगर आपका कोड बैकग्राउंड सेवा में किसी अलग हैंडलर थ्रेड पर चल रहा है, जैसे कि WearableListenerService में, तो putDataItem को ब्लॉक करने वाले कॉल के लिए runBlocking का इस्तेमाल करें.
ध्यान दें: मुख्य थ्रेड पर रहते हुए इसे कॉल न करें.
private fun Context.sendDataSync(count: Int) = runBlocking { val putDataReq = PutDataMapRequest.create("/count").run { dataMap.putInt("count_key", count) asPutDataRequest() } try { val result = Wearable.getDataClient(this@sendDataSync) .putDataItem(putDataReq) .await() // Logic for success } catch (e: Exception) { // Handle failure } }
डेटा लेयर के इवेंट को मॉनिटर करने की अनुमति
डेटा लेयर, हैंडहेल्ड और पहनने योग्य डिवाइसों के बीच डेटा को सिंक करती है और भेजती है. इसलिए, आपको आम तौर पर डेटा आइटम के बनाए जाने और मैसेज के मिलने जैसे ज़रूरी इवेंट को सुनना होता है.
डेटा लेयर के इवेंट को मॉनिटर करने के लिए, आपके पास दो विकल्प हैं:
WearableListenerServiceको बढ़ाने वाली सेवा बनाएं.DataClient.OnDataChangedListenerइंटरफ़ेस को लागू करने वाली कोई गतिविधि या क्लास बनाएं.
इन दोनों विकल्पों की मदद से, उन इवेंट के लिए डेटा इवेंट कॉलबैक के तरीकों को बदला जा सकता है जिन्हें आपको मैनेज करना है.
ध्यान दें: लिसनर को लागू करने का तरीका चुनते समय, अपने ऐप्लिकेशन के बैटरी इस्तेमाल करने की क्षमता को ध्यान में रखें. WearableListenerService को ऐप्लिकेशन के मेनिफ़ेस्ट में रजिस्टर किया जाता है. अगर ऐप्लिकेशन पहले से नहीं चल रहा है, तो यह उसे लॉन्च कर सकता है. अगर आपको सिर्फ़ तब इवेंट सुनने हैं, जब आपका ऐप्लिकेशन पहले से चल रहा हो, तो WearableListenerService का इस्तेमाल न करें. ऐसा अक्सर इंटरैक्टिव ऐप्लिकेशन के साथ होता है. इसके बजाय, लाइव लिसनर रजिस्टर करें. उदाहरण के लिए, DataClient क्लास के addListener तरीके का इस्तेमाल करें. इससे सिस्टम पर लोड कम हो सकता है और बैटरी की खपत भी कम हो सकती है.
WearableListenerService का इस्तेमाल करना
आम तौर पर, WearableListenerService के इंस्टेंस, पहनने लायक डिवाइस और हैंडहेल्ड डिवाइस, दोनों तरह के ऐप्लिकेशन में बनाए जाते हैं. हालांकि, अगर आपको किसी ऐप्लिकेशन में डेटा इवेंट ट्रैक नहीं करने हैं, तो आपको उस ऐप्लिकेशन में सेवा लागू करने की ज़रूरत नहीं है.
उदाहरण के लिए, आपके पास एक हैंडहेल्ड ऐप्लिकेशन हो सकता है, जो डेटा आइटम ऑब्जेक्ट सेट करता है और उन्हें वापस पाता है. साथ ही, आपके पास एक वियरेबल ऐप्लिकेशन हो सकता है, जो इन अपडेट को सुनकर अपने यूज़र इंटरफ़ेस (यूआई) को अपडेट करता है. वियरेबल डिवाइस पर मौजूद ऐप्लिकेशन, किसी भी डेटा आइटम को कभी अपडेट नहीं करता. इसलिए, हैंडहेल्ड डिवाइस पर मौजूद ऐप्लिकेशन, वियरेबल डिवाइस पर मौजूद ऐप्लिकेशन से किसी भी डेटा इवेंट को नहीं सुनता.
WearableListenerService का इस्तेमाल करके, इन इवेंट को सुना जा सकता है:
onDataChanged(): जब भी कोई डेटा आइटम ऑब्जेक्ट बनाया जाता है, मिटाया जाता है या उसमें बदलाव किया जाता है, तो सिस्टम कनेक्ट किए गए सभी नोड पर इस कॉलबैक को ट्रिगर करता है.onMessageReceived(): किसी नोड से भेजा गया मैसेज, टारगेट नोड पर इस कॉलबैक को ट्रिगर करता है.onCapabilityChanged(): जब आपके ऐप्लिकेशन के किसी इंस्टेंस के विज्ञापन में बताई गई सुविधा नेटवर्क पर उपलब्ध हो जाती है, तब यह इवेंट इस कॉलबैक को ट्रिगर करता है. अगर आपको आस-पास के नोड के बारे में जानकारी चाहिए, तो कॉल बैक में दिए गए नोड केisNearby()तरीके से क्वेरी की जा सकती है.
ChannelClient.ChannelCallback से भी इवेंट सुने जा सकते हैं. जैसे, onChannelOpened().
पहले के सभी इवेंट, बैकग्राउंड थ्रेड में लागू किए जाते हैं, न कि मुख्य थ्रेड में.
WearableListenerService बनाने के लिए, यह तरीका अपनाएं:
WearableListenerServiceको बढ़ाने वाली क्लास बनाएं.- अपनी पसंद के इवेंट सुनें, जैसे कि
onDataChanged(). - अपने 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> मेनिफ़ेस्ट एलिमेंट के लिए एपीआई रेफ़रंस दस्तावेज़ देखें.
इन्टेंट फ़िल्टर मैच करते समय, इन दो ज़रूरी नियमों का ध्यान रखें:
- अगर इंटेंट फ़िल्टर के लिए कोई स्कीम तय नहीं की गई है, तो सिस्टम अन्य सभी यूआरआई एट्रिब्यूट को अनदेखा कर देता है.
- अगर फ़िल्टर के लिए कोई होस्ट तय नहीं की गई है, तो सिस्टम सभी पाथ एट्रिब्यूट को अनदेखा कर देता है.
लाइव लिसनर का इस्तेमाल करना
अगर आपका ऐप्लिकेशन सिर्फ़ तब डेटा-लेयर इवेंट के बारे में जानकारी इकट्ठा करता है, जब उपयोगकर्ता ऐप्लिकेशन के साथ इंटरैक्ट कर रहा हो, तो उसे डेटा में होने वाले हर बदलाव को मैनेज करने के लिए, लंबे समय तक चलने वाली सेवा की ज़रूरत नहीं पड़ सकती. ऐसे में, किसी गतिविधि में इवेंट सुने जा सकते हैं.
ज़्यादा सुरक्षित और बेहतर तरीके से काम करने वाले कोड के लिए, लाइफ़साइकल ऑब्ज़र्वर का इस्तेमाल करें. लाइफ़साइकल ऑब्ज़र्वर का इस्तेमाल करके, रजिस्ट्रेशन लॉजिक को ऐक्टिविटी के onResume() से हटाकर, फिर से इस्तेमाल की जा सकने वाली एक अलग क्लास में ले जाया जाता है. यह क्लास DefaultLifecycleObserver को लागू करती है.
इस तरीके से, आपकी गतिविधि कम हो जाती है और लिसनर को अनरजिस्टर करने जैसी सामान्य गड़बड़ियों को रोका जा सकता है.
1. लाइफ़साइकल की जानकारी रखने वाला लिसनर बनाना
यह क्लास, DataClient.OnDataChangedListener को रैप करती है. साथ ही, ऐक्टिविटी के लाइफ़साइकल के आधार पर, अपनी सदस्यता को अपने-आप मैनेज करती है.
class WearDataLayerObserver( private val dataClient: DataClient, private val onDataReceived: (DataEventBuffer) -> Unit ) : DefaultLifecycleObserver, DataClient.OnDataChangedListener { // Implementation of the DataClient listener override fun onDataChanged(dataEvents: DataEventBuffer) { onDataReceived(dataEvents) } // Automatically register when the Activity starts override fun onResume(owner: LifecycleOwner) { dataClient.addListener(this) } // Automatically unregister when the Activity pauses override fun onPause(owner: LifecycleOwner) { dataClient.removeListener(this) } }
2. आपकी गतिविधि में इस्तेमाल
अब Wear API के लिए, आपकी गतिविधि को onResume() या onPause() को बदलने की ज़रूरत नहीं है. ऑब्ज़र्वर को onCreate() में एक बार जोड़ा जाता है.
class DataLayerLifecycleActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val dataClient = Wearable.getDataClient(this) // Create the observer and link it to the activity's lifecycle val wearObserver = WearDataLayerObserver(dataClient) { dataEvents -> handleDataEvents(dataEvents) } lifecycle.addObserver(wearObserver) } private fun handleDataEvents(dataEvents: DataEventBuffer) { // ... filter and process events ... } }
यह बेहतर क्यों है:
- Cleaner Activity: इससे Activity के लाइफ़साइकल के तरीकों से बॉयलरप्लेट कोड हटाया जाता है.
- सुरक्षा:
DefaultLifecycleObserverयह पुष्टि करने में मदद करता है कि लिसनर को हटा दिया गया है. भले ही, गतिविधि अचानक बंद हो गई हो. इससे मेमोरी लीक होने से रोकने में मदद मिलती है. - फिर से इस्तेमाल किया जा सकता है: रजिस्ट्रेशन लॉजिक को फिर से लिखे बिना, इस
WearDataLayerObserverको किसी भी गतिविधि या फ़्रैगमेंट में प्लग किया जा सकता है. - डिकपल करना: सुनने के लॉजिक को, डेटा के साथ क्या करना है, इसके लॉजिक से अलग किया जाता है.
लाइव सुनने वाले लोगों के लिए फ़िल्टर इस्तेमाल करना
जैसा कि पहले बताया गया है, मेनिफ़ेस्ट पर आधारित WearableListenerService ऑब्जेक्ट के लिए इंटेंट फ़िल्टर तय किए जा सकते हैं. इसी तरह, Wearable API के ज़रिए लाइव लिसनर रजिस्टर करते समय, इंटेंट फ़िल्टर का इस्तेमाल किया जा सकता है. ये नियम, एपीआई पर आधारित लाइव सुनने वालों और मेनिफ़ेस्ट पर आधारित सुनने वालों, दोनों पर लागू होते हैं.
किसी खास पाथ या पाथ प्रीफ़िक्स के लिए, LifecycleObserver का इस्तेमाल करके लिसनर रजिस्टर करना एक सामान्य पैटर्न है. इस तरह से लिसनर लागू करने पर, आपका ऐप्लिकेशन ज़्यादा चुनिंदा इवेंट पा सकता है. इससे इसके डिज़ाइन और परफ़ॉर्मेंस को बेहतर बनाया जा सकता है.