Синхронизация данных

В этом документе описывается, как синхронизировать данные между устройством Wear OS и телефоном. Ознакомьтесь с общими рекомендациями о том, когда использовать Data Layer API, а когда – собственную инфраструктуру.

Отправка и синхронизация данных напрямую из сети

Создавайте приложения для Wear OS, которые напрямую взаимодействуют с сетью. Используйте те же API, что и для мобильных устройств, но учитывайте особенности Wear OS.

Синхронизация данных с помощью Wear OS Data Layer API

DataClient предоставляет API, с помощью которого компоненты могут считывать данные из DataItem или Asset и записывать их туда.

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

  • DataItem синхронизируется на всех устройствах в сети Wear OS. Обычно они небольшого размера.

  • Используйте Asset для передачи более крупных объектов, например изображений. Система отслеживает, какие объекты уже были перенесены, и автоматически удаляет дубликаты.

Как отслеживать события в сервисах

Расширьте класс WearableListenerService. Система управляет жизненным циклом базового класса WearableListenerService, привязывая его к сервису, когда нужно отправить данные или сообщения, и отменяя привязку, когда работа не требуется.

Как отслеживать события в действиях

Реализуйте интерфейс OnDataChangedListener. Используйте этот интерфейс вместо WearableListenerService, если хотите отслеживать изменения только тогда, когда пользователь активно работает с приложением.

description: Передавайте большие двоичные объекты, например изображения, между телефонами Android и часами Wear OS, используя объекты в Data Layer API. keywords_public: Wear OS, Data Layer API, объекты, передача данных по Bluetooth, синхронизация данных, DataMap, PutDataRequest

Синхронизация данных

Чтобы передавать по Bluetooth большие двоичные объекты, например запись голоса с другого устройства, можно прикрепить Asset к объекту данных, а затем поместить этот объект в реплицированное хранилище данных.

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

Поэтому не используйте Data Layer API в качестве основного способа связи с сетью. Вместо этого используйте в приложении для Wear OS ту же схему, что и в приложении "Телефон", с небольшими различиями, описанными в статье Доступ к сети и синхронизация в Wear OS.

Объекты автоматически обрабатывают кэширование данных, чтобы предотвратить повторную передачу и сохранить пропускную способность Bluetooth. Обычно приложение "Телефон" скачивает изображение, уменьшает его до размера, подходящего для часов, и передает его в приложение для часов в качестве объекта. Следующие примеры демонстрируют эту закономерность.

Как передать объект

Создайте объект, используя один из методов create...() в классе Asset. Преобразуйте растровое изображение в массив байтов, а затем вызовите createFromBytes(), чтобы создать объект, как показано в примере ниже.

private fun createAssetFromBitmap(bitmap: Bitmap): Asset =
    ByteArrayOutputStream().let { byteStream ->
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteStream)
        Asset.createFromBytes(byteStream.toByteArray())
    }

Затем прикрепите объект к элементу данных с помощью метода putAsset() в DataMap или PutDataRequest. Затем поместите элемент данных в хранилище данных с помощью метода putDataItem(), как показано в следующих примерах.

В следующем примере используется PutDataRequest:

private fun Context.sendImagePutDataRequest(): Task<DataItem> {

    val asset: Asset = createAssetFromBitmap(BitmapFactory.decodeResource(resources, R.drawable.ic_walk))
    val request: PutDataRequest = PutDataRequest.create("/image").apply {
        putAsset("profileImage", asset)
    }
    val putTask: Task<DataItem> = Wearable.getDataClient(this).putDataItem(request)

    return putTask
}

В следующем примере используется PutDataMapRequest:

private fun Context.sendImagePutDataMapRequest(): Task<DataItem> {

    val asset: Asset = createAssetFromBitmap(BitmapFactory.decodeResource(resources, R.drawable.ic_walk))
    val request: PutDataRequest = PutDataMapRequest.create("/image").run {
        dataMap.putAsset("profileImage", asset)
        asPutDataRequest()
    }
    val putTask: Task<DataItem> = Wearable.getDataClient(this).putDataItem(request)

    return putTask
}

Получение объектов

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

override fun onDataChanged(dataEvents: DataEventBuffer) {
    dataEvents
        .filter { it.type == DataEvent.TYPE_CHANGED && it.dataItem.uri.path == "/image" }
        .forEach { event ->
            val asset = DataMapItem.fromDataItem(event.dataItem)
                .dataMap.getAsset("profileImage")

            asset?.let { safeAsset ->
                lifecycleScope.launch {
                    val bitmap = loadBitmapFromAsset(safeAsset)
                    // Do something with the bitmap
                }
            }
        }
}

private suspend fun loadBitmapFromAsset(asset: Asset): Bitmap? = withContext(Dispatchers.IO) {
    try {
        val assetResult = Wearable.getDataClient(this@DataLayerActivity2)
            .getFdForAsset(asset)
            .await()

        assetResult?.inputStream?.use { inputStream ->
            BitmapFactory.decodeStream(inputStream)
        }
    } catch (e: Exception) {
        e.printStackTrace()
        null
    }
}

Дополнительную информацию можно найти в примере проекта DataLayer на GitHub.