Obsługa zdarzeń warstwy danych na Wear

Po wywołaniu interfejsu API warstwy danych możesz uzyskać statusu połączenia po jego zakończeniu. Możesz też nasłuchiwać zdarzeń dotyczących danych zmian danych wprowadzanych przez aplikację w dowolnym miejscu Sieć Wear OS by Google.

Przykłady efektywnej pracy z interfejsem API warstwy danych znajdziesz Android DataLayer Sample.

Oczekiwanie na stan wywołań warstwy danych

Wywołania interfejsu API warstwy danych, takie jak wywołanie interfejsu putDataItem funkcji DataClient klasa – czasami zwraca błąd Task<ResultType> obiekt. Gdy tylko obiekt Task zostanie utworzony operacja dodano do kolejki w tle. Jeśli nie zrobisz nic więcej, operacja a konkretnie zakończy się dyskretnie.

Zwykle jednak wolisz używać wynik po jej zakończeniu, więc obiekt Task pozwala można zaczekać na stan wyniku, asynchronicznie lub synchronicznie.

Wywołania asynchroniczne

Jeśli Twój kod działa w głównym wątku UI, nie wysyłaj blokujących wywołań do Interfejs API warstwy danych. Asynchroniczne uruchamianie wywołań przez dodanie metody wywołania zwrotnego do obiektu Task, który uruchamia się po zakończeniu operacji:

Kotlin

// Using Kotlin function references
task.addOnSuccessListener(::handleDataItem)
task.addOnFailureListener(::handleDataItemError)
task.addOnCompleteListener(::handleTaskComplete)
...
fun handleDataItem(dataItem: DataItem) { ... }
fun handleDataItemError(exception: Exception) { ... }
fun handleTaskComplete(task: Task<DataItem>) { ... }

Java

// Using Java 8 Lambdas.
task.addOnSuccessListener(dataItem -> handleDataItem(dataItem));
task.addOnFailureListener(exception -> handleDataItemError(exception));
task.addOnCompleteListener(task -> handleTaskComplete(task));

Zobacz interfejsu Task API do innych możliwości, w tym do łańcucha wykonywania różne zadania.

Wywołania synchroniczne

Jeśli Twój kod działa w osobnym wątku modułu obsługi w usłudze w tle, na przykład w WearableListenerService, możesz blokować połączenia. W takim przypadku możesz zadzwonić pod numer Tasks.await() w: Task , który blokuje do czasu zakończenia żądania i zwraca Result obiekt. Widać to w przykładzie poniżej.

Uwaga: nie używaj tej opcji w wątku głównym.

Kotlin

try {
    Tasks.await(dataItemTask).apply {
        Log.d(TAG, "Data item set: $uri")
    }
}
catch (e: ExecutionException) { ... }
catch (e: InterruptedException) { ... }

Java

try {
    DataItem item = Tasks.await(dataItemTask);
    Log.d(TAG, "Data item set: " + item.getUri());
} catch (ExecutionException | InterruptedException e) {
  ...
}

Nasłuchuj zdarzeń warstwy danych

Warstwa danych synchronizuje i wysyła dane między urządzeniami urządzeń do noszenia, zwykle musisz nasłuchiwać ważnych zdarzeń, takich jak tworzone elementy danych i odbierane wiadomości.

Istnieją 2 sposoby nasłuchiwania zdarzeń warstwy danych:

Korzystając z obu tych opcji, zastępujesz metody wywołania zwrotnego zdarzenia danych dla funkcji zdarzenia, które chcesz obsługiwać.

Uwaga: przy wyborze bierz pod uwagę zużycie baterii przez aplikację w implementacji detektora. WearableListenerService jest zarejestrowany w pliku manifestu aplikacji i może ją uruchomić, jeśli jeszcze nie jest włączona; w domu. Jeśli chcesz nasłuchiwać tylko zdarzeń, gdy aplikacja jest już uruchomiona, co często ma miejsce w przypadku aplikacji interaktywnych, nie używaj WearableListenerService Zamiast tego zarejestruj detektora na żywo. Na przykład użyj metody addListener funkcji DataClient zajęcia. Może to zmniejszyć obciążenie systemu i wykorzystanie baterii.

Używanie usługi WearableListenerService

Zazwyczaj tworzysz instancje WearableListenerService zarówno na urządzeniu do noszenia, na urządzenia przenośne. Jeśli jednak nie interesują Cię zdarzenia związane z danymi w jednej z aplikacji, nie musisz implementować w niej tej usługi.

Możesz na przykład mieć aplikację podręczną, która ustawia i pobiera obiekty danych. i aplikacji do noszenia, która nasłuchuje aktualizacji, aby aktualizować interfejs. aplikacja do noszenia nigdy nie aktualizuje żadnych danych, więc nie będzie nasłuchiwać zdarzeń danych z aplikacji do noszenia.

Niektóre zdarzenia, których możesz nasłuchiwać za pomocą WearableListenerService to:

  • onDataChanged(): za każdym razem, gdy obiekt elementu danych zostaje utworzony, usunięty lub zmieniony, to wywołanie zwrotne we wszystkich połączonych węzłach.
  • onMessageReceived(): komunikat wysłany z aktywatorów węzła wywołanie zwrotne w węźle docelowym.
  • onCapabilityChanged(): gdy dostępna jest funkcja reklamowana w konkretnej aplikacji. w sieci, zdarzenie aktywuje to wywołanie zwrotne. Jeśli szukasz w pobliżu węzła, możesz wysłać zapytanie Metoda isNearby() węzłów podanych w wywołaniu zwrotnym.

Możesz też nasłuchiwać zdarzeń z ChannelClient.ChannelCallback, na przykład onChannelOpened().

Wszystkie poprzednie zdarzenia są wykonywane w wątku w tle, a nie w głównym wątku.

Aby utworzyć WearableListenerService, wykonaj te czynności:

  1. Utwórz zajęcia z rozszerzeniem WearableListenerService.
  2. Wykrywaj zdarzenia, które Cię interesują, np. onDataChanged().
  3. Zadeklaruj filtr intencji w pliku manifestu Androida, aby powiadamiać system o WearableListenerService Ta deklaracja umożliwia systemowi powiązanie w razie potrzeby.

Poniższy przykład pokazuje, jak wdrożyć prostą WearableListenerService:

Kotlin

private const val TAG = "DataLayerSample"
private const val START_ACTIVITY_PATH = "/start-activity"
private const val DATA_ITEM_RECEIVED_PATH = "/data-item-received"

class DataLayerListenerService : WearableListenerService() {

    override fun onDataChanged(dataEvents: DataEventBuffer) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "onDataChanged: $dataEvents")
        }

        // Loop through the events and send a message
        // to the node that created the data item.
        dataEvents.map { it.dataItem.uri }
                .forEach { uri ->
                    // Get the node ID from the host value of the URI.
                    val nodeId: String = uri.host
                    // Set the data of the message to be the bytes of the URI.
                    val payload: ByteArray = uri.toString().toByteArray()

                    // Send the RPC.
                    Wearable.getMessageClient(this)
                            .sendMessage(nodeId, DATA_ITEM_RECEIVED_PATH, payload)
                }
    }
}

Java

public class DataLayerListenerService extends WearableListenerService {
    private static final String TAG = "DataLayerSample";
    private static final String START_ACTIVITY_PATH = "/start-activity";
    private static final String DATA_ITEM_RECEIVED_PATH = "/data-item-received";

    @Override
    public void onDataChanged(DataEventBuffer dataEvents) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "onDataChanged: " + dataEvents);
        }

        // Loop through the events and send a message
        // to the node that created the data item.
        for (DataEvent event : dataEvents) {
            Uri uri = event.getDataItem().getUri();

            // Get the node ID from the host value of the URI.
            String nodeId = uri.getHost();
            // Set the data of the message to be the bytes of the URI.
            byte[] payload = uri.toString().getBytes();

            // Send the RPC.
            Wearable.getMessageClient(this).sendMessage(
                  nodeId,  DATA_ITEM_RECEIVED_PATH, payload);
        }
    }
}

Z sekcji poniżej dowiesz się, jak używać w przypadku tego detektora filtra intencji.

Używanie filtrów w usłudze WearableListenerService

Filtr intencji dla przykładu elementu WearableListenerService widocznego w poprzedniej sekcji może wyglądać tak:

<service android:name=".DataLayerListenerService" android:exported="true" tools:ignore="ExportedService" >
  <intent-filter>
      <action android:name="com.google.android.gms.wearable.DATA_CHANGED" />
      <data android:scheme="wear" android:host="*"
               android:path="/start-activity" />
  </intent-filter>
</service>

W tym filtrze działanie DATA_CHANGED zastępuje zalecane wcześniej działanie BIND_LISTENER, tak aby tylko określone zdarzeń powodują wybudzenie lub uruchomienie aplikacji. Ta zmiana poprawia wydajność systemu oraz zmniejsza zużycie baterii i inne koszty związane z . W tym przykładzie zegarek nasłuchuje /start-activity elementu danych oraz Telefon nasłuchuje odpowiedzi na wiadomość /data-item-received.

Obowiązują standardowe reguły dopasowania filtra Androida. Możesz określić wiele usług na plik manifestu, wiele filtrów intencji na usługę, wiele działań na filtr, oraz wiele streszczeń danych na filtr. Filtry mogą działać na hoście z symbolem wieloznacznym lub być włączone konkretnego filmu. Aby dopasować do hosta z symbolem wieloznacznym, użyj host="*". Aby dopasować na konkretnym hoście, wpisz host=<node_id>.

Możesz też dopasować ścieżkę literału lub prefiks ścieżki. Aby to zrobić: musisz podać symbol wieloznaczny lub konkretny host. W przeciwnym razie system zignoruje podaną ścieżkę.

Więcej informacji o typach filtrów obsługiwanych przez Wear OS znajdziesz w Dokumentacja interfejsu API dla usługi WearableListenerService

Więcej informacji o filtrach danych i regułach dopasowania znajdziesz w dokumentacji interfejsu API dokumentacja: <data> manifestu.

Dopasowując filtry intencji, pamiętaj o 2 ważnych regułach:

  • Jeśli nie określisz schematu dla filtra intencji, system go zignoruje. wszystkich pozostałych atrybutów URI.
  • Jeśli nie określono hosta dla filtra, system ignoruje wszystkich atrybutów ścieżki.

Korzystanie z detektora na żywo

Jeśli Twojej aplikacji interesują się tylko zdarzenia warstwy danych, gdy użytkownik wchodzi w interakcję z: aplikacji, może nie potrzebować długoterminowej usługi do obsługi każdej zmiany danych. W możesz nasłuchiwać zdarzeń w działaniu, implementując jeden lub inne interfejsy:

Aby utworzyć działanie, które nasłuchuje zdarzeń związanych z danymi:

  1. Zaimplementuj odpowiednie interfejsy.
  2. W metodzie onCreate() lub onResume() wywołaj funkcję Wearable.getDataClient(this).addListener(), MessageClient.addListener(), CapabilityClient.addListener() lub ChannelClient.registerChannelCallback(), aby powiadomić Google Play usług, w których Twoja aktywność chce nasłuchiwać zdarzeń warstwy danych.
  3. W: onStop() lub onPause(), wyrejestruj wszystkich detektorów z DataClient.removeListener(), MessageClient.removeListener(), CapabilityClient.removeListener() lub ChannelClient.unregisterChannelCallback().
  4. Jeśli aktywność obejmuje tylko zdarzenia z określonym prefiksem ścieżki, może dodać detektor z odpowiednim filtrem prefiksu, aby odbierać tylko dane, które są w odniesieniu do bieżącego stanu aplikacji.
  5. Wdróż onDataChanged(), onMessageReceived(), onCapabilityChanged() lub metod z ChannelClient.ChannelCallback, w zależności od zaimplementowanych interfejsów. Te metody są wywoływane w wątku głównym lub określić niestandardowy obiekt Looper za pomocą WearableOptions.

Oto przykład implementującej właściwość DataClient.OnDataChangedListener:

Kotlin

class MainActivity : Activity(), DataClient.OnDataChangedListener {

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

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

    override fun onDataChanged(dataEvents: DataEventBuffer) {
        dataEvents.forEach { event ->
            if (event.type == DataEvent.TYPE_DELETED) {
                Log.d(TAG, "DataItem deleted: " + event.dataItem.uri)
            } else if (event.type == DataEvent.TYPE_CHANGED) {
                Log.d(TAG, "DataItem changed: " + event.dataItem.uri)
            }
        }
    }
}

Java

public class MainActivity extends Activity implements DataClient.OnDataChangedListener {

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

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

    @Override
    public void onDataChanged(DataEventBuffer dataEvents) {
        for (DataEvent event : dataEvents) {
            if (event.getType() == DataEvent.TYPE_DELETED) {
                Log.d(TAG, "DataItem deleted: " + event.getDataItem().getUri());
            } else if (event.getType() == DataEvent.TYPE_CHANGED) {
                Log.d(TAG, "DataItem changed: " + event.getDataItem().getUri());
            }
        }
    }
}

Korzystanie z filtrów w przypadku słuchaczy na żywo

Jak już wspomnieliśmy, tak samo jak możesz określić filtry intencji oparte na pliku manifestu WearableListenerService obiektów, możesz użyć filtrów intencji podczas rejestrowania detektora Do noszenia API. Te same reguły dotyczą zarówno detektorów transmisji na żywo opartych na interfejsie API, detektorów opartych na plikach manifestu.

Typowym wzorcem jest rejestrowanie detektora z określoną ścieżką lub prefiksem ścieżki w onResume() aktywności a następnie usuń detektora Metoda onPause(). Taki sposób wdrożenia detektorów pozwala aplikacji bardziej wybiórczo do odbierania zdarzeń, poprawiając jego wygląd i wydajność.