Inviare e ricevere messaggi su Wear

Invii i messaggi utilizzando l'API MessageClient e allegando i seguenti elementi al messaggio:

  • Un payload arbitrario facoltativo
  • Un percorso che identifica in modo univoco l'azione del messaggio

A differenza degli elementi di dati, non viene eseguita alcuna sincronizzazione tra le app per dispositivi mobili e indossabili. I messaggi sono un meccanismo di comunicazione unidirezionale utile per le chiamate di procedura remota (RPC), ad esempio l'invio di un messaggio al dispositivo indossabile per avviare un'attività.

È possibile connettere più dispositivi indossabili al dispositivo portatile di un utente. Ogni dispositivo connesso alla rete è considerato un nodo.

Con più dispositivi connessi, devi considerare quali nodi ricevono i messaggi. Ad esempio, in un'app di trascrizione vocale che riceve dati vocali sul dispositivo indossabile, invia il messaggio a un nodo con la potenza di elaborazione e la capacità della batteria per gestire la richiesta, ad esempio un dispositivo portatile.

Nota:quando specifichi i dettagli del messaggio, considera la possibilità di più nodi connessi. Assicurati che il messaggio venga inviato ai dispositivi o ai nodi previsti.

Per esempi di utilizzo, consulta la seguente app di esempio: DataLayer

Inviare un messaggio

Un'app per indossabili può fornire funzionalità agli utenti, come la trascrizione vocale. Gli utenti possono parlare nel microfono del proprio dispositivo indossabile e salvare una trascrizione in una nota. Poiché un dispositivo indossabile in genere non dispone della potenza di elaborazione e della capacità della batteria necessarie per gestire l'attività di trascrizione vocale, l'app deve trasferire questo lavoro a un dispositivo connesso più potente.

Le seguenti sezioni mostrano come pubblicizzare i nodi del dispositivo che possono elaborare le richieste di attività, scoprire i nodi in grado di soddisfare un'esigenza richiesta e inviare messaggi a questi nodi.

Per avviare un'attività su un dispositivo portatile da un dispositivo indossabile, utilizza la classe MessageClient per inviare la richiesta. Poiché è possibile connettere più indossabili al dispositivo portatile, l'app per indossabili deve determinare se un nodo connesso è in grado di avviare l'attività. Nella tua app portatile, pubblicizza che il nodo su cui viene eseguita fornisce funzionalità specifiche.

Per pubblicizzare le funzionalità della tua app portatile:

  1. Crea un file di configurazione XML nella directory res/values/ del tuo progetto e assegnagli il nome wear.xml.
  2. Aggiungi una risorsa denominata android_wear_capabilities a wear.xml.
  3. Definisci le funzionalità fornite dal dispositivo.

Nota:le funzionalità sono stringhe personalizzate che definisci e devono essere univoche all'interno della tua app.

L'esempio seguente mostra come aggiungere una funzionalità denominata voice_transcription a wear.xml:

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

Recupera i nodi con le funzionalità richieste

Inizialmente, puoi rilevare i nodi compatibili chiamando il metodo getCapability della classe CapabilityClient. Per utilizzare questo metodo, l'app Wear OS e l'app per smartphone devono avere lo stesso ID applicazione. L'esempio seguente mostra come recuperare manualmente i risultati dei nodi raggiungibili con la funzionalità 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);
}

Attenzione: prima di utilizzare l'API Wearable Data Layer, verifica che sia disponibile su un dispositivo, altrimenti si verifica un'eccezione. Utilizza la classe GoogleApiAvailability, come implementato in Horologist.

Per rilevare i nodi compatibili quando si connettono al dispositivo indossabile, registra un'istanza di un listener, in particolare un OnCapabilityChangedListener di un oggetto CapabilityClient. L'esempio seguente mostra come registrare il listener e recuperare un risultato con nodi raggiungibili che dispongono della funzionalità 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);
}

Dopo aver rilevato i nodi idonei, determina dove inviare il messaggio. Scegli un nodo vicino al tuo dispositivo indossabile per ridurre al minimo il routing dei messaggi attraverso più nodi. Un nodo nelle vicinanze è definito come un nodo direttamente connesso al dispositivo. Per determinare se un nodo si trova nelle vicinanze, ad esempio se è connesso tramite Bluetooth, chiama il metodo Node.isNearby(). Se sono presenti più nodi nelle vicinanze, scegline uno in modo arbitrario. Allo stesso modo, se non è presente alcun nodo idoneo nelle vicinanze, scegline uno in modo arbitrario.

L'esempio seguente mostra come determinare il nodo migliore da utilizzare:

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

Inviare il messaggio

Una volta identificato un nodo da utilizzare, invia il messaggio utilizzando la classe MessageClient.

L'esempio seguente mostra come inviare un messaggio al nodo in grado di eseguire la trascrizione da un dispositivo indossabile. Questa chiamata è sincrona e blocca l'elaborazione finché il sistema non mette in coda il messaggio per la consegna.

Nota:un codice di risultato positivo non garantisce il recapito del messaggio. Se la tua app richiede l'affidabilità dei dati, valuta la possibilità di utilizzare oggetti DataItem o la classe ChannelClient per inviare dati tra i dispositivi.

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

Nota:per scoprire di più sulle chiamate asincrone e sincrone ai servizi Google Play e quando utilizzarle, consulta l'API Tasks.

Puoi anche trasmettere messaggi a tutti i nodi connessi. Per recuperare tutti i nodi connessi a cui puoi inviare messaggi, implementa il seguente codice:

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

Ricevere un messaggio

Per ricevere una notifica dei messaggi ricevuti, implementa l'interfaccia MessageClient.OnMessageReceivedListener per fornire un listener per gli eventi di messaggistica. Quindi, registra il listener con il metodo addListener. L'esempio seguente mostra come potresti implementare il listener per controllare VOICE_TRANSCRIPTION_MESSAGE_PATH. Se questa condizione è true, avvia un'attività per elaborare i dati vocali.

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

Questo codice richiede ulteriori dettagli di implementazione. Scopri di più su come implementare un servizio o un'attività di ascolto completa in Ascolta gli eventi del livello dati.