Daten synchronisieren

In diesem Dokument wird beschrieben, wie Sie Daten zwischen einem Wear OS-Gerät und einem Mobilgerät synchronisieren.

Daten direkt aus dem 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 sie in ein DataItem oder Asset lesen oder schreiben können.

Sie können Datenelemente und Assets festlegen, auch wenn keine Verbindung zu Geräten besteht. Sie werden synchronisiert, wenn die Geräte eine Netzwerkverbindung herstellen. Diese Daten sind privat für Ihre App und können nur von Ihrer App auf anderen Geräten aufgerufen werden.

  • Ein 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 WearableListenerService Klasse. Das System verwaltet den Lebenszyklus des Basisdienstes WearableListenerService. Es stellt eine Verbindung zum Dienst her, wenn Datenelemente oder Nachrichten gesendet werden müssen, und trennt die Verbindung, 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 auf Änderungen warten möchten, wenn der Nutzer Ihre App aktiv verwendet.

Daten übertragen

Wenn Sie große binäre Objekte über die Bluetooth-Übertragung senden möchten, z. B. eine Sprachaufzeichnung von einem anderen Gerät, können Sie ein Asset an ein Datenelement anhängen und das Datenelement dann in den replizierten Datenspeicher einfügen.

Assets verarbeiten automatisch das Caching von Daten, um eine erneute Übertragung zu verhindern und Bluetooth-Bandbreite zu sparen. Ein häufiges Muster ist, dass eine mobile 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 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 Asset Klasse. 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 putAsset() Methode in DataMap oder PutDataRequest an ein Datenelement an. Fügen Sie das Datenelement dann mit der putDataItem() Methode in den Datenspeicher ein, 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 Callbacks, um eine Asset-Änderung zu erkennen und das Asset zu extrahieren:

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

Weitere Informationen finden Sie im DataLayer-Beispielprojekt auf GitHub.