同步数据

本文档介绍了如何在 Wear OS 设备和手机之间同步数据。如需了解何时使用 Data Layer API 以及何时使用基础架构,请参阅概览指南

直接通过网络发送和同步数据

构建 Wear OS 应用以直接与网络通信。使用与移动应用开发相同的 API,但需要注意一些特定于 Wear OS 的差异。

使用 Wear OS Data Layer API 同步数据

DataClient 会公开一个 API,供组件读取或写入 DataItemAsset

可以在不连接到任何设备的情况下设置数据项和资源。 当设备建立网络连接时,它们会同步。此数据仅对您的应用可见,并且只能由您的应用在其他设备上访问。

  • 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() 方法将资源附加到 DataMapPutDataRequest 中的数据项。然后,使用 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 示例项目