Sincronizar dados

Neste documento, descrevemos como sincronizar dados entre um dispositivo Wear OS e um smartphone. Consulte as orientações gerais para saber quando usar a API da camada de dados e quando usar sua infraestrutura.

Enviar e sincronizar dados diretamente da rede

Crie apps para Wear OS que se comuniquem diretamente com a rede. Use as mesmas APIs que você usa para desenvolvimento de apps para dispositivos móveis, mas não se esqueça de algumas diferenças específicas do Wear OS.

Sincronizar dados usando a API Data Layer do Wear OS

Um DataClient expõe uma API para que os componentes leiam ou gravem em um DataItem ou Asset.

É possível definir itens de dados e recursos sem estar conectado a nenhum dispositivo. Eles são sincronizados quando os dispositivos estabelecem uma conexão de rede. Esses dados são particulares ao seu app e só podem ser acessados por ele em outros dispositivos.

  • Um DataItem é sincronizado em todos os dispositivos conectados a uma rede do Wear OS. Em geral, esses itens são pequenos.

  • Use um Asset para transferir um objeto maior, como uma imagem. O sistema rastreia quais recursos já foram transferidos e realiza a deduplicação automaticamente.

Detectar eventos em serviços

Estenda a classe WearableListenerService. O sistema gerencia o ciclo de vida do WearableListenerService básico, vinculando-o ao serviço quando ele precisa enviar itens de dados ou mensagens e desvinculando o serviço quando nenhuma ação é necessária.

Detectar eventos em atividades

Implementar a interface OnDataChangedListener. Use essa interface em vez de um WearableListenerService quando quiser detectar mudanças apenas quando o usuário estiver usando o app ativamente.

description: Transfira objetos binários grandes, como imagens, entre smartphones Android e relógios Wear OS usando recursos na API Data Layer. keywords_public: Wear OS, API Data Layer, recursos, transferência de dados por Bluetooth, sincronização de dados, DataMap, PutDataRequest

Sincronizar dados

Para compartilhar objetos binários grandes via Bluetooth, como uma gravação de voz de outro dispositivo, anexe um Asset a um item de dados e coloque o item no armazenamento de dados replicado. No entanto, se a troca for única entre dois dispositivos conectados, considere se uma transferência direta mais simples é mais adequada.

Observação:a API Data Layer pode enviar mensagens e sincronizar dados apenas com smartphones Android ou relógios Wear OS. Se um dispositivo Wear OS estiver pareado com um dispositivo iOS, a API Data Layer não vai funcionar.

Por esse motivo, não use a API Data Layer como principal maneira de se comunicar com uma rede. Em vez disso, siga o mesmo padrão no app para Wear OS e na versão para smartphone, com algumas pequenas diferenças, conforme descrito em Acesso à rede e sincronização no Wear OS.

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 para smartphone faça o download de uma imagem, diminua a imagem para um tamanho adequado para exibição no smartwatch e a compartilhe com o app para smartwatch como um recurso. Os exemplos a seguir demonstram esse padrão.

Transferir um recurso

Crie o recurso usando um dos métodos create...() na classe Asset. Converta um bitmap em uma matriz de bytes e depois chame createFromBytes() para criar o recurso, conforme mostrado no exemplo a seguir.

private fun createAssetFromBitmap(bitmap: Bitmap): Asset =
    ByteArrayOutputStream().let { byteStream ->
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteStream)
        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 datastore usando o método putDataItem(), conforme mostrado nos exemplos a seguir.

A amostra a seguir usa 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
}

A amostra a seguir usa 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
}

Receber recursos

Depois de criar um recurso, você normalmente o lê e extrai do outro lado da conexão. O exemplo a seguir mostra como implementar o callback para detectar uma mudança de recurso e extrair o recurso:

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
    }
}

Para mais informações, consulte o projeto de exemplo DataLayer no GitHub.