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 útil para las llamadas de procedimientos remotos (RPC), como el envío de un mensaje al wearable a fin de 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.
Como tiene varios dispositivos conectados, debes considerar los nodos que reciben los mensajes. Por ejemplo, en una app de transcripción de voz que recibe datos de voz en el dispositivo wearable, envía el mensaje a un nodo con la potencia de procesamiento y la capacidad de batería para procesar la solicitud, como un dispositivo de mano.
Nota: Cuando especifiques los detalles de tu mensaje, considera la posibilidad de que haya varios nodos conectados. Asegúrate de que el mensaje se entregue a los dispositivos o nodos previstos.
Consulta la siguiente app de ejemplo para ver ejemplos de uso: DataLayer
Cómo enviar un mensaje
Una app para wearables 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 el modo para 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.
Para anunciar las funciones de tu app para dispositivos de mano, haz 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 cadenas 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 nodos con las funciones requeridas
Inicialmente, puedes detectar los nodos capaces con una llamada al método getCapability
de la clase
CapabilityClient
. Para usar este método, la app para Wear OS y la app para teléfonos deben tener el mismo ID de aplicación. En el siguiente ejemplo, se muestra cómo obtener de forma manual 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 un resultado con nodos accesibles que tengan 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. You can use named or anonymous classes. 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. Elige 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 a aquel que está directamente conectado al dispositivo. Para saber si un nodo está cerca, por ejemplo, conectado por Bluetooth, llama al método Node.isNearby()
. Si hay más de uno, elige uno de manera arbitraria. Del mismo modo, si no hay ningún nodo capaz cerca, elige uno de manera arbitraria.
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 un nodo para usar, envía el mensaje usando la clase
MessageClient
.
En el siguiente ejemplo, se muestra cómo enviar un mensaje desde un dispositivo wearable al nodo capaz de realizar la transcripción. 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 de
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 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 código requiere más detalles sobre la implementación. Obtén información para implementar una actividad o un servicio completo de objeto de escucha en Cómo detectar eventos de Data Layer.