Синхронизируйте элементы данных с API уровня данных.

DataItem определяет интерфейс, который система использует для синхронизации данных между портативными и носимыми устройствами. DataItem обычно состоит из следующих компонентов:

  • Полезная нагрузка: байтовый массив, который можно заполнить данными, что позволяет выполнять собственную сериализацию и десериализацию объектов. Размер полезной нагрузки ограничен 100 КБ.
  • Путь: уникальная строка, которая должна начинаться с косой черты, например "/path/to/data" .

Примечание: API Data Layer позволяет отправлять сообщения и синхронизировать данные только с телефонами Android или часами Wear OS. Если ваше устройство Wear OS сопряжено с устройством iOS, API Data Layer не будет работать.

По этой причине не используйте API уровня данных в качестве основного способа взаимодействия с сетью. Вместо этого следуйте той же схеме, что и в мобильном приложении, с некоторыми небольшими отличиями .

Обычно DataItem не реализуется напрямую. Вместо этого делается следующее:

  1. Создайте объект PutDataRequest , указав строковый путь для уникальной идентификации элемента.
  2. Вызовите setData() , чтобы установить полезную нагрузку.
  3. Если задержка синхронизации может негативно повлиять на работу пользователя, вызовите setUrgent() .
  4. Используйте метод putDataItem класса DataClient , чтобы запросить у системы создание элемента данных.

При запросе элементов данных система возвращает объекты, которые правильно реализуют интерфейс DataItem . Однако вместо работы с сырыми байтами с помощью setData() мы рекомендуем использовать карту данных , которая предоставляет элемент данных с интерфейсом, подобным Bundle .

Более подробную информацию см. в примере приложения DataLayer .

Синхронизация данных с картой данных

По возможности используйте класс DataMap . Этот подход позволяет работать с элементами данных в формате Android Bundle , благодаря чему система выполняет сериализацию и десериализацию объектов автоматически, а вы можете манипулировать данными с помощью пар «ключ-значение».

Чтобы использовать карту данных:

  1. Создайте объект PutDataMapRequest , задав путь к элементу данных.

    Примечание: Строка пути — это уникальный идентификатор элемента данных, позволяющий получить к нему доступ с любой стороны соединения. Путь должен начинаться с косой черты. Если в вашем приложении используются иерархические данные, создайте схему пути, соответствующую структуре данных.

  2. Вызовите PutDataMapRequest.getDataMap() чтобы получить карту данных, на которой можно задать значения.
  3. Задайте значения для карты данных с помощью методов put...() , таких как putString() .
  4. Если задержка синхронизации может негативно повлиять на работу пользователя, вызовите setUrgent() .
  5. Вызовите PutDataMapRequest.asPutDataRequest() чтобы получить объект PutDataRequest .
  6. Используйте метод 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 .

Вы также можете реализовать прослушиватель как службу. Подробнее см. в разделе Прослушивание событий уровня данных .