Para enviar mensajes, debes usar la API de
MessageClient
y adjuntar los siguientes elementos al mensaje:
- Una carga útil arbitraria (opcional)
- Una ruta de acceso que identifica exclusivamente la acción del mensaje.
A diferencia de lo que ocurre en el caso de los elementos de datos, no se produce ninguna sincronización entre las apps para dispositivos de mano y para wearables. Los mensajes son un mecanismo de comunicación unidireccional apropiado para las llamadas de procedimientos remotos (RPC), como el envío de un mensaje al wearable para iniciar una actividad.
Se pueden conectar varios wearables al dispositivo de mano de un usuario. Cada dispositivo conectado en la red se considera un nodo. Al tener varios dispositivos conectados, debes considerar qué nodos reciben los mensajes. Por ejemplo, en una app de transcripción de voz que recibe datos de voz en el wearable, debes enviar el mensaje a un nodo con la potencia de procesamiento y la capacidad de batería para manejar la solicitud, como un dispositivo de mano.
Nota: Con las versiones de los Servicios de Google Play anteriores a 7.3.0, solo se podía conectar un wearable a un dispositivo de mano a la vez. Es posible que debas actualizar tu código existente para que se tenga en cuenta la función de varios nodos conectados. Si no implementas los cambios, tus mensajes podrían no entregarse a los dispositivos que deseas.
Consulta los siguientes recursos relacionados:
Cómo enviar un mensaje
Una app para wearable puede proporcionar funciones como la transcripción de voz a los usuarios. Los usuarios pueden hablar al micrófono de su dispositivo wearable y guardar la transcripción de lo que dicen en una nota. Como un dispositivo wearable generalmente no tiene la potencia de procesamiento ni la capacidad de batería necesarias para controlar la actividad de transcripción de voz, la app debe descargar este trabajo en un dispositivo conectado con mayor capacidad.
En las siguientes secciones, verás cómo anunciar nodos de dispositivos que pueden procesar solicitudes de actividad, identificar los nodos capaces de satisfacer una necesidad solicitada y enviar mensajes a esos nodos.
Cómo anunciar funciones
Si vas a iniciar una actividad en un dispositivo de mano desde un wearable, usa la clase
MessageClient
para enviar la solicitud. Como se pueden conectar varios wearables al dispositivo de mano, la app para wearables debe determinar que hay un nodo conectado capaz de iniciar la actividad. En tu app para dispositivos de mano, anuncia que el nodo en el que se ejecuta proporciona funciones específicas.
A fin de anunciar las funciones de tu app para dispositivos de mano, realiza lo siguiente:
- Crea un archivo de configuración XML en el directorio
res/values/
de tu proyecto y asígnale el nombrewear.xml
. - Agrega un recurso llamado
android_wear_capabilities
awear.xml
. - Define las funciones que brinda el dispositivo.
Nota: Las funciones son strings personalizadas que defines y deben ser únicas dentro de tu app.
En el siguiente ejemplo, se muestra cómo agregar una función llamada voice_transcription
a 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>
Cómo obtener los nodos con las funciones requeridas
Inicialmente, puedes detectar los nodos capaces mediante una llamada al método getCapability
de la clase
CapabilityClient
. En el siguiente ejemplo, se muestra cómo obtener manualmente los resultados de los nodos disponibles con la función 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); }
Para detectar nodos capaces a medida que se conectan al dispositivo wearable, registra una instancia de un objeto de escucha, específicamente un OnCapabilityChangedListener
de un objeto
CapabilityClient
. En el siguiente ejemplo, se muestra cómo registrar el objeto de escucha y obtener los resultados de los nodos disponibles con la función 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. Named or anonymous classes can also be used. CapabilityClient.OnCapabilityChangedListener capabilityListener = capabilityInfo -> { updateTranscriptionCapability(capabilityInfo); }; Wearable.getCapabilityClient(context).addListener( capabilityListener, VOICE_TRANSCRIPTION_CAPABILITY_NAME); }
Después de detectar los nodos capaces, determina adónde enviar el mensaje. Deberías elegir un nodo que esté cerca de tu dispositivo wearable para minimizar el enrutamiento de mensajes a través de muchos nodos. Se entiende por nodo cercano aquel que está directamente conectado al dispositivo. Para saber si hay un nodo cerca, llama al método Node.isNearby()
.
En el siguiente ejemplo, se muestra cómo podrías determinar cuál es el mejor nodo para usar:
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; }
Cómo entregar el mensaje
Cuando hayas identificado cuál es el mejor nodo para usar, envía el mensaje usando la clase
MessageClient
.
En el ejemplo a continuación, se muestra cómo enviar un mensaje desde un dispositivo wearable al nodo capaz de realizar la transcripción. Verifica que el nodo esté disponible antes de intentar enviar el mensaje. Esta llamada es síncrona y bloquea el procesamiento hasta que el sistema pone en cola el mensaje para su entrega.
Nota: Un código de resultado exitoso no garantiza que se haya entregado el mensaje. Si tu app requiere confiabilidad de datos, puedes usar objetos DataItem
o la clase ChannelClient
para enviar datos entre dispositivos.
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 } }
Nota: Para obtener más información sobre las llamadas síncronas y asíncronas a los Servicios de Google Play y cuándo usarlas, consulta la API de Tasks.
También puedes transmitir mensajes a todos los nodos conectados. Para recuperar todos los nodos conectados a los que puedes enviar mensajes, implementa el siguiente código:
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; }
Cómo recibir un mensaje
Si quieres recibir notificaciones de mensajes recibidos, implementa la interfaz
MessageClient.OnMessageReceivedListener
para proporcionar un objeto de escucha de eventos de mensaje. Luego, registra ese objeto de escucha con el método addListener
. En el siguiente ejemplo, se muestra cómo podrías implementar el objeto de escucha para comprobar la VOICE_TRANSCRIPTION_MESSAGE_PATH
. Si la condición es true
, inicia una actividad para procesar los datos de voz.
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); } }
Este es solo un fragmento que requiere más detalles de implementación. Obtén información sobre cómo implementar una actividad o un servicio completo de objeto de escucha en Cómo escuchar eventos de Data Layer.