Synchronizowanie elementów danych z interfejsem Data Layer API

DataItem określa interfejs, którego system używa do synchronizowania danych między urządzeniami przenośnymi a urządzeniami do noszenia. DataItem zwykle składa się z tych komponentów:

  • Payload:tablica bajtów, którą możesz ustawić za pomocą danych, co umożliwia samodzielne serializowanie i deserializowanie obiektów. Rozmiar ładunku jest ograniczony do 100 KB.
  • Ścieżka: unikalny ciąg znaków, który musi zaczynać się od ukośnika, np. "/path/to/data".

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 postępuj tak samo jak w przypadku aplikacji mobilnej, z kilkoma drobnymi różnicami.

Zwykle nie implementujesz bezpośrednio funkcji DataItem. Zamiast tego wykonaj te czynności:

  1. Utwórz obiekt PutDataRequest, podając ciąg znaków ścieżki, aby jednoznacznie zidentyfikować element.
  2. Zadzwoń pod numer setData(), aby ustawić ładunek.
  3. Jeśli opóźnienie synchronizacji miałoby negatywny wpływ na wrażenia użytkownika, wywołaj funkcję setUrgent().
  4. Użyj metody putDataItem klasy DataClient, aby poprosić system o utworzenie elementu danych.

Podczas żądania elementów danych system zwraca obiekty, które prawidłowo implementują interfejs DataItem. Zamiast jednak pracować z surowymi bajtami za pomocą funkcji setData(), zalecamy użycie mapy danych, która udostępnia element danych z interfejsem podobnym do Bundle.

Więcej informacji znajdziesz w aplikacji DataLayer Sample.

Synchronizowanie danych z mapą danych

Jeśli to możliwe, używaj klasy DataMap. Dzięki temu możesz pracować z elementami danych w formie Bundle Androida. System zajmuje się serializacją i deserializacją obiektów, a Ty możesz manipulować danymi za pomocą par klucz-wartość.

Aby użyć mapy danych:

  1. Utwórz obiekt PutDataMapRequest, ustawiając ścieżkę elementu danych.

    Uwaga: ciąg ścieżki to unikalny identyfikator elementu danych, który umożliwia dostęp do niego z obu stron połączenia. Ścieżka musi zaczynać się od ukośnika. Jeśli w aplikacji używasz danych hierarchicznych, utwórz schemat ścieżki, który pasuje do struktury danych.

  2. Wywołaj PutDataMapRequest.getDataMap(), aby uzyskać mapę danych, w której możesz ustawić wartości.
  3. Ustaw wartości mapy danych za pomocą metod put...(), np. putString().
  4. Jeśli opóźnienie synchronizacji miałoby negatywny wpływ na wrażenia użytkownika, wywołaj setUrgent().
  5. Zadzwoń pod numer PutDataMapRequest.asPutDataRequest(), aby uzyskać obiekt PutDataRequest.
  6. Użyj metody putDataItem klasy DataClient, aby poprosić system o utworzenie elementu danych.

    Uwaga: jeśli telefon i urządzenia do noszenia są odłączone, dane są buforowane i synchronizowane po ponownym nawiązaniu połączenia.

Metoda increaseCounter() w przykładzie poniżej pokazuje, jak utworzyć mapę danych i umieścić w niej dane:

Kotlin

private const val COUNT_KEY = "com.example.key.count"

class MainActivity : Activity() {

    private lateinit var dataClient: DataClient
    private var count = 0
    ...
    // Create a data map and put data in it
    private fun increaseCounter() {
        val putDataReq: PutDataRequest = PutDataMapRequest.create("/count").run {
            dataMap.putInt(COUNT_KEY, count++)
            asPutDataRequest()
        }
        val putDataTask: Task<DataItem> = dataClient.putDataItem(putDataReq)
    }
    ...
}

Java

public class MainActivity extends Activity {
    private static final String COUNT_KEY = "com.example.key.count";
    private DataClient dataClient;
    private int count = 0;
    ...
    // Create a data map and put data in it
    private void increaseCounter() {
        PutDataMapRequest putDataMapReq = PutDataMapRequest.create("/count");
        putDataMapReq.getDataMap().putInt(COUNT_KEY, count++);
        PutDataRequest putDataReq = putDataMapReq.asPutDataRequest();
        Task<DataItem> putDataTask = dataClient.putDataItem(putDataReq);
    }
  ...
}

Więcej informacji o obsłudze Tasks znajdziesz w  dokumentacji.

Ostrzeżenie: zanim użyjesz interfejsu Wearable Data Layer API, sprawdź, czy jest on dostępny na urządzeniu. W przeciwnym razie wystąpi wyjątek. Użyj klasy GoogleApiAvailability, tak jak w przypadku klasy Horologist.

Ustawianie priorytetu elementu DataItem

Interfejs DataClient API umożliwia przesyłanie pilnych żądań synchronizacji obiektówDataItem. Zwykle system opóźnia dostarczanie elementów danych do sieci Wear OS, aby wydłużyć czas pracy baterii urządzeń użytkowników, ale jeśli opóźnienie w synchronizacji elementów danych negatywnie wpływa na wygodę użytkowników, możesz oznaczyć je jako pilne. Na przykład w aplikacji do zdalnego sterowania, w której użytkownik oczekuje natychmiastowego odzwierciedlenia swoich działań, możesz natychmiast synchronizować elementy danych, wywołując setUrgent().

Jeśli nie wywołasz funkcji setUrgent(), system może opóźnić synchronizację niepilnych elementów danych nawet o 30 minut, choć zwykle opóźnienie wynosi tylko kilka minut. Domyślny poziom pilności to „niepilne”, więc jeśli chcesz zachować zachowanie natychmiastowej synchronizacji z poprzednich wersji interfejsu Wear OS API, musisz użyć setUrgent().

Nasłuchiwanie zdarzeń elementu danych

Jeśli jedna strona połączenia warstwy danych zmieni element danych, powiadom użytkownika o wszelkich zmianach po drugiej stronie połączenia. Możesz to zrobić, wdrażając odbiornik zdarzeń elementu danych.

Fragment kodu w tym przykładzie powiadamia aplikację o zmianie wartości licznika zdefiniowanego w poprzednim przykładzie:

Kotlin

private const val COUNT_KEY = "com.example.key.count"

class MainActivity : Activity(), DataClient.OnDataChangedListener {

    private var count = 0

    override fun onResume() {
        super.onResume()
        Wearable.getDataClient(this).addListener(this)
    }

    override fun onPause() {
        super.onPause()
        Wearable.getDataClient(this).removeListener(this)
    }

    override fun onDataChanged(dataEvents: DataEventBuffer) {
        dataEvents.forEach { event ->
            // DataItem changed
            if (event.type == DataEvent.TYPE_CHANGED) {
                event.dataItem.also { item ->
                    if (item.uri.path.compareTo("/count") == 0) {
                        DataMapItem.fromDataItem(item).dataMap.apply {
                            updateCount(getInt(COUNT_KEY))
                        }
                    }
                }
            } else if (event.type == DataEvent.TYPE_DELETED) {
                // DataItem deleted
            }
        }
    }

    // Method to update the count
    private fun updateCount(int: Int) { ... }
    ...
}

Java

public class MainActivity extends Activity implements DataClient.OnDataChangedListener {
    private static final String COUNT_KEY = "com.example.key.count";
    private int count = 0;

    @Override
    protected void onResume() {
        super.onResume();
        Wearable.getDataClient(this).addListener(this);
    }

    @Override
    protected void onPause() {
        super.onPause();
        Wearable.getDataClient(this).removeListener(this);
    }

    @Override
    public void onDataChanged(DataEventBuffer dataEvents) {
        for (DataEvent event : dataEvents) {
            if (event.getType() == DataEvent.TYPE_CHANGED) {
                // DataItem changed
                DataItem item = event.getDataItem();
                if (item.getUri().getPath().compareTo("/count") == 0) {
                    DataMap dataMap = DataMapItem.fromDataItem(item).getDataMap();
                    updateCount(dataMap.getInt(COUNT_KEY));
                }
            } else if (event.getType() == DataEvent.TYPE_DELETED) {
                // DataItem deleted
            }
        }
    }

    // Method to update the count
    private void updateCount(int c) { ... }
    ...
}

Ta aktywność implementuje interfejs DataClient.OnDataChangedListener. Aktywność dodaje się jako odbiorca zdarzeń elementu danych w metodzie onResume() i usuwa odbiorcę w metodzie onPause(). Aby zobaczyć implementację z użyciem obrazów, modeli i usług, zapoznaj się z aplikacją DataLayer Sample.

Możesz też zaimplementować odbiornik jako usługę. Więcej informacji znajdziesz w artykule Nasłuchiwanie zdarzeń warstwy danych.