Transférer des éléments sur Wear

Pour envoyer des objets binaires volumineux via le transport Bluetooth, tels qu'un enregistrement vocal depuis un autre appareil, vous pouvez associer un Asset à un élément de données, puis placer l'élément de données dans le data store répliqué.

Les éléments gèrent automatiquement la mise en cache des données pour empêcher la retransmission et préserver la bande passante Bluetooth. Il est courant de télécharger une image, de la réduire à une taille appropriée pour l'afficher sur l'objet connecté et de la transmettre à l'application connectée en tant qu'élément. Les exemples suivants illustrent ce schéma.

Remarque : Bien que la taille des éléments de données soit théoriquement limitée à 100 Ko, en pratique, vous pouvez utiliser des éléments de données plus volumineux. Pour les éléments de données plus volumineux, séparez les données par des chemins uniques et éviter d'utiliser un seul chemin pour toutes les données. Dans de nombreux cas, le transfert d'éléments volumineux affecte l'expérience utilisateur. Par conséquent, testez vos applications pour vous assurer qu'elles fonctionnent bien lors de ce type de transfert.

Transférer un élément

Créez l'élément à l'aide de l'une des méthodes create...() de la classe Asset. Convertissez un bitmap en flux d'octets, puis appelez createFromBytes() pour créer l'élément, comme illustré dans l'exemple suivant.

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

Associez ensuite cet élément à un élément de données avec la méthode putAsset() dans DataMap ou PutDataRequest. Puis, placez l'élément de données dans le data store à l'aide de la méthode putDataItem(), comme indiqué dans les exemples suivants.

L'exemple suivant utilise "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);
L'exemple suivant utilise "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);

Recevoir les éléments

Lorsqu'un élément est créé, vous souhaitez probablement le lire et l'extraire de l'autre côté de la connexion. Voici un exemple d'implémentation du rappel pour détecter une modification d'élément et l'extraire :

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

Pour en savoir plus, consultez l'exemple de projet DataLayer sur GitHub.