DataItem
определяет интерфейс, который система использует для синхронизации данных между портативными и носимыми устройствами. DataItem
обычно состоит из следующих компонентов:
- Полезная нагрузка: байтовый массив, который можно заполнить данными, что позволяет выполнять собственную сериализацию и десериализацию объектов. Размер полезной нагрузки ограничен 100 КБ.
- Путь: уникальная строка, которая должна начинаться с косой черты, например
"/path/to/data"
.
Примечание: API Data Layer позволяет отправлять сообщения и синхронизировать данные только с телефонами Android или часами Wear OS. Если ваше устройство Wear OS сопряжено с устройством iOS, API Data Layer не будет работать.
По этой причине не используйте API уровня данных в качестве основного способа взаимодействия с сетью. Вместо этого следуйте той же схеме, что и в мобильном приложении, с некоторыми небольшими отличиями .
Обычно DataItem
не реализуется напрямую. Вместо этого делается следующее:
- Создайте объект
PutDataRequest
, указав строковый путь для уникальной идентификации элемента. - Вызовите
setData()
, чтобы установить полезную нагрузку. - Если задержка синхронизации может негативно повлиять на работу пользователя, вызовите
setUrgent()
. - Используйте метод
putDataItem
классаDataClient
, чтобы запросить у системы создание элемента данных.
При запросе элементов данных система возвращает объекты, которые правильно реализуют интерфейс DataItem
. Однако вместо работы с сырыми байтами с помощью setData()
мы рекомендуем использовать карту данных , которая предоставляет элемент данных с интерфейсом, подобным Bundle
.
Более подробную информацию см. в примере приложения DataLayer .
Синхронизация данных с картой данных
По возможности используйте класс DataMap
. Этот подход позволяет работать с элементами данных в формате Android Bundle
, благодаря чему система выполняет сериализацию и десериализацию объектов автоматически, а вы можете манипулировать данными с помощью пар «ключ-значение».
Чтобы использовать карту данных:
- Создайте объект
PutDataMapRequest
, задав путь к элементу данных.Примечание: Строка пути — это уникальный идентификатор элемента данных, позволяющий получить к нему доступ с любой стороны соединения. Путь должен начинаться с косой черты. Если в вашем приложении используются иерархические данные, создайте схему пути, соответствующую структуре данных.
- Вызовите
PutDataMapRequest.getDataMap()
чтобы получить карту данных, на которой можно задать значения. - Задайте значения для карты данных с помощью методов
put...()
, таких какputString()
. - Если задержка синхронизации может негативно повлиять на работу пользователя, вызовите
setUrgent()
. - Вызовите
PutDataMapRequest.asPutDataRequest()
чтобы получить объектPutDataRequest
. - Используйте метод
putDataItem
классаDataClient
, чтобы запросить у системы создание элемента данных.Примечание: если телефон и носимые устройства отключены, данные буферизуются и синхронизируются при восстановлении соединения.
Метод increaseCounter()
в следующем примере показывает, как создать карту данных и поместить в нее данные:
Котлин
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) } ... }
Ява
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
см. в справочной документации .
Внимание: Перед использованием API Wearable Data Layer убедитесь, что он доступен на устройстве; в противном случае возникнет исключение. Используйте класс GoogleApiAvailability
, как реализовано в Horologist .
Установить приоритет DataItem
API DataClient
позволяет выполнять срочные запросы на синхронизацию объектов DataItem
. Обычно система откладывает доставку элементов данных в сеть Wear OS для экономии заряда батареи пользовательских устройств, но если задержка в синхронизации элементов данных негативно влияет на пользовательский опыт, вы можете пометить их как срочные. Например, в приложении для удалённого управления, где пользователь ожидает немедленного выполнения своих действий, вы можете заставить систему синхронизировать элементы данных немедленно, вызвав setUrgent()
.
Если не вызывать setUrgent()
, система может задержать синхронизацию несрочных элементов данных до 30 минут, хотя обычно задержка составляет всего несколько минут. По умолчанию срочность — несрочная, поэтому необходимо использовать setUrgent()
если нужно сохранить режим немедленной синхронизации, реализованный в предыдущих версиях API Wear OS.
Прослушивание событий элемента данных
Если одна сторона соединения уровня данных изменяет элемент данных, уведомите пользователя о любых изменениях на другой стороне соединения. Это можно сделать, реализовав прослушиватель событий элемента данных.
Фрагмент кода в следующем примере уведомляет приложение об изменении значения счетчика, определенного в предыдущем примере:
Котлин
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) { ... } ... }
Ява
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 .
Вы также можете реализовать прослушиватель как службу. Подробнее см. в разделе Прослушивание событий уровня данных .