Wenn Sie die Data Layer API aufrufen, können Sie den Status des Aufrufs nach Abschluss abrufen. Sie können auch auf Datenereignisse reagieren, die durch Datenänderungen ausgelöst werden, die Ihre App an beliebiger Stelle im Wear OS by Google-Netzwerk vornimmt.
Ein Beispiel für die effektive Verwendung der Data Layer API finden Sie in der Android DataLayer Sample App.
Auf den Status von Datenschichtaufrufen warten
Bei Aufrufen der Data Layer API, z. B. mit der Methode putDataItem der Klasse DataClient, wird manchmal ein Task<ResultType>-Objekt zurückgegeben. Sobald das Task-Objekt erstellt wurde, wird der Vorgang im Hintergrund in die Warteschlange gestellt.
Wenn Sie danach nichts weiter unternehmen, wird der Vorgang irgendwann im Hintergrund abgeschlossen.
In der Regel möchten Sie jedoch nach Abschluss des Vorgangs etwas mit dem Ergebnis tun. Mit dem Task-Objekt können Sie asynchron oder synchron auf den Ergebnisstatus warten.
Asynchrone Anrufe
Wenn Ihr Code im Haupt-UI-Thread ausgeführt wird, sollten Sie keine blockierenden Aufrufe an die Data Layer API vornehmen. Führen Sie die Aufrufe asynchron aus, indem Sie dem Task-Objekt eine Callback-Methode hinzufügen, die ausgelöst wird, wenn der Vorgang abgeschlossen ist:
// 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>) { ... }
Weitere Möglichkeiten, z. B. das Verketten der Ausführung verschiedener Aufgaben, finden Sie in der Task API.
Synchrone Aufrufe
Wenn Ihr Code in einem Hintergrunddienst in einem separaten Handler-Thread ausgeführt wird, z. B. in einem WearableListenerService, können die Aufrufe blockiert werden.
In diesem Fall können Sie Tasks.await() für das Task-Objekt aufrufen. Der Aufruf wird blockiert, bis die Anfrage abgeschlossen ist, und gibt ein Result-Objekt zurück. Dies wird im folgenden Beispiel veranschaulicht.
Hinweis:Rufen Sie diese Funktion nicht im Hauptthread auf.
try {
Tasks.await(dataItemTask).apply {
Log.d(TAG, "Data item set: $uri")
}
}
catch (e: ExecutionException) { ... }
catch (e: InterruptedException) { ... }
Auf Datenschichtereignisse warten
Da die Datenschicht Daten zwischen dem Smartphone und dem Wearable synchronisiert und sendet, müssen Sie in der Regel auf wichtige Ereignisse wie das Erstellen von Datenobjekten und den Empfang von Nachrichten warten.
Sie haben zwei Möglichkeiten, Datenschichtereignisse zu erfassen:
- Erstelle einen Dienst, der
WearableListenerServiceerweitert. - Erstelle eine Aktivität oder Klasse, die die Schnittstelle
DataClient.OnDataChangedListenerimplementiert.
Bei beiden Optionen überschreiben Sie die Datenereignis-Callback-Methoden für die Ereignisse, die Sie verarbeiten möchten.
Hinweis:Berücksichtigen Sie bei der Auswahl einer Listener-Implementierung die Akkunutzung Ihrer App. Ein WearableListenerService ist im Manifest der App registriert und kann die App starten, wenn sie noch nicht ausgeführt wird. Wenn Sie nur auf Ereignisse warten müssen, wenn Ihre App bereits ausgeführt wird, was bei interaktiven Anwendungen häufig der Fall ist, verwenden Sie kein WearableListenerService. Registrieren Sie stattdessen einen Live-Listener. Verwenden Sie beispielsweise die Methode addListener der Klasse DataClient. Dadurch kann die Belastung des Systems und der Akkuverbrauch reduziert werden.
WearableListenerService verwenden
Normalerweise erstellen Sie Instanzen von WearableListenerService sowohl in Ihren Wearable- als auch in Ihren Handheld-Apps. Wenn Sie jedoch keine Datenereignisse in einer der Apps benötigen, müssen Sie den Dienst in dieser App nicht implementieren.
Sie können beispielsweise eine Handheld-App haben, die Datenobjekte festlegt und abruft, und eine Wearable-App, die auf diese Aktualisierungen wartet, um ihre Benutzeroberfläche zu aktualisieren. Die Wearable-App aktualisiert keine der Daten-Items. Die Smartphone-App wartet daher nicht auf Datenereignisse von der Wearable-App.
Einige der Ereignisse, auf die Sie mit WearableListenerService warten können, sind die folgenden:
onDataChanged(): Immer wenn ein Datenobjekt erstellt, gelöscht oder geändert wird, löst das System diesen Callback für alle verbundenen Knoten aus.onMessageReceived(): Eine von einem Knoten gesendete Nachricht löst diesen Callback auf dem Zielknoten aus.onCapabilityChanged(): Wenn eine Funktion, die eine Instanz Ihrer App bewirbt, im Netzwerk verfügbar wird, löst dieses Ereignis diesen Callback aus. Wenn Sie nach einem Knoten in der Nähe suchen, können Sie die MethodeisNearby()der im Callback bereitgestellten Knoten abfragen.
Sie können auch auf Ereignisse von ChannelClient.ChannelCallback warten, z. B. onChannelOpened().
Alle vorherigen Ereignisse werden in einem Hintergrundthread und nicht im Hauptthread ausgeführt.
So erstellen Sie eine WearableListenerService:
- Erstellen Sie eine Klasse, die
WearableListenerServiceerweitert. - Hören Sie auf die Ereignisse, die Sie interessieren, z. B.
onDataChanged(). - Deklarieren Sie in Ihrem Android-Manifest einen Intent-Filter, um das System über Ihre
WearableListenerServicezu informieren. Durch diese Deklaration kann das System Ihren Dienst nach Bedarf binden.
Das folgende Beispiel zeigt, wie Sie eine WearableListenerService implementieren:
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 ) } } }
Im folgenden Abschnitt wird beschrieben, wie Sie einen Intent-Filter mit diesem Listener verwenden.
Filter mit WearableListenerService verwenden
Ein Intent-Filter für das WearableListenerService-Beispiel im vorherigen Abschnitt könnte so aussehen:
<service android:name=".snippets.datalayer.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>
Der Aktionsfilter DATA_CHANGED teilt dem System mit, dass Ihre App an Data-Layer-Ereignissen interessiert ist.
In diesem Beispiel wartet die Smartwatch auf das Datenelement /start-activity und das Smartphone auf die Antwort der Nachricht /data-item-received (DATA_ITEM_RECEIVED_PATH).
Es gelten die Standardregeln für den Android-Filterabgleich. Sie können mehrere Dienste pro Manifest, mehrere Intent-Filter pro Dienst, mehrere Aktionen pro Filter und mehrere Datenabschnitte pro Filter angeben. Filter können auf einen Platzhalterhost oder auf einen bestimmten Host abgestimmt werden. Verwenden Sie host="*", um einen Platzhalterhost abzugleichen. Wenn Sie einen bestimmten Host abgleichen möchten, geben Sie host=<node_id> an.
Sie können auch einen Literalpfad oder ein Pfadpräfix abgleichen. Dazu müssen Sie einen Platzhalter oder einen bestimmten Host angeben. Andernfalls wird der angegebene Pfad vom System ignoriert.
Weitere Informationen zu den von Wear OS unterstützten Filtertypen finden Sie in der API-Referenzdokumentation zu WearableListenerService.
Weitere Informationen zu Datenfiltern und Abgleichsregeln finden Sie in der API-Referenzdokumentation zum Manifestelement <data>.
Beim Abgleichen von Intent-Filtern sind zwei wichtige Regeln zu beachten:
- Wenn kein Schema für den Intent-Filter angegeben ist, ignoriert das System alle anderen URI-Attribute.
- Wenn kein Host für den Filter angegeben ist, ignoriert das System alle Pfadattribute.
Live-Zuhörer verwenden
Wenn Ihre App nur auf Datenschichtereignisse reagieren muss, wenn der Nutzer mit der App interagiert, ist möglicherweise kein Dienst erforderlich, der lange ausgeführt wird, um jede Datenänderung zu verarbeiten. In diesem Fall können Sie auf Ereignisse in einer Aktivität reagieren, indem Sie eine oder mehrere der folgenden Schnittstellen implementieren:
DataClient.OnDataChangedListenerMessageClient.OnMessageReceivedListenerCapabilityClient.OnCapabilityChangedListenerChannelClient.ChannelCallback
So erstellen Sie eine Aktivität, die auf Datenereignisse wartet:
- Implementieren Sie die erforderlichen Schnittstellen.
- Rufen Sie in der Methode
onCreate()oderonResume()die MethodeWearable.getDataClient(this).addListener(),MessageClient.addListener(),CapabilityClient.addListener()oderChannelClient.registerChannelCallback()auf, um die Google Play-Dienste darüber zu informieren, dass Ihre Aktivität an Data Layer-Ereignissen interessiert ist. - Heben Sie in
onStop()oderonPause()die Registrierung aller Listener mitDataClient.removeListener(),MessageClient.removeListener(),CapabilityClient.removeListener()oderChannelClient.unregisterChannelCallback()auf. - Wenn eine Aktivität nur Ereignisse mit einem bestimmten Pfadpräfix empfangen muss, fügen Sie einen Listener mit einem Präfixfilter hinzu, um nur Daten zu empfangen, die für den aktuellen Anwendungsstatus relevant sind.
- Implementieren Sie
onDataChanged(),onMessageReceived(),onCapabilityChanged()oder Methoden ausChannelClient.ChannelCallback, je nachdem, welche Schnittstellen Sie implementiert haben. Diese Methoden werden im Hauptthread aufgerufen. Sie können aber auch einen benutzerdefiniertenLoopermitWearableOptionsangeben.
Hier ein Beispiel für die Implementierung von DataClient.OnDataChangedListener:
class MainActivity : Activity(), DataClient.OnDataChangedListener { public 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 -> 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) } } } }
Achtung:Prüfen Sie vor der Verwendung der Wearable Data Layer API, ob sie auf einem Gerät verfügbar ist. Andernfalls tritt eine Ausnahme auf. Verwenden Sie die Klasse GoogleApiAvailability, wie in Horologist implementiert.
Filter mit Live-Zuhörern verwenden
Wie bereits erwähnt, können Sie Intent-Filter für manifestbasierte WearableListenerService-Objekte angeben. Sie können Intent-Filter auch verwenden, wenn Sie einen Live-Listener über die Wearable API registrieren. Für API-basierte und manifestbasierte Live-Listener gelten dieselben Regeln.
Ein häufiges Muster besteht darin, einen Listener mit einem bestimmten Pfad oder Pfadpräfix in der onResume()-Methode einer Aktivität zu registrieren und den Listener dann in der onPause()-Methode der Aktivität zu entfernen. Wenn Sie Listener auf diese Weise implementieren, kann Ihre App Ereignisse selektiver empfangen, was das Design und die Effizienz verbessert.