Sie senden Nachrichten über die
MessageClient
API und hängen die folgenden Elemente an die Nachricht an:
- Eine optionale beliebige Nutzlast
- Ein Pfad, der die Aktion der Nachricht eindeutig identifiziert
Im Gegensatz zu Datenpunkten erfolgt keine Synchronisierung zwischen den Smartphone- und Wearable-Apps. Nachrichten sind ein unidirektionaler Kommunikationsmechanismus, der für Remoteprozeduraufrufe (RPCs) nützlich ist, z. B. zum Senden einer Nachricht an das Wearable, um eine Aktivität zu starten.
Es können mehrere Wearables mit dem Mobilgerät eines Nutzers verbunden werden. Jedes verbundene Gerät im Netzwerk wird als Knoten betrachtet.
Bei mehreren verbundenen Geräten müssen Sie berücksichtigen, welche Knoten die Nachrichten empfangen. Wenn beispielsweise eine Sprachtranskriptions-App Sprachdaten auf dem Wearable empfängt, senden Sie die Nachricht an einen Knoten mit der erforderlichen Rechenleistung und Akkukapazität, z. B. an ein Smartphone.
Hinweis:Wenn Sie die Details Ihrer Nachricht angeben, sollten Sie die Möglichkeit mehrerer verbundener Knoten berücksichtigen. Achten Sie darauf, dass die Nachricht an die vorgesehenen Geräte oder Knoten gesendet wird.
Beispiele für die Verwendung finden Sie in der folgenden Beispiel-App: DataLayer
Nachricht senden
Eine Wearable-App kann Nutzern Funktionen wie die Spracheingabe bieten. Nutzer können in das Mikrofon ihres Wearable-Geräts sprechen und eine Transkription in einer Notiz speichern lassen. Da ein Wearable in der Regel nicht die Rechenleistung und Akkukapazität hat, die für die Sprach-zu-Text-Transkription erforderlich sind, muss die App diese Aufgabe an ein leistungsfähigeres verbundenes Gerät auslagern.
In den folgenden Abschnitten erfahren Sie, wie Sie Geräteknoten bewerben, die Aktivitätsanfragen verarbeiten können, wie Sie die Knoten ermitteln, die eine angeforderte Aufgabe ausführen können, und wie Sie Nachrichten an diese Knoten senden.
Funktionen bewerben
Wenn Sie eine Aktivität auf einem tragbaren Gerät über ein Wearable starten möchten, verwenden Sie die Klasse
MessageClient
, um die Anfrage zu senden. Da mehrere Wearables mit dem Mobilgerät verbunden sein können, muss die Wearable-App feststellen, ob ein verbundener Knoten die Aktivität starten kann. Geben Sie in Ihrer Handheld-App an, dass der Knoten, auf dem sie ausgeführt wird, bestimmte Funktionen bietet.
So werben Sie für die Funktionen Ihrer Smartphone-App:
- Erstellen Sie im Verzeichnis
res/values/
Ihres Projekts eine XML-Konfigurationsdatei mit dem Namenwear.xml
. - Fügen Sie
wear.xml
eine Ressource mit dem Namenandroid_wear_capabilities
hinzu. - Definieren Sie die Funktionen, die das Gerät bietet.
Hinweis:Funktionen sind benutzerdefinierte Strings, die Sie definieren und die in Ihrer App eindeutig sein müssen.
Das folgende Beispiel zeigt, wie Sie wear.xml
die Funktion voice_transcription
hinzufügen:
<resources xmlns:tools="http://schemas.android.com/tools" tools:keep="@array/android_wear_capa<bilities"> string-array name="android_<wear_capabilities"&<gt; < item>voice_<transcription/item> /string-array> /resources>
Knoten mit den erforderlichen Funktionen abrufen
Zuerst können Sie die entsprechenden Knoten erkennen, indem Sie die Methode getCapability
der Klasse
CapabilityClient
aufrufen. Damit du diese Methode verwenden kannst, müssen deine Wear OS-App und deine Smartphone-App dieselbe Anwendungs-ID haben. Im folgenden Beispiel wird gezeigt, wie Sie die Ergebnisse erreichbarer Knoten mit der voice_transcription
-Funktion manuell abrufen:
Kotlin
private const val VOICE_TRANSCRIPTION_CAPABILITY_NAME = "voice_transcription" ... private fun setupVoiceTranscription() { val capabilityInfo: CapabilityInfo = Tasks.await( Wearable.getCapabilityClient(context) .getCapability( VOICE_TRANSCRIPTION_CAPABILITY_NAME, CapabilityClient.FILTER_REACHABLE ) ) // capabilityInfo has the reachable nodes with the transcription capability updateTranscriptionCapability(capabilityInfo) }
Java
private static final String VOICE_TRANSCRIPTION_CAPABILITY_NAME = "voice_transcription"; ... private void setupVoiceTranscription() { CapabilityInfo capabilityInfo = Tasks.await( Wearable.getCapabilityClient(context).getCapability( VOICE_TRANSCRIPTION_CAPABILITY_NAME, CapabilityClient.FILTER_REACHABLE)); // capabilityInfo has the reachable nodes with the transcription capability updateTranscriptionCapability(capabilityInfo); }
Achtung:Bevor Sie die Wearable Data Layer API verwenden, prüfen Sie, ob sie auf einem Gerät verfügbar ist. Andernfalls tritt eine Ausnahme auf. Verwenden Sie die Klasse GoogleApiAvailability
, wie sie in Horologist implementiert ist.
Um geeignete Knoten zu erkennen, wenn sie sich mit dem Wearable verbinden, registrieren Sie eine Listener-Instanz, insbesondere eine OnCapabilityChangedListener
eines CapabilityClient
-Objekts. Im folgenden Beispiel wird gezeigt, wie Sie den Listener registrieren und ein Ergebnis mit erreichbaren Knoten abrufen, die die Funktion voice_transcription
haben:
Kotlin
private fun setupVoiceTranscription() { updateTranscriptionCapability(capabilityInfo).also { capabilityListener -> Wearable.getCapabilityClient(context).addListener( capabilityListener, VOICE_TRANSCRIPTION_CAPABILITY_NAME ) } }
Java
private void setupVoiceTranscription() { ... // This example uses a Java 8 Lambda. You can use named or anonymous classes. CapabilityClient.OnCapabilityChangedListener capabilityListener = capabilityInfo -> { updateTranscriptionCapability(capabilityInfo); }; Wearable.getCapabilityClient(context).addListener( capabilityListener, VOICE_TRANSCRIPTION_CAPABILITY_NAME); }
Nachdem die entsprechenden Knoten erkannt wurden, wird festgelegt, wohin die Nachricht gesendet werden soll. Wähle einen Knoten aus, der sich in unmittelbarer Nähe deines Wearable befindet, um das Routing von Nachrichten über mehrere Knoten zu minimieren. Ein Knoten in der Nähe ist ein Knoten, der direkt mit dem Gerät verbunden ist. Rufen Sie die Methode
Node.isNearby()
auf, um festzustellen, ob sich ein Knoten in der Nähe befindet, z. B. über Bluetooth verbunden ist. Wenn sich mehrere Knoten in der Nähe befinden, wählen Sie einen beliebig aus. Wenn sich kein geeigneter Knoten in der Nähe befindet, wählen Sie einen beliebigen geeigneten Knoten aus.
Das folgende Beispiel zeigt, wie Sie den besten Knoten ermitteln können:
Kotlin
private var transcriptionNodeId: String? = null private fun updateTranscriptionCapability(capabilityInfo: CapabilityInfo) { transcriptionNodeId = pickBestNodeId(capabilityInfo.nodes) } private fun pickBestNodeId(nodes: Set<Node>): String? { // Find a nearby node or pick one arbitrarily. return nodes.firstOrNull { it.isNearby }?.id ?: nodes.firstOrNull()?.id }
Java
private String transcriptionNodeId = null; private void updateTranscriptionCapability(CapabilityInfo capabilityInfo) { Set<Node> connectedNodes = capabilityInfo.getNodes(); transcriptionNodeId = pickBestNodeId(connectedNodes); } private String pickBestNodeId(Set<Node> nodes) { String bestNodeId = null; // Find a nearby node or pick one arbitrarily. for (Node node : nodes) { if (node.isNearby()) { return node.getId(); } bestNodeId = node.getId(); } return bestNodeId; }
Nachricht übermitteln
Nachdem Sie einen Knoten für die Verwendung identifiziert haben, senden Sie die Nachricht mit der Klasse
MessageClient
.
Das folgende Beispiel zeigt, wie eine Nachricht von einem Wearable an den Knoten gesendet wird, der die Transkription ausführen kann. Dieser Aufruf ist synchron und blockiert die Verarbeitung, bis das System die Nachricht für die Zustellung in die Warteschlange stellt.
Hinweis:Ein erfolgreicher Ergebniscode garantiert nicht die Zustellung der Nachricht. Wenn Ihre App Datenzuverlässigkeit erfordert, sollten Sie
DataItem
-Objekte oder die ChannelClient
-Klasse verwenden, um Daten zwischen Geräten zu senden.
Kotlin
const val VOICE_TRANSCRIPTION_MESSAGE_PATH = "/voice_transcription" ... private fun requestTranscription(voiceData: ByteArray) { transcriptionNodeId?.also >{ nodeId - val send<T>ask: Task* = Wearable.getMessageClient(context).sendMessage( nodeId, VOICE_TRANSCRIPTION_MESSAGE_PATH, voiceData ).apply { addOnSuccessListener { ... } addOnFailureListener { ... } } } }
Java
public static final String VOICE_TRANSCRIPTION_MESSAGE_PATH = "/voice_transcription"; private void requestTranscription(byte[] voiceData) { if (transcriptionNodeId != null) { < T>askInteger sendTask = Wearable.getMessageClient(context).sendMessage( transcriptionNodeId, VOICE_TRANSCRIPTION_MESSAGE_PATH, voiceData); // You can add success and/or failure listeners, // Or you can call Tasks.await() and catch ExecutionException sendTask.addOnSuccessListener(...); sendTask.addOnFailureListener(...); } else { // Unable to retrieve node with transcription capability } }
Hinweis:Weitere Informationen zu asynchronen und synchronen Aufrufen von Google Play-Diensten und dazu, wann welche verwendet werden sollten, finden Sie in der Tasks API.
Sie können auch Nachrichten an alle verbundenen Knoten senden. Implementieren Sie den folgenden Code, um alle verbundenen Knoten abzurufen, an die Sie Nachrichten senden können:
Kotlin
private fun getNodes(): Collection<String> { return Tasks.await(Wearable.getNodeClient(context).connectedNodes).map { it.id } }
Java
private Collection<String> getNodes() { HashSet <String>results = new HashSet<String>(); List<Node> nodes = Tasks.await(Wearable.getNodeClient(context).getConnectedNodes()); for (Node node : nodes.getNodes()) { results.add(node.getId()); } return results; }
Nachrichten empfangen
Wenn Sie über empfangene Nachrichten benachrichtigt werden möchten, implementieren Sie die
MessageClient.OnMessageReceivedListener
-Schnittstelle, um einen Listener für Nachrichtenereignisse bereitzustellen. Registrieren Sie den Listener dann mit der Methode addListener
. Das folgende Beispiel zeigt, wie Sie den Listener implementieren können, um VOICE_TRANSCRIPTION_MESSAGE_PATH
zu prüfen. Wenn diese Bedingung true
ist, starten Sie eine Aktivität zur Verarbeitung der Sprachdaten.
Kotlin
fun onMessageReceived(messageEvent: MessageEvent) { if (messageEvent.path == VOICE_TRANSCRIPTION_MESSAGE_PATH) { val startIntent = Intent(this, MainActivity::class.java).apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) putExtra("VOICE_DATA", messageEvent.data) } startActivity(this, startIntent) } }
Java
@Override public void onMessageReceived(MessageEvent messageEvent) { if (messageEvent.getPath().equals(VOICE_TRANSCRIPTION_MESSAGE_PATH)) { Intent startIntent = new Intent(this, MainActivity.class); startIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startIntent.putExtra("VOICE_DATA", messageEvent.getData()); startActivity(this, startIntent); } }
Für diesen Code sind weitere Implementierungsdetails erforderlich. Informationen zum Implementieren eines vollständigen Listener-Dienstes oder einer vollständigen Listener-Aktivität finden Sie unter Datenschichtereignisse aufzeichnen.