Datenschichtereignisse für Wear verarbeiten

Wenn Sie die Data Layer API aufrufen, können Sie den Parameter Status des Aufrufs nach Abschluss des Aufrufs. Sie können auch auf Datenereignisse warten, die sich aus Datenänderungen ergeben, die Ihre App irgendwo im Wear OS by Google-Netzwerk.

Ein Beispiel für die effektive Arbeit mit dem Data Layer API finden Sie in der <ph type="x-smartling-placeholder"></ph> Android DataLayer Sample App.

Auf Status von Datenschichtaufrufen warten

Aufrufe an die Data Layer API, z. B. Aufrufe über die putDataItem der Methode DataClient-Klasse – manchmal wird ein Task<ResultType>-Objekt. Sobald das Task-Objekt erstellt wurde, ist der Vorgang im Hintergrund in die Warteschlange gestellt. Wenn Sie danach nichts weiter tun, wird der Vorgang wird schließlich im Hintergrund abgeschlossen.

Üblicherweise sollten Sie jedoch das Ergebnis nach Abschluss des Vorgangs, sodass das Task-Objekt warten Sie auf den Ergebnisstatus, entweder asynchron oder synchron.

Asynchrone Aufrufe

Wenn Ihr Code im Haupt-UI-Thread ausgeführt wird, führen Sie keine blockierenden Aufrufe an den Data Layer API. Aufrufe durch Hinzufügen einer Callback-Methode asynchron ausführen an das Task-Objekt, das ausgelöst wird, wenn der Vorgang abgeschlossen ist:

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));

Siehe Task-API für andere Möglichkeiten, einschließlich Verkettung der Ausführung von verschiedene Aufgaben zu erledigen.

Synchrone Aufrufe

Wenn Ihr Code in einem separaten Handler-Thread in einem Hintergrunddienst ausgeführt wird, z. B. in einem WearableListenerService, können Sie die Anrufe blockieren. In diesem Fall können Sie Tasks.await() in der Task , das bis zum Abschluss der Anfrage blockiert und eine Result-Objekt. Dies wird im folgenden Beispiel gezeigt.

Hinweis:Rufen Sie diese Nachricht nicht auf, während Sie sich im Hauptthread befinden.

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) {
  ...
}

Auf Datenschichtereignisse warten

Da die Datenschicht Daten synchronisiert und über das Handheld und Wearables müssen Sie in der Regel auf wichtige Ereignisse wie Datenelemente, die erstellt werden und empfangene Nachrichten.

Es gibt zwei Möglichkeiten, auf Datenschichtereignisse zu warten:

Mit beiden Optionen überschreiben Sie die Datenereignis-Callback-Methoden für die die Sie verarbeiten möchten.

Hinweis:Berücksichtigen Sie bei der Auswahl eine Listener-Implementierung. Ein WearableListenerService ist im Manifest der App registriert und kann die App starten, falls dies noch nicht geschehen ist ausgeführt wird. Wenn Sie nur auf Ereignisse warten müssen, wenn Ihre App bereits ausgeführt wird, Dies ist häufig bei interaktiven Anwendungen der Fall. WearableListenerService Registrieren Sie stattdessen einen Live-Hörer. Verwenden Sie beispielsweise die Methode addListener des Objekts DataClient . Dies kann das System entlasten und den Akkuverbrauch verringern.

WearableListenerService verwenden

Normalerweise erstellen Sie Instanzen von . WearableListenerService in Ihrem Wearable und Handheld-Apps. Wenn Sie jedoch kein Interesse an Datenereignissen müssen Sie den Dienst nicht in dieser App implementieren.

Beispielsweise können Sie eine Handheld-App haben, die Datenobjekte festlegt und abruft. und eine Wearable-App, die auf diese Updates achtet, um ihre Benutzeroberfläche zu aktualisieren. Die Die Wearable-App aktualisiert keine Datenelemente, sodass die Handheld-App auf Datenereignisse von der Wearable-App warten.

Einige der Ereignisse, die Sie mit WearableListenerService sind die folgenden:

  • <ph type="x-smartling-placeholder"></ph> onDataChanged(): Immer wenn ein Datenelementobjekt erstellt, gelöscht oder geändert wird, löst das System diesen Callback auf allen verbundenen Knoten.
  • <ph type="x-smartling-placeholder"></ph> onMessageReceived(): Eine von einem Knoten gesendete Nachricht wird ausgelöst diesen Callback auf dem Zielknoten.
  • <ph type="x-smartling-placeholder"></ph> onCapabilityChanged(): Wenn eine Funktion verfügbar wird, die von einer Instanz Ihrer App beworben wird im Netzwerk, löst dieses Ereignis diesen Callback aus. Wenn Sie eine Knoten in der Nähe befindet, können Sie <ph type="x-smartling-placeholder"></ph> isNearby() der im Callback angegebenen Knoten.

Sie können auch auf Ereignisse von ChannelClient.ChannelCallback, z. B. onChannelOpened().

Alle vorherigen Ereignisse werden in einem Hintergrundthread ausgeführt. nicht im Hauptthread.

So erstellen Sie eine WearableListenerService:

  1. Erstellen Sie eine Klasse, die WearableListenerService erweitert.
  2. Beobachten Sie Ereignisse, die Sie interessieren, z. B. onDataChanged().
  3. Deklarieren Sie in Ihrem Android-Manifest einen Intent-Filter, um das System über Ihre WearableListenerService Mit dieser Deklaration kann das System Ihre -Dienst nach Bedarf.

Das folgende Beispiel zeigt, wie eine einfache WearableListenerService implementiert wird:

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

Im folgenden Abschnitt wird erläutert, wie Sie mit diesem Listener einen Intent-Filter verwenden.

Filter mit WearableListenerService verwenden

Intent-Filter für das im vorherigen Abschnitt gezeigte WearableListenerService-Beispiel könnte wie folgt aussehen:

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

In diesem Filter wird durch die Aktion DATA_CHANGED Folgendes ersetzt: empfohlene Maßnahme BIND_LISTENER, damit nur spezifische oder Ihre App starten. Durch diese Änderung wird die Systemeffizienz verbessert und senkt den Akkuverbrauch und die In diesem Beispiel wartet die Smartwatch auf den /start-activity-Datenelement und die Das Smartphone wartet auf die Nachrichtenantwort /data-item-received.

Es gelten die Standardregeln für den Android-Filterabgleich. Sie können mehrere Dienste angeben pro Manifest, mehrere Intent-Filter pro Dienst, mehrere Aktionen pro Filter, und mehrere Daten-Stanzas pro Filter. Filter können mit einem Platzhalter-Host oder auf einer bestimmten. Für den Abgleich mit einem Platzhalterhost verwenden Sie host="*". Übereinstimmung auf einem bestimmten Host, geben Sie host=<node_id> an.

Sie können auch einen literalen Pfad oder ein Pfadpräfix abgleichen. Gehen Sie dazu wie folgt vor: müssen Sie einen Platzhalter oder einen bestimmten Host angeben. Andernfalls ignoriert das System den von Ihnen angegebenen Pfad.

Weitere Informationen zu den von Wear OS unterstützten Filtertypen findest du in den API-Referenzdokumentation für WearableListenerService

Weitere Informationen zu Datenfiltern und Abgleichregeln finden Sie in der API-Referenz Dokumentation für <data> Manifest-Element enthält.

Beachten Sie beim Abgleichen von Intent-Filtern zwei wichtige Regeln:

  • Wenn für den Intent-Filter kein Schema angegeben ist, ignoriert das System alle anderen URI-Attribute.
  • Falls für den Filter kein Host angegeben ist, ignoriert das System alle Pfadattribute.

Live-Zuhörer verwenden

Wenn für Ihre App Datenebenen-Ereignisse nur relevant sind, wenn der Nutzer mit der Anwendung ist, ist kein lang andauernder Dienst erforderlich, um jede Datenänderung zu verarbeiten. In können Sie in einer Aktivität auf Ereignisse warten, indem Sie ein oder der folgenden Oberflächen verwenden:

So erstellen Sie eine Aktivität, die auf Datenereignisse wartet:

  1. Implementieren Sie die gewünschten Schnittstellen.
  2. Rufen Sie in der Methode onCreate() oder onResume() Wearable.getDataClient(this).addListener(), MessageClient.addListener(), CapabilityClient.addListener() oder ChannelClient.registerChannelCallback(), um Google Play zu benachrichtigen Dienste, die von Ihrer Aktivität auf Datenschichtereignisse überwacht werden sollen.
  3. Im Jahr onStop() oder onPause(), Registrierung aller Listener mit DataClient.removeListener() aufheben, MessageClient.removeListener(), CapabilityClient.removeListener() oder ChannelClient.unregisterChannelCallback()
  4. Wenn eine Aktivität nur an Ereignissen mit einem bestimmten Pfadpräfix interessiert ist, können Sie einen Listener mit einem geeigneten Präfixfilter hinzufügen, um nur Daten zu empfangen, relevant für den aktuellen Anwendungsstatus sind.
  5. onDataChanged(), onMessageReceived() implementieren onCapabilityChanged() oder Methoden aus ChannelClient.ChannelCallback abhängig von den von Ihnen implementierten Schnittstellen. Diese Methoden werden am dem Hauptthread oder Sie können mit WearableOptions ein benutzerdefiniertes Looper-Objekt angeben.

Hier ist ein Beispiel für die Implementierung von 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());
            }
        }
    }
}

Filter mit Live-Hörern verwenden

Wie bereits erwähnt, können Sie ebenso wie Sie Intent-Filter für Manifestbasierte WearableListenerService -Objekten enthält, können Sie Intent-Filter verwenden, wenn Sie einen Live-Listener über die Am Körper tragbar API zu erstellen. Für API-basierte Live-Listener und Manifest-basierten Listenern.

Ein gängiges Muster besteht darin, einen Listener mit einem bestimmten Pfad- oder Pfadpräfix zu registrieren. im onResume() einer Aktivität und dann den Listener aus der Methode onPause()-Methode. Wenn Sie Listener auf diese Weise implementieren, kann Ihre App selektiver Ereignisse empfangen und so sein Design und seine Effizienz verbessern können.