Assets auf Wear übertragen

Um binäre große Objekte über Bluetooth zu senden, z. B. eine Sprachaufnahme von einem anderen Gerät, können Sie ein Asset an ein Datenelement anhängen und es dann im replizierten Datenspeicher ablegen.

Assets übernehmen automatisch das Caching von Daten, um eine erneute Übertragung zu verhindern und die Bluetooth-Bandbreite zu sparen. Ein gängiges Muster ist, dass eine Handheld-App ein Bild herunterlädt, auf eine geeignete Größe für die Anzeige auf dem Wearable verkleinert und als Asset an die Wearable-App überträgt. Die folgenden Beispiele veranschaulichen dieses Muster.

Hinweis: Obwohl die Größe der Datenelemente theoretisch auf 100 KB beschränkt ist, können in der Praxis auch größere Datenelemente verwendet werden. Bei größeren Datenelementen sollten Sie die Daten durch eindeutige Pfade trennen und nicht für alle Daten denselben Pfad verwenden. Die Übertragung großer Assets wirkt sich in vielen Fällen auf die Nutzererfahrung aus. Testen Sie daher Ihre Apps, um sicherzustellen, dass sie beim Übertragen großer Assets eine gute Leistung erzielen.

Asset übertragen

Erstellen Sie das Asset mit einer der create...()-Methoden in der Klasse Asset. Konvertieren Sie eine Bitmap in einen Bytestream und rufen Sie dann createFromBytes() auf, um das Asset zu erstellen, wie im folgenden Beispiel gezeigt.

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

Als Nächstes hängen Sie das Asset mit der Methode putAsset() in DataMap oder PutDataRequest an ein Datenelement an. Legen Sie das Datenelement dann mit der Methode putDataItem() im Datenspeicher ab, wie in den folgenden Beispielen gezeigt.

Im folgenden Beispiel wird `PutDataRequest` verwendet:

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);
Im folgenden Beispiel wird `PutDataMapRequest` verwendet:

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

Assets erhalten

Wenn ein Asset erstellt wird, möchten Sie es wahrscheinlich auf der anderen Seite der Verbindung lesen und extrahieren. Hier ein Beispiel für die Implementierung des Callbacks, mit dem eine Asset-Änderung erkannt und das Asset extrahiert wird:

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

Weitere Informationen finden Sie im DataLayer-Beispielprojekt auf GitHub.