In diesem Dokument wird beschrieben, wie Sie Daten zwischen einem Wear OS-Gerät und einem tragbaren Gerät synchronisieren.
Daten direkt vom Netzwerk senden und synchronisieren
Entwickeln Sie Wear OS-Apps, die direkt mit dem Netzwerk kommunizieren. Verwenden Sie dieselben APIs wie für die mobile Entwicklung, beachten Sie aber einige Wear OS-spezifische Unterschiede.
Daten mit der Wear OS Data Layer API synchronisieren
Ein DataClient
stellt eine API für Komponenten bereit, mit der Daten in eine DataItem
oder Asset
gelesen oder geschrieben werden können.
Sie können Datenelemente und Assets festlegen, ohne mit Geräten verbunden zu sein. Sie werden synchronisiert, wenn die Geräte eine Netzwerkverbindung herstellen. Diese Daten sind privat und nur für Ihre App auf anderen Geräten zugänglich.
Eine
DataItem
wird auf allen Geräten in einem Wear OS-Netzwerk synchronisiert. Sie sind in der Regel klein.Verwenden Sie ein
Asset
, um ein größeres Objekt wie ein Bild zu übertragen. Das System verfolgt, welche Assets bereits übertragen wurden, und führt automatisch eine Deduplizierung durch.
Auf Ereignisse in Diensten warten
Erweitern Sie die Klasse WearableListenerService
. Das System verwaltet den Lebenszyklus der Basis-WearableListenerService
. Es stellt eine Verbindung zum Dienst her, wenn Daten oder Nachrichten gesendet werden müssen, und trennt die Verbindung zum Dienst, wenn keine Arbeit erforderlich ist.
Auf Ereignisse in Aktivitäten warten
Implementieren Sie die OnDataChangedListener
-Schnittstelle. Verwenden Sie diese Schnittstelle anstelle von WearableListenerService
, wenn Sie nur dann auf Änderungen reagieren möchten, wenn der Nutzer Ihre App aktiv verwendet.
Daten übertragen
Wenn Sie binäre große Objekte über den Bluetooth-Transport senden möchten, z. B. eine Sprachaufzeichnung von einem anderen Gerät, können Sie einem Datenelement ein
Asset
anhängen und das Datenelement dann in den replizierten Datenspeicher einfügen.
Assets übernehmen automatisch das Caching von Daten, um eine erneute Übertragung zu verhindern und Bluetooth-Bandbreite zu sparen. Ein gängiges Muster ist, dass eine Smartphone-App ein Bild herunterlädt, es auf eine geeignete Größe für die Anzeige auf dem Wearable verkleinert und es als Asset an die Wearable-App überträgt. Die folgenden Beispiele veranschaulichen dieses Muster.
Hinweis:Die Größe von Datenelementen ist theoretisch auf 100 KB begrenzt. In der Praxis können jedoch auch größere Datenelemente verwendet werden. Bei größeren Datenelementen sollten Sie Daten nach eindeutigen Pfaden trennen und nicht einen einzelnen Pfad für alle Daten verwenden. Die Übertragung großer Assets wirkt sich in vielen Fällen auf die Nutzerfreundlichkeit aus. Testen Sie Ihre Apps daher, um sicherzustellen, dass sie bei der Übertragung großer Assets gut funktionieren.
Asset übertragen
Erstellen Sie das Asset mit einer der create...()
-Methoden in der Klasse
Asset
.
Konvertieren Sie eine Bitmap in einen Byte-Stream 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()); }
Hängen Sie das Asset als Nächstes mit der Methode putAsset()
in
DataMap
oder
PutDataRequest
an ein Datenelement an. Speichern Sie das Datenelement dann mit der Methode
putDataItem()
im Datenspeicher, 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 empfangen
Wenn ein Asset erstellt wird, möchten Sie es wahrscheinlich auf der anderen Seite der Verbindung lesen und extrahieren. Hier ist ein Beispiel für die Implementierung des Rückrufs zum Erkennen einer Asset-Änderung und zum Extrahieren des Assets:
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.