呼叫 Data Layer API 時,您可以在呼叫完成後收到呼叫的狀態。如果應用程式在 Wear OS by Google 網路中的任何位置發生資料變更,您也可以監聽因此而產生的資料事件。
如需有效使用 Data Layer API 的範例,請參閱「Android 資料層範例」應用程式。
等待資料層呼叫的狀態
呼叫 Data Layer API (例如使用
DataClient
類別的 putDataItem
方法呼叫) 有時會傳回
Task<ResultType>
物件。建立 Task
物件後,這項作業會在背景中排入佇列。如果操作完成後不再執行其他動作,作業完成時不會發送通知。
不過,您通常會希望在作業完成後,針對結果執行某些操作,因此 Task
物件可讓您以非同步或同步的方式等待結果狀態。
非同步呼叫
如果您的程式碼在主 UI 執行緒上執行,請勿封鎖對 Data Layer 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));
請參閱 Task API 瞭解其他可能性,包括鏈結不同工作的執行作業。
同步呼叫
如果程式碼是在背景服務中的個別處理常式執行緒上執行 (例如在
WearableListenerService
中),則可以封鎖呼叫。在這種情況下,您可以在 Task
物件上呼叫 Tasks.await()
,在要求完成並傳回 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
介面的活動或類別。
使用這兩個選項時,您可以針對要處理的事件,覆寫資料事件回呼方法。
注意:選擇實作事件監聽器時,請考慮應用程式的電池用量。WearableListenerService
已在應用程式的資訊清單中註冊,如果應用程式尚未執行,則可將其啟動。如果您只需要在應用程式執行期間監聽事件 (這通常是互動式應用程式的情況),請勿使用 WearableListenerService
。改為註冊即時事件監聽器。
例如,使用 DataClient
類別的 addListener
方法。這麼做可以降低系統負載並降低電池用量。
使用 WearableListenerService
您通常會一併在穿戴式應用程式與手持應用程式中建立 WearableListenerService
例項。不過,如果您對其中一個應用程式的資料事件不感興趣,就不需要在該應用程式中實作該服務。
例如,您可以建立手持應用程式來設定及取得資料項目物件,以及用來監聽這些更新,藉此更新 UI 的穿戴式應用程式。穿戴式應用程式一律不會更新任何資料項目,因此手持應用程式不會監聽來自穿戴式應用程式的任何資料事件。
您可以使用 WearableListenerService
監聽的部分事件如下:
onDataChanged()
:每當建立、刪除或變更資料項目物件時,系統會在所有連結的節點上觸發這個回呼。onMessageReceived()
:從節點傳送的訊息會在目標節點上觸發這個回呼。onCapabilityChanged()
:當應用程式例項所通告的能力發布到網路上,該事件就會觸發這個回呼。如要尋找附近的節點,可以查詢回呼中提供節點的isNearby()
方法。
您也可以監聽
ChannelClient.ChannelCallback
的事件,例如 onChannelOpened()
。
上述所有事件都是在背景執行緒中執行,而不是在主執行緒中執行。
如要建立 WearableListenerService
,請按照下列步驟操作:
- 建立可擴充
WearableListenerService
的類別。 - 監聽感興趣的事件,例如
onDataChanged()
。 - 在 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); } } }
下一節將說明如何將這個事件監聽器與意圖篩選器搭配使用。
搭配 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
訊息回覆。
請遵循標準 Android 篩選器比對規則。您可以為每個資訊清單指定多項服務、為每個服務指定多個意圖篩選器、為每個篩選器指定多個動作,以及為每個篩選器指定多個資料段落。篩選器可以透過萬用字元主機或特定主機進行比對。如要比對萬用字元主機,請使用 host="*"
。如要比對特定主機,請指定 host=<node_id>
。
您也可以比對常值路徑或路徑前置字串。如要這麼做,您必須指定萬用字元或特定主機,否則系統會忽略您指定的路徑。
如要進一步瞭解 Wear OS 支援的篩選器類型,請參閱 WearableListenerService
的 API 參考資料文件。
如要進一步瞭解資料篩選器和比對規則,請參閱 <data>
資訊清單元素的 API 參考文件。
比對意圖篩選器時,請記得以下兩項重要規則:
- 如果沒有為意圖篩選器指定配置,系統會忽略所有其他 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()
,或從ChannelClient.ChannelCallback
得到的方法。系統會在主執行緒上呼叫這些方法,您也可以使用WearableOptions
指定自訂Looper
。
以下為實作 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()); } } } }
搭配即時監聽器使用篩選器
如上文所述,如同您能夠針對以資訊清單為基礎的 WearableListenerService
物件指定意圖篩選器一樣,您也可以在透過 Wearable API 註冊即時事件監聽器時使用意圖篩選器。無論是以 API 為基礎的即時事件監聽器,還是以資訊清單為基礎的事件監聽器,皆須遵守相同規則。
常見的做法是透過在活動的 onResume()
方法中註冊具有特定路徑或路徑前置字串的事件監聽器,並在活動的 onPause()
方法中移除事件監聽器。以這個方式實作事件監聽器,可讓應用程式在選擇接收事件方面更具彈性,改善應用程式的設計和效率。