Cómo transferir recursos en Wear

Para enviar grandes BLOB de datos binarios, como imágenes, mediante transporte Bluetooth, puedes adjuntar un Asset a un elemento de datos y, luego, colocar ese elemento en el almacén de datos de réplica.

Nota: Si bien una app para Wear se puede comunicar con una app para teléfonos mediante la API de Data Layer que se menciona más abajo, no se recomienda establecer conexión con una red usando esta API.

Los recursos manejan automáticamente el almacenamiento en caché de datos para evitar la retransmisión y conservar el ancho de banda de Bluetooth. Un patrón común es que una app para dispositivos portátiles descargue una imagen, reduzca su tamaño a uno apropiado para mostrarla en el wearable y la transmita como recurso a la app para wearables. En los siguientes ejemplos, se muestra este patrón.

Nota: Aunque el tamaño de los elementos de datos está limitado a 100 KB, los recursos pueden ser tan grandes como se desee. Sin embargo, como la transferencia de recursos grandes en muchos casos afecta la experiencia del usuario, prueba tus apps para asegurarte de que funcionen bien si transfieres recursos grandes.

Consulta los siguientes recursos relacionados:

Cómo transferir un recurso

Crea el recurso usando uno de los métodos create...() en la clase Asset. Aquí convertimos un mapa de bits en un flujo de bytes y, luego, llamamos a createFromBytes() para crear el recurso.

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());
    }
    

Cuando tengas un recurso, adjúntalo a un elemento de datos con el método putAsset() DataMap o PutDataRequest y, luego, coloca el elemento de datos en el almacén de datos con putDataItem():

Cómo usar 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);
    

Cómo usar 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);
    

Cómo recibir recursos

Cuando se crea un recurso, es probable que quieras leerlo y extraerlo en otro extremo de la conexión. A continuación, se incluye un ejemplo de cómo implementar la devolución de llamada para detectar un cambio de recurso y extraerlo:

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