使用数据层 API 同步数据项

一个 DataItem 定义了系统用于在手持设备和可穿戴设备之间同步数据的接口。一个 DataItem 通常包含以下组件

  • 有效负载: 一个字节数组,您可以用数据设置它,让您进行自己的对象序列化和反序列化。有效负载的大小限制为 100 KB。
  • 路径: 一个唯一的字符串,必须以正斜杠开头,例如 "/path/to/data"

注意: 数据层 API 只能将消息发送到 Android 手机或 Wear OS 手表,并与它们同步数据。如果您的 Wear OS 设备与 iOS 设备配对,数据层 API 将不起作用。

出于这个原因,不要将数据层 API 作为与网络通信的主要方式。相反,请遵循与移动应用相同的模式,但有一些细微的差别

通常您不会直接实现 DataItem。相反,您需要执行以下操作

  1. 创建一个 PutDataRequest 对象,指定一个字符串路径来唯一标识该项目。
  2. 调用 setData() 来设置有效负载。
  3. 如果同步延迟会对用户体验产生负面影响,请调用 setUrgent()
  4. 使用 DataClient 类的 putDataItem 方法请求系统创建数据项。

在请求数据项时,系统会返回正确实现 DataItem 接口的对象。但是,我们建议您使用数据映射,而不是使用 setData() 来处理原始字节,它会公开一个带有 Bundle 类接口的数据项。

有关详细信息,请参阅 数据层示例 应用。

使用数据映射同步数据

尽可能使用 DataMap 类。这种方法可以让您以 Android Bundle 的形式处理数据项,因此系统会为您进行对象序列化和反序列化,您可以使用键值对操作数据。

要使用数据映射,请执行以下操作

  1. 创建一个 PutDataMapRequest 对象,设置数据项的路径。

    注意: 路径字符串是数据项的唯一标识符,可用于从连接的任一端访问它。路径必须以斜杠开头。如果您的应用使用层次数据,请创建与数据结构匹配的路径方案。

  2. 调用 PutDataMapRequest.getDataMap() 获取一个可以设置值的数据映射。
  3. 使用 put...() 方法(例如 putString())为数据映射设置值。
  4. 如果同步延迟会对用户体验产生负面影响,请调用 setUrgent()
  5. 调用 PutDataMapRequest.asPutDataRequest() 获取一个 PutDataRequest 对象。
  6. 使用 DataClient 类的 putDataItem 方法请求系统创建数据项。

    注意: 如果手机和平板设备断开连接,则数据将被缓冲,并在连接重新建立后同步。

以下示例中的 increaseCounter() 方法演示了如何创建数据映射并将数据放入其中

Kotlin

private const val COUNT_KEY = "com.example.key.count"

class MainActivity : Activity() {

    private lateinit var dataClient: DataClient
    private var count = 0
    ...
    // Create a data map and put data in it
    private fun increaseCounter() {
        val putDataReq: PutDataRequest = PutDataMapRequest.create("/count").run {
            dataMap.putInt(COUNT_KEY, count++)
            asPutDataRequest()
        }
        val putDataTask: Task<DataItem> = dataClient.putDataItem(putDataReq)
    }
    ...
}

Java

public class MainActivity extends Activity {
    private static final String COUNT_KEY = "com.example.key.count";
    private DataClient dataClient;
    private int count = 0;
    ...
    // Create a data map and put data in it
    private void increaseCounter() {
        PutDataMapRequest putDataMapReq = PutDataMapRequest.create("/count");
        putDataMapReq.getDataMap().putInt(COUNT_KEY, count++);
        PutDataRequest putDataReq = putDataMapReq.asPutDataRequest();
        Task<DataItem> putDataTask = dataClient.putDataItem(putDataReq);
    }
  ...
}

有关处理 Tasks 的更多信息,请参见 参考文档

设置数据项优先级

DataClient API 允许对 DataItem 对象的同步进行紧急请求。通常,系统会延迟将数据项传递到 Wear OS 网络,以改善用户设备的电池寿命,但如果同步数据项的延迟会对用户体验造成负面影响,则可以将它们标记为紧急。例如,在用户期望其操作立即反映在远程控制应用程序中时,您可以通过调用 setUrgent() 让系统立即同步您的数据项。

如果您没有调用 setUrgent(),系统可能会延迟长达 30 分钟才能同步非紧急数据项,尽管您通常可以预期延迟只有几分钟。默认紧急程度是非紧急的,因此如果您需要保留 Wear OS API 的先前版本的立即同步行为,则必须使用 setUrgent()

监听数据项事件

如果数据层连接的一端更改了数据项,请通知连接另一端的用户有关任何更改。您可以通过为数据项事件实现监听器来实现这一点。

以下示例中的代码片段会在上一个示例中定义的计数器值更改时通知应用程序

Kotlin

private const val COUNT_KEY = "com.example.key.count"

class MainActivity : Activity(), DataClient.OnDataChangedListener {

    private var count = 0

    override fun onResume() {
        super.onResume()
        Wearable.getDataClient(this).addListener(this)
    }

    override fun onPause() {
        super.onPause()
        Wearable.getDataClient(this).removeListener(this)
    }

    override fun onDataChanged(dataEvents: DataEventBuffer) {
        dataEvents.forEach { event ->
            // DataItem changed
            if (event.type == DataEvent.TYPE_CHANGED) {
                event.dataItem.also { item ->
                    if (item.uri.path.compareTo("/count") == 0) {
                        DataMapItem.fromDataItem(item).dataMap.apply {
                            updateCount(getInt(COUNT_KEY))
                        }
                    }
                }
            } else if (event.type == DataEvent.TYPE_DELETED) {
                // DataItem deleted
            }
        }
    }

    // Method to update the count
    private fun updateCount(int: Int) { ... }
    ...
}

Java

public class MainActivity extends Activity implements DataClient.OnDataChangedListener {
    private static final String COUNT_KEY = "com.example.key.count";
    private int count = 0;

    @Override
    protected void onResume() {
        super.onResume();
        Wearable.getDataClient(this).addListener(this);
    }

    @Override
    protected void onPause() {
        super.onPause();
        Wearable.getDataClient(this).removeListener(this);
    }

    @Override
    public void onDataChanged(DataEventBuffer dataEvents) {
        for (DataEvent event : dataEvents) {
            if (event.getType() == DataEvent.TYPE_CHANGED) {
                // DataItem changed
                DataItem item = event.getDataItem();
                if (item.getUri().getPath().compareTo("/count") == 0) {
                    DataMap dataMap = DataMapItem.fromDataItem(item).getDataMap();
                    updateCount(dataMap.getInt(COUNT_KEY));
                }
            } else if (event.getType() == DataEvent.TYPE_DELETED) {
                // DataItem deleted
            }
        }
    }

    // Method to update the count
    private void updateCount(int c) { ... }
    ...
}

此活动实现了 DataClient.OnDataChangedListener 接口。该活动在 onResume() 方法中将自身添加为数据项事件的监听器,并在 onPause() 方法中删除监听器。要查看使用图像、视图模型和服务的实现,请参见 DataLayer 示例 应用程序。

您还可以将监听器实现为服务。有关更多信息,请参见 监听数据层事件