Data Layer API को कॉल करने पर, कॉल पूरा होने के बाद आपको कॉल का स्टेटस मिल सकता है. इसके अलावा, Wear OS by Google नेटवर्क पर कहीं भी आपके ऐप्लिकेशन के डेटा में हुए बदलावों से जुड़े डेटा इवेंट भी सुने जा सकते हैं.
डेटा लेयर एपीआई का असरदार तरीके से इस्तेमाल करने का उदाहरण देखने के लिए, Android DataLayer Sample ऐप्लिकेशन देखें.
डेटा लेयर कॉल के स्टेटस का इंतज़ार करना
Data Layer API को किए गए कॉल, जैसे कि 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> मेनिफ़ेस्ट एलिमेंट के लिए एपीआई का संदर्भ दस्तावेज़ देखें.
इन्टेंट फ़िल्टर मैच करते समय, दो ज़रूरी नियमों का ध्यान रखें:
- अगर इंटेंट फ़िल्टर के लिए कोई स्कीम तय नहीं की गई है, तो सिस्टम अन्य सभी यूआरआई एट्रिब्यूट को अनदेखा कर देता है.
- अगर फ़िल्टर के लिए कोई होस्ट तय नहीं की गई है, तो सिस्टम सभी पाथ एट्रिब्यूट को अनदेखा कर देता है.
लाइव लिसनर का इस्तेमाल करना
अगर आपका ऐप्लिकेशन सिर्फ़ तब डेटा-लेयर इवेंट के बारे में जानकारी इकट्ठा करता है, जब उपयोगकर्ता ऐप्लिकेशन के साथ इंटरैक्ट कर रहा हो, तो उसे डेटा में होने वाले हर बदलाव को मैनेज करने के लिए, लंबे समय तक चलने वाली सेवा की ज़रूरत नहीं पड़ सकती. ऐसे में, किसी गतिविधि में इवेंट सुने जा सकते हैं.
ज़्यादा सुरक्षित और बेहतर तरीके से काम करने के लिए, लाइफ़साइकल ऑब्ज़र्वर का इस्तेमाल करें. लाइफ़साइकल ऑब्ज़र्वर का इस्तेमाल करके, रजिस्ट्रेशन लॉजिक को गतिविधि के LifecycleResumeEvent से हटाकर, फिर से इस्तेमाल की जा सकने वाली एक अलग क्लास में ले जाया जाता है. यह क्लास 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 के लिए, आपकी गतिविधि को LifecycleResumeEvent या onPause का इस्तेमाल करने की ज़रूरत नहीं है. निरीक्षक को LaunchedEvent (या 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को किसी भी Activity या Composable में प्लग किया जा सकता है. इसके लिए, रजिस्ट्रेशन लॉजिक को फिर से लिखने की ज़रूरत नहीं होती. - डिकपल करना: सुनने के लॉजिक को, डेटा के साथ क्या करना है, इसके लॉजिक से अलग किया जाता है.
लाइव सुनने वाले लोगों के लिए फ़िल्टर इस्तेमाल करना
जैसा कि पहले बताया गया है, मेनिफ़ेस्ट पर आधारित WearableListenerService ऑब्जेक्ट के लिए इंटेंट फ़िल्टर तय किए जा सकते हैं. इसी तरह, Wearable API के ज़रिए लाइव लिसनर रजिस्टर करते समय, इंटेंट फ़िल्टर का इस्तेमाल किया जा सकता है. ये नियम, एपीआई पर आधारित लाइव सुनने वालों और मेनिफ़ेस्ट पर आधारित सुनने वालों, दोनों पर लागू होते हैं.
collectAsStateWithLifecycle() का इस्तेमाल करके, किसी खास पाथ या पाथ प्रीफ़िक्स के साथ लिसनर को रजिस्टर करना एक सामान्य पैटर्न है. इस तरह से लिसनर लागू करने पर, आपका ऐप्लिकेशन ज़्यादा चुनिंदा इवेंट पा सकता है. इससे, ऐप्लिकेशन के डिज़ाइन और परफ़ॉर्मेंस को बेहतर बनाया जा सकता है.