Envoyer et recevoir des messages sur Wear

Vous envoyez des messages à l'aide de l'API MessageClient et joignez les éléments suivants au message :

  • Une charge utile arbitraire facultative
  • Un chemin d'accès identifiant de manière unique l'action du message

Contrairement aux éléments de données, aucune synchronisation n'a lieu entre les applications mobiles et connectées. Les messages constituent un mécanisme de communication unidirectionnel adapté aux appels de procédure à distance (RPC), comme l'envoi d'un message à l'accessoire connecté pour démarrer une activité.

Plusieurs accessoires connectés peuvent être connectés à l'appareil portable d'un utilisateur. Chaque appareil connecté au réseau est considéré comme un nœud.

Lorsque plusieurs appareils sont connectés, vous devez déterminer quels nœuds reçoivent les messages. Par exemple, dans le cas d'une application de transcription vocale qui reçoit des données vocales sur l'appareil connecté, envoyez le message à un nœud disposant de la puissance de calcul et de la capacité de batterie nécessaires pour traiter la requête, comme un appareil portable.

Remarque : Lorsque vous spécifiez les détails de votre message, tenez compte du fait qu'il peut y avoir plusieurs nœuds connectés. Assurez-vous que le message est diffusé sur les appareils ou les nœuds prévus.

Reportez-vous aux applications exemples suivantes pour en savoir plus :

Envoie un message

Une appli connectée peut fournir des fonctionnalités aux utilisateurs, comme la transcription vocale. Les utilisateurs peuvent parler dans le micro de leur accessoire connecté et enregistrer une transcription dans une note. Étant donné qu'un accessoire connecté ne dispose généralement pas de la puissance de calcul ni de la capacité de batterie nécessaires pour traiter l'activité de transcription vocale, l'appli doit déléguer cette tâche à un appareil connecté plus performant.

Les sections suivantes expliquent comment annoncer les nœuds d'appareil pouvant traiter des requêtes d'activité, identifier les nœuds capables de répondre à une demande et envoyer des messages à ces nœuds.

Pour lancer une activité sur un appareil portable à partir d'un accessoire connecté, utilisez la classe MessageClient afin d'envoyer la requête. Étant donné que plusieurs accessoires connectés peuvent être connectés à l'appareil portable, l'appli connectée doit déterminer qu'un nœud connecté est capable de lancer l'activité. Dans votre application portable, annoncez que le nœud sur lequel elle s'exécute fournit des fonctionnalités spécifiques.

Pour annoncer les fonctionnalités de votre application portable, procédez comme suit :

  1. Créez un fichier de configuration XML dans le répertoire res/values/ de votre projet et nommez-le wear.xml.
  2. Ajoutez une ressource nommée android_wear_capabilities à wear.xml.
  3. Définissez les fonctionnalités fournies par l'appareil.

Remarque : Les fonctionnalités sont des chaînes personnalisées que vous définissez et qui doivent être uniques au sein de votre application.

L'exemple suivant montre comment ajouter une fonctionnalité nommée voice_transcription à wear.xml :

<resources xmlns:tools="http://schemas.android.com/tools"
           tools:keep="@array/android_wear_capabilities">
    <string-array name="android_wear_capabilities">
        <item>voice_transcription</item>
    </string-array>
</resources>

Récupérer les nœuds disposant des fonctionnalités requises

Au début, vous pouvez détecter les nœuds qui présentent les fonctionnalités nécessaires en appelant la méthode getCapability de la classe CapabilityClient. Pour que cette méthode puisse être utilisée, l'application Wear OS et l'application pour téléphone doivent avoir le même ID application. L'exemple suivant montre comment récupérer manuellement les résultats de nœuds accessibles avec la fonctionnalité voice_transcription :

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

Pour détecter les nœuds qui présentent les fonctionnalités nécessaires lorsqu'ils se connectent à l'accessoire connecté, enregistrez une instance d'un écouteur, et plus précisément un OnCapabilityChangedListener d'un objet CapabilityClient. L'exemple suivant montre comment enregistrer l'écouteur et récupérer un résultat avec des nœuds accessibles qui disposent de la fonctionnalité voice_transcription :

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

Après avoir détecté les nœuds compatibles, déterminez la destination du message. Choisissez un nœud situé à proximité de votre accessoire connecté afin de réduire l'acheminement des messages via plusieurs nœuds. Un nœud à proximité se définit comme étant directement connecté à l'appareil. Pour déterminer si un nœud est à proximité, par exemple connecté via Bluetooth, appelez la méthode Node.isNearby(). Si plusieurs nœuds se trouvent à proximité, choisissez-en un de façon arbitraire. De même, si aucun nœud compatible ne se trouve à proximité, choisissez-en un arbitrairement.

L'exemple suivant montre comment identifier le meilleur nœud à utiliser :

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

Diffuser le message

Une fois que vous avez identifié un nœud à utiliser, envoyez le message à l'aide de la classe  MessageClient.

L'exemple suivant montre comment envoyer un message au nœud compatible avec la transcription à partir d'un accessoire connecté. Cet appel est synchrone et bloque le traitement jusqu'à ce que le système mette le message en file d'attente en vue de le diffuser.

Remarque : Un code de résultat réussi ne garantit pas la diffusion du message. Si la fiabilité des données est requise, pensez à utiliser des objets DataItem ou la classe ChannelClient pour envoyer des données entre les appareils.

Kotlin

const val VOICE_TRANSCRIPTION_MESSAGE_PATH = "/voice_transcription"
...
private fun requestTranscription(voiceData: ByteArray) {
    transcriptionNodeId?.also { nodeId ->
        val sendTask: 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) {
        Task<Integer> 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
    }
}

Remarque:Pour en savoir plus sur les appels asynchrones et synchrones vers les services Google Play, et pour savoir quand les utiliser, consultez l'API Tasks.

Vous pouvez également diffuser des messages sur tous les nœuds connectés. Pour récupérer tous les nœuds connectés auxquels vous pouvez envoyer des messages, implémentez le code suivant :

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

Recevoir un message

Pour être averti des messages reçus, implémentez l'interface MessageClient.OnMessageReceivedListener afin de fournir un écouteur pour les événements de message. Ensuite, enregistrez l'écouteur avec la méthode addListener. L'exemple suivant montre comment mettre en œuvre l'écouteur pour vérifier le VOICE_TRANSCRIPTION_MESSAGE_PATH. Si cette condition a la valeur true, démarrez une activité pour traiter les données vocales.

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

Ce code nécessite davantage d'informations sur l'implémentation. Pour découvrir comment implémenter une activité ou un service d'écoute complet, consultez la section Écouter les événements Data Layer.