Este documento descreve como sincronizar dados entre um dispositivo Wear OS e um dispositivo portátil.
Enviar e sincronizar dados diretamente da rede
Crie apps para Wear OS que se comuniquem diretamente com a rede. Use a mesma APIs usadas no desenvolvimento para dispositivos móveis, mas que precisam ser específicas para o Wear OS as diferenças em mente.
Sincronizar dados usando a API Data Layer do Wear OS
Um DataClient
expõe uma API para componentes lerem ou gravarem em um DataItem
ou
Asset
É possível definir itens de dados e recursos quando não há conexão com nenhum dispositivo. Eles são sincronizados quando os dispositivos estabelecem uma conexão de rede. Esses dados é particular para seu app e só pode ser acessado por ele em outros dispositivos.
Um
DataItem
é sincronizado em todos os dispositivos conectados a uma rede do Wear OS. Em geral, eles são pequenos.Use um
Asset
para transferir um objeto maior, como uma imagem. O sistema acompanha quais recursos já foram transferidos e realiza a eliminação de duplicação automaticamente.
Detectar eventos em serviços
Estenda a classe WearableListenerService
. O sistema gerencia
ciclo de vida da WearableListenerService
base, vinculada ao serviço quando
que precisa enviar itens de dados ou mensagens e desvincular o serviço quando não há trabalho
necessários.
Detectar eventos em atividades
Implemente a interface OnDataChangedListener
. Use esta interface
de um WearableListenerService
quando quiser detectar mudanças somente quando o
o usuário está usando seu app ativamente.
Transferir dados
Enviar objetos grandes binários por Bluetooth, como uma gravação de voz
de outro dispositivo, é possível anexar um
Asset
em um item de dados e, em seguida, coloca o item no repositório de dados replicado.
Os recursos processam automaticamente o armazenamento de dados em cache para evitar a retransmissão e conservar a largura de banda do Bluetooth. É um padrão comum que um app de dispositivo portátil faça o download de uma imagem, diminua a imagem para um tamanho adequado para exibição no wearable e a envie ao app para wearables como um recurso. Os exemplos abaixo demonstram esse padrão.
Observação: teoricamente, o tamanho dos itens de dados é limitado a 100 KB, mas, na prática, é possível usar itens de dados maiores. Para itens de dados maiores, os desenvolvedores precisam separar os dados por caminhos exclusivos e evitar usar um único caminho para todos os dados. A transferência de recursos grandes afeta a experiência do usuário em muitos casos. Teste seus apps para garantir que eles funcionem bem ao transferir recursos grandes.
Transferir um recurso
Crie o recurso usando um dos métodos create...()
na classe
Asset
.
Converta um bitmap em um stream de bytes e depois chame
createFromBytes()
para criar o recurso, conforme mostrado no exemplo abaixo.
Kotlin
private fun createAssetFromBitmap(bitmap: Bitmap): Asset = ByteArrayOutputStream().let { byteStream -> bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteStream) Asset.createFromBytes(byteStream.toByteArray()) }
Java
private static Asset createAssetFromBitmap(Bitmap bitmap) { final ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteStream); return Asset.createFromBytes(byteStream.toByteArray()); }
Depois, anexe o recurso a um item de dados com o método putAsset()
em
DataMap
ou
PutDataRequest
. Em seguida, coloque o item de dados no armazenamento de dados usando o
putDataItem()
, conforme mostrado nos exemplos a seguir.
O exemplo a seguir usa PutDataRequest
:
Kotlin
val asset: Asset = BitmapFactory.decodeResource(resources, R.drawable.image).let { bitmap -> createAssetFromBitmap(bitmap) } val request: PutDataRequest = PutDataRequest.create("/image").apply { putAsset("profileImage", asset) } val putTask: Task<DataItem> = Wearable.getDataClient(context).putDataItem(request)
Java
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image); Asset asset = createAssetFromBitmap(bitmap); PutDataRequest request = PutDataRequest.create("/image"); request.putAsset("profileImage", asset); Task<DataItem> putTask = Wearable.getDataClient(context).putDataItem(request);
O exemplo a seguir usa PutDataMapRequest
:
Kotlin
val asset: Asset = BitmapFactory.decodeResource(resources, R.drawable.image).let { bitmap -> createAssetFromBitmap(bitmap) } val request: PutDataRequest = PutDataMapRequest.create("/image").run { dataMap.putAsset("profileImage", asset) asPutDataRequest() } val putTask: Task<DataItem> = Wearable.getDataClient(context).putDataItem(request)
Java
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image); Asset asset = createAssetFromBitmap(bitmap); PutDataMapRequest dataMap = PutDataMapRequest.create("/image"); dataMap.getDataMap().putAsset("profileImage", asset); PutDataRequest request = dataMap.asPutDataRequest(); Task<DataItem> putTask = Wearable.getDataClient(context).putDataItem(request);
Receber recursos
Quando um recurso é criado, é provável que você queira fazer a leitura e extração dele no outro lado da conexão. Confira um exemplo de como implementar o callback para detectar uma mudança e extrair o recurso:
Kotlin
override fun onDataChanged(dataEvents: DataEventBuffer) { dataEvents .filter { it.type == DataEvent.TYPE_CHANGED && it.dataItem.uri.path == "/image" } .forEach { event -> val bitmap: Bitmap? = DataMapItem.fromDataItem(event.dataItem) .dataMap.getAsset("profileImage") .let { asset -> loadBitmapFromAsset(asset) } // Do something with the bitmap } } fun loadBitmapFromAsset(asset: Asset): Bitmap? { // Convert asset into a file descriptor and block until it's ready val assetInputStream: InputStream? = Tasks.await(Wearable.getDataClient(context).getFdForAsset(asset)) ?.inputStream return assetInputStream?.let { inputStream -> // Decode the stream into a bitmap BitmapFactory.decodeStream(inputStream) } ?: run { Log.w(TAG, "Requested an unknown Asset.") null } }
Java
@Override public void onDataChanged(DataEventBuffer dataEvents) { for (DataEvent event : dataEvents) { if (event.getType() == DataEvent.TYPE_CHANGED && event.getDataItem().getUri().getPath().equals("/image")) { DataMapItem dataMapItem = DataMapItem.fromDataItem(event.getDataItem()); Asset profileAsset = dataMapItem.getDataMap().getAsset("profileImage"); Bitmap bitmap = loadBitmapFromAsset(profileAsset); // Do something with the bitmap } } } public Bitmap loadBitmapFromAsset(Asset asset) { if (asset == null) { throw new IllegalArgumentException("Asset must be non-null"); } // Convert asset into a file descriptor and block until it's ready InputStream assetInputStream = Tasks.await(Wearable.getDataClient(context).getFdForAsset(asset)) .getInputStream(); if (assetInputStream == null) { Log.w(TAG, "Requested an unknown Asset."); return null; } // Decode the stream into a bitmap return BitmapFactory.decodeStream(assetInputStream); }
Para saber mais, consulte o projeto de exemplo DataLayer (link em inglês) no GitHub.