使用数据层 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 示例应用。

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