本文档介绍了如何在 Wear OS 设备和手机之间同步数据。如需了解何时使用 Data Layer API 以及何时使用基础架构,请参阅概览指南。
直接通过网络发送和同步数据
构建 Wear OS 应用以直接与网络通信。使用与移动应用开发相同的 API,但需要注意一些特定于 Wear OS 的差异。
使用 Wear OS Data Layer API 同步数据
DataClient 会公开一个 API,供组件读取或写入 DataItem 或 Asset。
可以在不连接到任何设备的情况下设置数据项和资源。 当设备建立网络连接时,它们会同步。此数据仅对您的应用可见,并且只能由您的应用在其他设备上访问。
DataItem会在 Wear OS 网络中的所有设备之间同步。它们的大小通常很小。使用
Asset传输较大的对象,例如图片。系统会跟踪哪些资源已传输,并自动执行重复数据消除。
监听服务中的事件
扩展 WearableListenerService 类。系统会管理基本 WearableListenerService 的生命周期,在需要发送数据项或消息时绑定到该服务,而在不需要执行任何操作时取消绑定该服务。
监听 activity 中的事件
实现 OnDataChangedListener 接口。如果您希望仅在用户正在使用您的应用时监听相关更改,请使用此接口而不是 WearableListenerService。
description: Transfer large binary objects, such as images, between Android phones and Wear OS watches using Assets in the Data Layer API. keywords_public: Wear OS, Data Layer API, Assets, Bluetooth data transfer, data synchronization, DataMap, PutDataRequest
同步数据
如需通过蓝牙传输功能共享来自其他设备的录音等大型二进制对象,您可以将 Asset 附加到数据项,然后将数据项放入重复数据存储区。
注意 :Data Layer API 只能通过运行 Android 的手机或 Wear OS 手表发送消息并与之同步数据。如果 Wear OS 设备配对的是 iOS 设备,Data Layer API 将无法正常运行。
因此,请不要使用 Data Layer API 作为与网络进行通信的主要方式。在 Wear OS 应用中,您应遵循与 手机应用中的模式相同的模式,但二者有一些细微差异,详见 Wear OS 上的网络访问和同步。
资源会自动处理数据的缓存,以防止重新传输,并节省蓝牙带宽。对于手机应用来说,一种常见模式是,下载图片,将其缩小到适合在手表上显示的尺寸,然后将其作为资源共享给手表应用。以下示例演示了这一模式。
传输资源
使用 create...() 方法之一在
Asset 类中创建资源。将一个位图转换成字节数组,然后调用
createFromBytes()来创建资源,如以下
示例所示。
private fun createAssetFromBitmap(bitmap: Bitmap): Asset = ByteArrayOutputStream().let { byteStream -> bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteStream) Asset.createFromBytes(byteStream.toByteArray()) }
接下来,使用 putAsset() 方法将资源附加到
DataMap 或 PutDataRequest 中的数据项。然后,使用 putDataItem() 方法将数据项放入
数据存储,如以下
示例所示。
以下示例使用 PutDataRequest:
private fun Context.sendImagePutDataRequest(): Task<DataItem> { val asset: Asset = createAssetFromBitmap(BitmapFactory.decodeResource(resources, R.drawable.ic_walk)) val request: PutDataRequest = PutDataRequest.create("/image").apply { putAsset("profileImage", asset) } val putTask: Task<DataItem> = Wearable.getDataClient(this).putDataItem(request) return putTask }
以下示例使用 PutDataMapRequest:
private fun Context.sendImagePutDataMapRequest(): Task<DataItem> { val asset: Asset = createAssetFromBitmap(BitmapFactory.decodeResource(resources, R.drawable.ic_walk)) val request: PutDataRequest = PutDataMapRequest.create("/image").run { dataMap.putAsset("profileImage", asset) asPutDataRequest() } val putTask: Task<DataItem> = Wearable.getDataClient(this).putDataItem(request) return putTask }
接收资源
创建资源后,您通常会在连接的另一端读取并提取该资源。以下示例说明了如何实现回调来检测资源变化并提取资源:
override fun onDataChanged(dataEvents: DataEventBuffer) { dataEvents .filter { it.type == DataEvent.TYPE_CHANGED && it.dataItem.uri.path == "/image" } .forEach { event -> val asset = DataMapItem.fromDataItem(event.dataItem) .dataMap.getAsset("profileImage") asset?.let { safeAsset -> lifecycleScope.launch { val bitmap = loadBitmapFromAsset(safeAsset) // Do something with the bitmap } } } } private suspend fun loadBitmapFromAsset(asset: Asset): Bitmap? = withContext(Dispatchers.IO) { try { val assetResult = Wearable.getDataClient(this@DataLayerActivity2) .getFdForAsset(asset) .await() assetResult?.inputStream?.use { inputStream -> BitmapFactory.decodeStream(inputStream) } } catch (e: Exception) { e.printStackTrace() null } }
如需了解详情,请参阅 GitHub 上的 DataLayer 示例项目。