Nachrichten über Wear senden und empfangen

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.

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:

  1. Erstellen Sie im Verzeichnis res/values/ Ihres Projekts eine XML-Konfigurationsdatei mit dem Namen wear.xml.
  2. Fügen Sie wear.xml eine Ressource mit dem Namen android_wear_capabilities hinzu.
  3. 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.