Synchronizowanie elementów danych z interfejsem Data Layer API

DataItem definiuje interfejs używany przez system do synchronizowania danych między urządzeniami mobilnymi i urządzeniami do noszenia. DataItem zazwyczaj składa się z tych komponentów:

  • Ładunek: tablica bajtów, którą możesz ustawić za pomocą danych, co umożliwia własną serializację i deserializację 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 Twoje urządzenie z Wear OS jest sparowane z urządzeniem z iOS, interfejs Data Layer API nie będzie działać.

W związku z tym interfejs Data Layer API nie powinien być podstawowym sposobem komunikacji z siecią. Zamiast tego stosuj ten sam wzór co w przypadku aplikacji mobilnej, z kilkoma drobnymi różnicami.

Zwykle nie implementujesz DataItem bezpośrednio. Zamiast tego:

  1. Utwórz obiekt PutDataRequest, podając ścieżkę ciągu tekstowego, aby jednoznacznie zidentyfikować element.
  2. Wywołaj setData(), aby ustawić ładunek.
  3. Jeśli opóźnienie synchronizacji negatywnie wpływa na wygodę użytkowników, wywołaj setUrgent().
  4. Użyj metody putDataItem klasy DataClient, aby poprosić system o utworzenie elementu danych.

Gdy żądasz elementów danych, system zwraca obiekty, które prawidłowo implementują interfejs DataItem. Jednak zamiast korzystać z nieprzetworzonych bajtów za pomocą funkcji setData(), zalecamy użycie mapy danych, która udostępnia element danych za pomocą interfejsu podobnego do Bundle.

Więcej informacji znajdziesz w aplikacji DataLayer Sample.

Synchronizacja danych z mapą danych

W miarę możliwości używaj klasy DataMap. To podejście umożliwia pracę z elementami danych w postaci Bundle Androida, dzięki czemu system wykonuje serializację i deserializację obiektów za Ciebie, a możesz manipulować danymi za pomocą par klucz-wartość.

Aby użyć mapy danych:

  1. Utwórz obiekt PutDataMapRequest, aby ustawić ścieżkę elementu danych.

    Uwaga: ciąg znaków 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 pasujący do struktury danych.

  2. Wywołaj PutDataMapRequest.getDataMap(), aby uzyskać mapę danych, dla której możesz ustawiać wartości.
  3. Ustaw wartości na potrzeby mapowania danych za pomocą metod put...(), takich jak putString().
  4. Jeśli opóźnienie synchronizacji negatywnie wpływa na wygodę użytkowników, wywołaj setUrgent().
  5. Wywołaj PutDataMapRequest.asPutDataRequest(), aby uzyskać obiekt PutDataRequest.
  6. Użyj metody putDataItem klasy DataClient, aby poprosić system o utworzenie elementu danych.

    Uwaga: jeśli słuchawka i urządzenia do noszenia nie są rozłączone, dane są buforowane i zsynchronizowane po ponownym nawiązaniu połączenia.

Metoda increaseCounter() w poniższym przykładzie 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 obiektu Tasks znajdziesz w dokumentacji referencyjnej.

Ustawianie priorytetu elementu DataItem

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

Jeśli nie zadzwonisz pod numer setUrgent(), system może opóźnić synchronizację mniej pilnych elementów danych nawet po 30 minutach. Zazwyczaj opóźnienie wynosi tylko kilka minut. Domyślna pilna czynność nie jest pilna, więc jeśli chcesz zachować natychmiastowe działanie synchronizacji z poprzednich wersji interfejsu Wear OS API, użyj setUrgent().

Wykrywa zdarzenia związane z elementem danych

Jeśli jedna strona połączenia warstwy danych zmienia element danych, powiadom użytkownika o wszelkich zmianach po drugiej stronie połączenia. Aby to zrobić, zaimplementuj odbiornik zdarzenia elementu danych.

Fragment kodu w poniższym przykładzie powiadamia aplikację o zmianie wartości licznika zdefiniowanej 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) { ... }
    ...
}

To działanie implementuje interfejs DataClient.OnDataChangedListener. Aktywność dodaje się jako odbiornik zdarzeń elementu danych w metodzie onResume() i usuwa go w metodzie onPause(). Aby zobaczyć implementację z użyciem obrazów oraz modele i usługi, otwórz aplikację DataLayer Sample (Przykład warstwy danych).

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