使用数据层 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的接口。

更多信息,请参阅 DataLayer 示例 应用。

使用数据映射同步数据

尽可能使用 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 允许紧急请求同步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 示例 应用。

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