在 Wear 上同步数据项

DataItem 会定义系统在手持式设备与穿戴式设备之间同步数据时使用的接口。DataItem 通常由下面几部分组成:

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

注意:Wear 应用可以使用 Data Layer 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,请参阅参考文档

设置 DataItem 优先级

DataClient API 允许紧急请求同步 DataItems。通常,系统可能会延迟向 Wear 网络传递 DataItems,以延长用户设备的电池续航时间,但如果延迟同步 DataItems 会对用户体验产生负面影响,您可以将其标记为紧急。例如,在某个遥控应用中,如果用户期望他们所执行的操作能立即生效,您可以通过调用 setUrgent(),让系统立即同步您的 DataItems

如果您不调用 setUrgent(),系统可能最多延迟 30 分钟后再同步非紧急 DataItems,但通常可以预计的是,即便有延迟,也只有几分钟。现在默认紧急程度为非紧急,因此如果您希望保留旧版本 Wear 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
                }
            }
        }

        // Our 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
                }
            }
        }

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

        ...
    }
    

此 Activity 会实现 DataClient.OnDataChangedListener 接口。此 Activity 在 onResume() 方法中将自身添加为数据项事件的监听器,并在 onPause() 方法中移除该监听器。

您还能以服务的形式实现该监听器。如需了解详情,请参阅监听数据层事件