Synchronizuj dane

W tym dokumencie opisujemy, jak synchronizować dane między urządzeniem z Wear OS a telefonem. Zapoznaj się z ogólnymi wskazówkami dotyczącymi tego, kiedy używać interfejsu Data Layer API, a kiedy infrastruktury.

Wysyłanie i synchronizowanie danych bezpośrednio z sieci

Twórz aplikacje na Wear OS, które bezpośrednio komunikują się z siecią. Używaj tych samych interfejsów API, których używasz do tworzenia aplikacji mobilnych, ale pamiętaj o różnicach specyficznych dla Wear OS.

Synchronizowanie danych za pomocą interfejsu Wear OS Data Layer API

DataClient udostępnia interfejs API, który umożliwia komponentom odczytywanie danych z DataItem lub Asset oraz zapisywanie w nich danych.

Elementy danych i zasoby można ustawiać bez połączenia z urządzeniami. Są one synchronizowane, gdy urządzenia nawiążą połączenie z siecią. Te dane są prywatne dla Twojej aplikacji i dostępne tylko dla niej na innych urządzeniach.

  • DataItem jest synchronizowany na wszystkich urządzeniach w sieci Wear OS. Zwykle są niewielkie.

  • Użyj Asset, aby przenieść większy obiekt, np. obraz. System śledzi, które komponenty zostały już przeniesione, i automatycznie usuwa duplikaty.

Nasłuchiwanie zdarzeń w usługach

Wydłuż zajęcia WearableListenerService. System zarządza cyklem życia podstawowego WearableListenerService, wiążąc go z usługą, gdy musi wysyłać elementy danych lub wiadomości, i odwiązując go, gdy nie jest potrzebny.

Nasłuchiwanie zdarzeń w aktywnościach

Zaimplementuj interfejs OnDataChangedListener. Używaj tego interfejsu zamiast WearableListenerService, jeśli chcesz nasłuchiwać zmian tylko wtedy, gdy użytkownik aktywnie korzysta z aplikacji.

description: Przenoszenie dużych obiektów binarnych, takich jak obrazy, między telefonami z Androidem a zegarkami z Wear OS za pomocą zasobów w interfejsie Data Layer API. keywords_public: Wear OS, Data Layer API, zasoby, przesyłanie danych przez Bluetooth, synchronizacja danych, DataMap, PutDataRequest

Synchronizowanie danych

Aby udostępniać duże obiekty binarne przez Bluetooth, np. nagranie głosowe z innego urządzenia, możesz dołączyć Asset do elementu danych, a następnie umieścić ten element w replikowanym magazynie danych. Jeśli jednak wymiana jest jednorazowa i odbywa się między 2 połączonymi urządzeniami, zastanów się, czy prostsze przesyłanie bezpośrednie nie będzie bardziej odpowiednie.

Uwaga: interfejs Data Layer API może wysyłać wiadomości i synchronizować dane tylko z telefonami z Androidem lub zegarkami z Wear OS. Jeśli urządzenie z Wear OS jest sparowane z urządzeniem z iOS, interfejs Data Layer API nie będzie działać.

Z tego powodu nie używaj interfejsu Data Layer API jako głównego sposobu komunikacji z siecią. Zamiast tego w aplikacji na Wear OS zastosuj ten sam wzorzec co w aplikacji na telefon – z niewielkimi różnicami opisanymi w artykule Dostęp do sieci i synchronizacja w Wear OS.

Urządzenia automatycznie obsługują buforowanie danych, aby zapobiegać ponownej transmisji i oszczędzać pasmo Bluetooth. Często aplikacja na telefon pobiera obraz, zmniejsza go do rozmiaru odpowiedniego do wyświetlenia na zegarku i udostępnia go aplikacji na zegarek jako zasób. Poniższe przykłady ilustrują ten wzorzec.

Przenoszenie zasobu

Utwórz zasób, korzystając z jednej z metod create...() w klasie Asset. Przekonwertuj bitmapę na tablicę bajtów, a następnie wywołaj createFromBytes(), aby utworzyć komponent, jak pokazano w tym przykładzie.

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

Następnie dołącz zasób do elementu danych za pomocą metody putAsset()DataMap lub PutDataRequest. Następnie umieść element danych w magazynie danych za pomocą metody putDataItem(), jak pokazano w tych przykładach.

W tym przykładzie użyto PutDataRequest:

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
}

W tym przykładzie użyto PutDataMapRequest:

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
}

Otrzymywanie zasobów

Po utworzeniu zasobu zwykle odczytujesz go i wyodrębniasz po drugiej stronie połączenia. Poniższy przykład pokazuje, jak wdrożyć wywołanie zwrotne, aby wykryć zmianę komponentu i wyodrębnić komponent:

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

Więcej informacji znajdziesz w przykładowym projekcie DataLayer w GitHubie.