调用 Data Layer API 时,您可以在调用完成后收到调用状态。如果您的应用在 Wear OS by Google 网络上的任何位置进行了数据更改,您还可以监听因此而引发的数据事件。
如需查看有效使用 Data Layer API 的示例,请参阅 Android DataLayer 示例应用。
等待数据层调用的状态
对 Data Layer API 的调用(例如使用 DataClient 类的 putDataItem 方法进行的调用)有时会返回 Task<ResultType> 对象。一旦创建了 Task 对象,操作便会在后台排队。
如果您在此之后不再进行任何处理,则操作最终会以静默方式完成。
不过,您通常需要在操作完成后对结果进行某种处理,因此 Task 对象允许您以异步或同步方式等待结果状态。
异步调用
如果您的代码是在主界面线程上运行的,请勿对 Data Layer API 进行阻塞调用,并使用协程来调用 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)中的单独处理程序线程上运行,请使用 runBlocking 对 putDataItem 进行阻塞调用。
注意:切勿在主线程上调用此方法。
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 } }
监听数据层事件
由于数据层会在手持式设备和穿戴式设备之间同步和发送数据,因此您通常需要监听一些重要事件,比如创建了数据项、接收了消息等。
要侦听数据层 event,您有两个选择:
- 创建扩展
WearableListenerService的服务。 - 创建实现
DataClient.OnDataChangedListener接口的 activity 或类。
无论选择哪一个,您都需要针对想要处理的事件,替换其数据事件回调方法。
注意:在选择监听器的实现方案时,请考虑应用的电池用量。WearableListenerService 是在应用的清单中注册的,可以在应用尚未运行时启动应用。如果您只需要在应用运行时监听事件(交互式应用通常就是如此),那么请不要使用 WearableListenerService。请改为注册实时监听器。例如,使用 DataClient 类的 addListener 方法。这样可以减少系统上的负载并减少电池用量。
使用 WearableListenerService
您通常需要同时在穿戴式设备应用和手持式设备应用中创建 WearableListenerService 的实例。不过,如果您对其中一个应用中的数据事件不感兴趣,则无需在相应应用中实现该服务。
例如,您可以让手持式设备应用设置并获取数据项对象,而让穿戴式设备应用监听这些更新以更新其界面。穿戴式设备应用从不更新任何数据项,因此手持式设备应用不会监听任何来自穿戴式设备应用的数据事件。
您可以使用 WearableListenerService 监听的部分事件如下:
onDataChanged():每当创建、删除或更改数据项对象时,系统都会在所有连接的节点上触发此回调。onMessageReceived():从某个节点发送的消息会在目标节点上触发此回调。onCapabilityChanged():当您的应用实例广播的某个功能发布到网络上时,该事件会触发此回调。如果您要寻找附近的节点,可以查询回调中提供的节点的isNearby()方法。
您还可以监听来自 ChannelClient.ChannelCallback 的事件,如 onChannelOpened()。
上述所有事件都在后台线程上执行,而不是在主线程上执行。
如需创建 WearableListenerService,请按以下步骤操作:
- 创建一个扩展
WearableListenerService的类。 - 监听您感兴趣的事件,例如
onDataChanged()。 - 在 Android 清单中声明一个 intent 过滤器,以向系统通知您的
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 ) } } }
下一部分介绍如何将 intent 过滤器与此监听器一起使用。
对 WearableListenerService 使用过滤器
上一部分中所示 WearableListenerService 示例的 intent 过滤器可能如下所示:
<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 过滤器匹配规则。您可以为每个清单指定多项服务,为每项服务指定多个 intent 过滤器,为每个过滤器指定多项操作,并为每个过滤器指定多个数据 stanza。过滤器可以匹配通配符主机或特定主机。如需匹配通配符主机,请使用 host="*"。如需匹配特定主机,请指定 host=<node_id>。
您还可以匹配字面量路径或路径前缀。为此,您必须指定通配符或特定主机。否则,系统将忽略您指定的路径。
如需详细了解 Wear OS 支持的过滤器类型,请参阅 WearableListenerService 的 API 参考文档。
如需详细了解数据过滤器和匹配规则,请参阅 <data> 清单元素的 API 参考文档。
在匹配 intent 过滤器时,请谨记两条重要规则:
- 如果没有为 intent 过滤器指定地址协议,系统会忽略其他所有 URI 属性。
- 如果没有为过滤器指定主机,系统会忽略所有路径属性。
使用实时监听器
如果您的应用只关心用户与应用互动时的数据层事件,则可能不需要长时间运行服务来处理每项数据更改。在这种情况下,您可以在 activity 中监听事件。
为了推荐一种更简洁、更安全的方法,请使用生命周期观察器。通过使用生命周期观察器,您可以将注册逻辑从 activity 的 onResume() 中移至实现 DefaultLifecycleObserver 的单独的可重用类中。
这种方法可让您的 activity 保持精简,并防止忘记取消注册监听器等常见 bug。
1. 创建生命周期感知型监听器
此类封装了 DataClient.OnDataChangedListener,并根据 activity 的生命周期自动管理自己的订阅。
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. 在 activity 中的使用情况
现在,您的 activity 无需针对 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 ... } }
这样做的优势在于:
- 更简洁的 Activity:您可以从 Activity 生命周期方法中移除样板代码。
- 安全性:
DefaultLifecycleObserver有助于验证即使 Activity 意外销毁,监听器也会被移除,从而防止内存泄漏。 - 可重用性:您可以将此
WearDataLayerObserver插入任何 Activity 或 Fragment,而无需重写注册逻辑。 - 解耦:侦听时间逻辑与数据处理逻辑分离。
对实时监听器使用过滤器
如前所述,就像您可以为基于清单的 WearableListenerService 对象指定 intent 过滤器一样,您也可以在通过 Wearable API 注册实时监听器时使用 intent 过滤器。基于 API 的实时监听器和基于清单的监听器需遵守相同的规则。
一种常见模式是使用 LifecycleObserver 注册具有特定路径或路径前缀的监听器。以这种方式实现监听器可以让您的应用更有选择性地接收事件,从而改进其设计和效率。