כשמבצעים קריאה ל-Data Layer API, אפשר לקבל בסטטוס השיחה בסיום השיחה. אפשר גם להאזין לאירועי נתונים כתוצאה משינויים בנתונים שהאפליקציה שלך עורכת במקום כלשהו רשת Wear OS by Google.
דוגמה לעבודה יעילה עם ה-Data Layer API, אפשר לעיין האפליקציה Android DataLayer Sample.
המתנה לסטטוס של קריאות לשכבת הנתונים
קריאות ל-Data Layer API — כמו קריאה באמצעות putDataItem
ה-method של
מחלקה
DataClient
— לפעמים מוחזר
אובייקט
Task<ResultType>
. מיד אחרי שהאובייקט Task
נוצר, הפעולה
בהמתנה בתור ברקע. אם לא תבצעו שום פעולה נוספת לאחר מכן, הפעולה
מסתיים בשקט.
אבל בדרך כלל רצוי לעשות משהו
את התוצאה אחרי סיום הפעולה, כך שהאובייקט Task
מאפשר
להמתין לסטטוס התוצאה באופן אסינכרוני או סינכרוני.
קריאות אסינכרוניות
אם הקוד פועל בשרשור הראשי של ממשק המשתמש, אל תבצעו הפעלות של חסימה אל
ממשק API של שכבת נתונים. הרצת הקריאות באופן אסינכרוני על ידי הוספת שיטת קריאה חוזרת
לאובייקט 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));
Tasks API מאפשר אפשרויות אחרות, כולל יצירת שרשורים של ביצוע משימות שונות.
שיחות סינכרוניות
אם הקוד שלכם פועל ב-thread נפרד של handler בשירות רקע,
למשל, ב
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
. - יצירת פעילות או מחלקה שמטמיעים את הממשק של
DataClient.OnDataChangedListener
.
בשתי האפשרויות האלה אפשר לבטל את השיטות לקריאה חוזרת של אירועי נתונים עבור אירועים שברצונך לטפל בהם.
הערה: כשבוחרים באפשרות הזו, כדאי להביא בחשבון את השימוש בסוללה של האפליקציה
הטמעת מכשיר Listener. WearableListenerService
רשום במניפסט של האפליקציה ויכול להפעיל את האפליקציה אם עדיין לא
ריצה. אם אתם צריכים להאזין לאירועים רק כשהאפליקציה כבר פועלת,
וזה קורה לעיתים קרובות באפליקציות אינטראקטיביות,
WearableListenerService
במקום זאת, מומלץ לרשום מאזינים בשידור חי.
לדוגמה, אפשר להשתמש בשיטה addListener
של DataClient
.
בכיתה. הפעולה הזו יכולה להפחית את העומס על המערכת ולהפחית את השימוש בסוללה.
שימוש ב-WearableListenerService
בדרך כלל יוצרים מופעים של
WearableListenerService
גם בגאדג'ט הלביש וגם
לאפליקציות להחזקה ביד. אבל, אם אתם לא מעוניינים באירועי נתונים באחד
אין צורך להטמיע את השירות באפליקציה הזו.
לדוגמה, אפשר ליצור אפליקציה להחזקה ביד שמגדירה ומקבלת אובייקטים של פריטי נתונים ואפליקציה לבישה שמזהה את העדכונים האלה כדי לעדכן את ממשק המשתמש שלה. האפליקציה הלבישה אף פעם לא מעדכנת אף אחד מפריטי הנתונים, לכן האפליקציה להחזקה ביד להאזין לאירועי נתונים מהאפליקציה הלבישה.
חלק מהאירועים שאפשר להאזין להם בעזרת
WearableListenerService
הם:
-
onDataChanged()
: בכל פעם שאובייקט של פריט נתונים נוצר, נמחק או משתנה, המערכת מופעלת הקריאה החוזרת (callback) הזו בכל הצמתים המחוברים. -
onMessageReceived()
: הודעה שנשלחה מטריגר של צומת הקריאה החוזרת (callback) הזו בצומת היעד. -
onCapabilityChanged()
: כשאפשרות שמופע של האפליקציה מפרסמת מתאפשרת ברשת, האירוע הזה יפעיל את הקריאה החוזרת (callback). אם ברצונך לחפש של צומת קרוב, אפשר לשלוח שאילתה שיטתisNearby()
של הצמתים שצוינו בקריאה החוזרת (callback).
אפשר גם להאזין לאירועים מ-
ChannelClient.ChannelCallback
, כמו onChannelOpened()
.
כל האירועים הקודמים מבוצעים בשרשור ברקע, לא בשרשור הראשי.
כדי ליצור WearableListenerService
, פועלים לפי השלבים הבאים:
- יצירת כיתה שמרחיבים את
WearableListenerService
. - להאזין לאירועים שמעניינים אותך, כמו
onDataChanged()
. - יש להצהיר על מסנן Intent במניפסט של 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); } } }
בקטע הבא מוסבר איך להשתמש במסנן Intent עם המאזינים האלה.
שימוש במסננים עם WearableListenerService
מסנן Intent לדוגמה של 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. אפשר לציין כמה שירותים
לכל מניפסט, מספר מסנני Intent לכל שירות, מספר פעולות לכל מסנן
ומכמה שורות נתונים לכל מסנן. המסננים יכולים להתאים במארח תו כללי לחיפוש או במופעל
ספציפית. כדי לבצע התאמה במארח עם תו כללי לחיפוש, יש להשתמש בפונקציה host="*"
. התאמה
במארח ספציפי, מציינים את host=<node_id>
.
אפשר גם להתאים ערך מילולי או קידומת של נתיב. כדי לעשות את זה, יש לציין תו כללי לחיפוש או מארח ספציפי. אחרת, המערכת תתעלם מהנתיב שציינתם.
למידע נוסף על סוגי המסננים שנתמכים ב-Wear OS, אפשר לעיין במאמר בנושא
מאמרי העזרה של ה-API עבור
WearableListenerService
מידע נוסף על מסנני נתונים וכללי התאמה זמין בהפניית ה-API
מסמכים עבור <data>
רכיב מניפסט.
כשמתאימים בין מסנני Intent, חשוב לזכור שני כללים חשובים:
- אם לא צוינה סכמה למסנן Intent, המערכת מתעלמת כל שאר מאפייני ה-URI.
- אם לא צוין מארח למסנן, המערכת תתעלם את כל מאפייני הנתיב.
שימוש בהאזנה בזמן אמת
אם לאפליקציה שלכם אכפת רק מאירועים בשכבת הנתונים כשהמשתמש יוצר אינטראקציה איתם את האפליקציה, ייתכן שהיא לא תצטרך שירות ארוך טווח כדי לטפל בכל שינוי בנתונים. לחשבון במקרה כזה, אפשר להאזין לאירועים בפעילות על ידי הטמעה של אירוע אחד או באחד מהממשקים הבאים:
DataClient.OnDataChangedListener
MessageClient.OnMessageReceivedListener
CapabilityClient.OnCapabilityChangedListener
ChannelClient.ChannelCallback
כדי ליצור פעילות שמאזינים לאירועי נתונים:
- להטמיע את הממשקים הרצויים.
- בשיטה
onCreate()
אוonResume()
, מתקשריםWearable.getDataClient(this).addListener()
,MessageClient.addListener()
,CapabilityClient.addListener()
, אוChannelClient.registerChannelCallback()
כדי לשלוח הודעה ל-Google Play השירותים שאתם מעוניינים להאזין להם עבור אירועים של שכבת נתונים. - בתיקייה
onStop()
אוonPause()
, ביטול רישום של מאזינים ב-DataClient.removeListener()
,MessageClient.removeListener()
,CapabilityClient.removeListener()
, אוChannelClient.unregisterChannelCallback()
. - אם פעילות מסוימת מתעניינת רק באירועים עם קידומת של נתיב ספציפית, יכול להוסיף אוזן עם מסנן תחילית מתאים כדי לקבל רק נתונים שרלוונטיים למצב הנוכחי של האפליקציה.
- הטמעה של
onDataChanged()
,onMessageReceived()
,onCapabilityChanged()
, או methods מ-ChannelClient.ChannelCallback
, בהתאם לממשקים שהטמעתם. השיטות האלה מופעלות של ה-thread הראשי, או שאפשר לציין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()); } } } }
שימוש בפילטרים עם מאזינים בשידור חי
כפי שצוין קודם, בדיוק כמו שאפשר לציין מסנני Intent עבור
WearableListenerService
מבוסס מניפסט
ניתן להשתמש במסנני Intent במהלך רישום של האזנה פעילה באמצעות
גאדג'טים לבישים
API. אותם כללים חלים גם על מאזינים בזמן אמת שמבוססים על API וגם על
מאזינים שמבוססים על מניפסטים.
דפוס נפוץ הוא רישום מאזינים עם נתיב ספציפי או תחילית ספציפית של נתיב
onResume()
של פעילות
ואז להסיר את המאזינים בפעילות
onPause()
.
הטמעת מאזינים באופן הזה מאפשרת לאפליקציה באופן סלקטיבי יותר
לקבל אירועים, ולשפר את העיצוב והיעילות שלו.