Daten synchronisieren

In diesem Dokument wird beschrieben, wie Daten zwischen einem Wear OS-Gerät und einem Smartphone synchronisiert werden. In der Übersicht finden Sie Informationen dazu, wann Sie die Data Layer API und wann Sie Ihre Infrastruktur verwenden sollten.

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 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 für Ihre App und können nur von Ihrer App auf anderen Geräten aufgerufen werden.

  • 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 die Deduplizierung automatisch durch.

Auf Ereignisse in Diensten warten

Erweitern Sie die Klasse WearableListenerService. Das System verwaltet den Lebenszyklus des 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

OnDataChangedListener-Schnittstelle implementieren. Verwenden Sie diese Schnittstelle anstelle eines WearableListenerService, wenn Sie nur dann auf Änderungen reagieren möchten, wenn der Nutzer Ihre App aktiv verwendet.

description: Transfer large binary objects, such as images, between Android phones and Wear OS watches using Assets in the Data Layer API. keywords_public: Wear OS, Data Layer API, Assets, Bluetooth data transfer, data synchronization, DataMap, PutDataRequest

Daten synchronisieren

Wenn Sie große binäre Objekte über Bluetooth übertragen 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.

Hinweis:Mit der Data Layer API können Nachrichten nur an Smartphones mit Android und Smartwatches mit Wear OS gesendet und Daten nur mit diesen Geräten synchronisiert werden. Wenn ein Wear OS-Gerät mit einem iOS-Gerät gekoppelt ist, funktioniert die Data Layer API nicht.

Verwenden Sie die Data Layer API daher nicht als primäre Methode für die Kommunikation mit einem Netzwerk. Folge stattdessen in deiner Wear OS-App dem gleichen Muster wie in einer Smartphone-App – mit einigen geringfügigen Unterschieden, wie unter Netzwerkzugriff und Synchronisierung unter Wear OS beschrieben.

Assets übernehmen automatisch das Zwischenspeichern von Daten, um eine erneute Übertragung zu verhindern und Bluetooth-Bandbreite zu sparen. Ein häufiges Muster ist, dass eine Smartphone-App ein Bild herunterlädt, es auf eine für die Anzeige auf der Smartwatch geeignete Größe verkleinert und es als Asset für die Smartwatch-App freigibt. Die folgenden Beispiele veranschaulichen dieses Muster.

Asset übertragen

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

private fun createAssetFromBitmap(bitmap: Bitmap): Asset =
    ByteArrayOutputStream().let { byteStream ->
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteStream)
        Asset.createFromBytes(byteStream.toByteArray())
    }

Weisen Sie das Asset als Nächstes mit der Methode putAsset() in DataMap oder PutDataRequest einem Datenelement zu. Speichern Sie das Datenelement dann mit der Methode putDataItem() im Datenspeicher, wie in den folgenden Beispielen gezeigt.

Im folgenden Beispiel wird PutDataRequest verwendet:

private fun Context.sendImagePutDataRequest(): Task<DataItem> {

    val asset: Asset = createAssetFromBitmap(BitmapFactory.decodeResource(resources, R.drawable.ic_walk))
    val request: PutDataRequest = PutDataRequest.create("/image").apply {
        putAsset("profileImage", asset)
    }
    val putTask: Task<DataItem> = Wearable.getDataClient(this).putDataItem(request)

    return putTask
}

Im folgenden Beispiel wird PutDataMapRequest verwendet:

private fun Context.sendImagePutDataMapRequest(): Task<DataItem> {

    val asset: Asset = createAssetFromBitmap(BitmapFactory.decodeResource(resources, R.drawable.ic_walk))
    val request: PutDataRequest = PutDataMapRequest.create("/image").run {
        dataMap.putAsset("profileImage", asset)
        asPutDataRequest()
    }
    val putTask: Task<DataItem> = Wearable.getDataClient(this).putDataItem(request)

    return putTask
}

Assets erhalten

Nachdem Sie ein Asset erstellt haben, lesen und extrahieren Sie es in der Regel auf der anderen Seite der Verbindung. Das folgende Beispiel zeigt, wie der Callback implementiert wird, 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.