GCM: MulticastResult – ¿cuál es el resultado de qué dispositivo?

Siguiendo la última sección en la guía de GCM: Getting Started , hay una contabilidad que debe hacerse después de recibir los resultados.

Citando la guía:

Ahora es necesario analizar el resultado y tomar las medidas adecuadas en los siguientes casos:

  • Si el mensaje se creó pero el resultado devolvió un ID de registro canónico, es necesario reemplazar el registro actual
    ID con el canónico.
  • Si el error devuelto es NotRegistered, es necesario quitar ese ID de registro, porque la aplicación se desinstaló del dispositivo.

He aquí un fragmento de código que maneja estas dos condiciones:

if (result.getMessageId() != null) { String canonicalRegId = result.getCanonicalRegistrationId(); if (canonicalRegId != null) { // same device has more than on registration ID: update database } } else { String error = result.getErrorCodeName(); if (error.equals(Constants.ERROR_NOT_REGISTERED)) { // application has been removed from device - unregister database } } 

La guía anterior se refiere a un solo resultado, y no al caso multicast. No estoy seguro de cómo manejar el caso de multidifusión:

  ArrayList<String> devices = new ArrayList<String>(); for (String d : relevantDevices) { devices.add(d); } Sender sender = new Sender(myApiKey); Message message = new Message.Builder().addData("hello", "world").build(); try { MulticastResult result = sender.send(message, devices, 5); for (Result r : result.getResults()) { if (r.getMessageId() != null) { String canonicalRegId = r.getCanonicalRegistrationId(); if (canonicalRegId != null) { // same device has more than on registration ID: update database // BUT WHICH DEVICE IS IT? } } else { String error = r.getErrorCodeName(); if (error.equals(Constants.ERROR_NOT_REGISTERED)) { // application has been removed from device - unregister database // BUT WHICH DEVICE IS IT? } } } } catch (IOException ex) { Log.err(TAG, "sending message failed", ex); } 

Presento una lista de dispositivos y recibo una lista de resultados. El objeto Result no contiene el id de registro, sino sólo un id canónico si el primero está obsoleto. Es indocumentado si las dos listas están relacionadas (es decir, conserva el orden y el tamaño).

¿Cómo puedo estar seguro de qué resultado se refiere a qué dispositivo?

– ACTUALIZACIÓN

He pegado un fragmento de la solución en una respuesta por separado a continuación

Los resultados están en el orden de la matriz registration_id que envió al servidor GCM. Por ejemplo, si sus registration_ids son:

 [id1, id4, id7, id8] 

Entonces la matriz de resultados que obtendrá tendrá el mismo orden para id1, id4, id7 e id8.

Sólo tienes que analizar cada resultado en consecuencia, por ejemplo, si el 2do resultado tiene 'id_mensaje' y 'id_de_registro' de 'id9', sabes que 'id4' está obsoleto y debería ser reemplazado por id9.

Para la conveniencia de los lectores, aquí hay un fragmento que maneja la respuesta de varios dispositivos

 public void sendMessageToMultipleDevices(String key, String value, ArrayList<String> devices) { Sender sender = new Sender(myApiKey); Message message = new Message.Builder().addData(key, value).build(); try { MulticastResult result = sender.send(message, devices, 5); MTLog.info(TAG, "result " + result.toString()); for (int i = 0; i < result.getTotal(); i++) { Result r = result.getResults().get(i); if (r.getMessageId() != null) { String canonicalRegId = r.getCanonicalRegistrationId(); if (canonicalRegId != null) { // devices.get(i) has more than on registration ID: update database } } else { String error = r.getErrorCodeName(); if (error.equals(Constants.ERROR_NOT_REGISTERED)) { // application has been removed from devices.get(i) - unregister database } } } } catch (IOException ex) { MTLog.err(TAG, "sending message failed", ex); } } 

Esta solución es hecha por la muestra de desarrollador de google GCM Demo aplicación nota el asyncSend para multicasting manejar

 List<GcmUsers> devices=SearchRegisterdDevicesByCourseCommand.execute(instructorId, courseId); String status; if ( devices.equals(Collections.<GcmUsers>emptyList())) { status = "Message ignored as there is no device registered!"; } else { // NOTE: check below is for demonstration purposes; a real application // could always send a multicast, even for just one recipient if (devices.size() == 1) { // send a single message using plain post GcmUsers gcmUsers = devices.get(0); Message message = new Message.Builder().build(); Result result = sender.send(message, gcmUsers.getGcmRegid(), 5); status = "Sent message to one device: " + result; } else { // send a multicast message using JSON // must split in chunks of 1000 devices (GCM limit) int total = devices.size(); List<String> partialDevices = new ArrayList<String>(total); int counter = 0; int tasks = 0; for (GcmUsers device : devices) { counter++; partialDevices.add(device.getGcmRegid()); int partialSize = partialDevices.size(); if (partialSize == MULTICAST_SIZE || counter == total) { asyncSend(partialDevices); partialDevices.clear(); tasks++; } } status = "Asynchronously sending " + tasks + " multicast messages to " + total + " devices"; } } req.setAttribute(HomeServlet.ATTRIBUTE_STATUS, status.toString()); private void asyncSend(List<String> partialDevices) { // make a copy final List<String> devices = new ArrayList<String>(partialDevices); threadPool.execute(new Runnable() { public void run() { Message message = new Message.Builder().build(); MulticastResult multicastResult; try { multicastResult = sender.send(message, devices, 5); } catch (IOException e) { logger.log(Level.SEVERE, "Error posting messages", e); return; } List<Result> results = multicastResult.getResults(); // analyze the results for (int i = 0; i < devices.size(); i++) { String regId = devices.get(i); Result result = results.get(i); String messageId = result.getMessageId(); if (messageId != null) { logger.fine("Succesfully sent message to device: " + regId + "; messageId = " + messageId); String canonicalRegId = result.getCanonicalRegistrationId(); if (canonicalRegId != null) { // same device has more than on registration id: update it logger.info("canonicalRegId " + canonicalRegId); Datastore.updateRegistration(regId, canonicalRegId); } } else { String error = result.getErrorCodeName(); if (error.equals(Constants.ERROR_NOT_REGISTERED)) { // application has been removed from device - unregister it logger.info("Unregistered device: " + regId); Datastore.unregister(regId); } else { logger.severe("Error sending message to " + regId + ": " + error); } } } }}); } 
  • Cómo obtener una clave de API para usarla con Google Cloud Messaging
  • Mensajes de GCM no se entregan
  • Android GCM time_to_live issue
  • GCM deja de funcionar después de algún tiempo
  • Servidor para la notificación de empuje de GCM a android en C #
  • Integración de GCM para Android
  • GCMRegistrar.getRegistrationId (this) siempre devuelve una cadena vacía, incluso después de una llamada correcta para registrarse
  • ID de registro canónico y formato ID de mensaje
  • Manejo de identificadores de registro de GCM para varios dispositivos, mismo usuario
  • ¿Es posible enviar la Notificación Push desde Java Server Side 3 mes automáticamente entre la fecha de inicio y la fecha de finalización para cada usuario diferente?
  • Comprobación rápida de GCM de Android para comprobar si hay fichas
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.