在 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() 方法中移除该监听器。

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