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

3 Solutions collect form web for “GCM: MulticastResult – ¿cuál es el resultado de qué dispositivo?”

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); } } } }}); } 
  • GCM Enviar mensajes a Temas: TOO_MANY_TOPICS error
  • El anular el registro y el nuevo registro de mensajes GCM hace que dos regId sean válidos. ¿Es esto como se pretende?
  • GCM funciona bien en Android pero no funciona en iOS
  • Cómo puedo saber los dispositivos registrados en mi nube de aplicaciones de GCM (Lista de dispositivos)
  • SecurityException: No se puede iniciar el servicio Intención {act = com.google.android.c2dm.intent.REGISTER pkg = com.google.android.gms (tiene extras)}
  • Mensajería en la nube de Google (fake_message_id)
  • GCM duplicó mensajes
  • Cómo cancelar el registro de GCM después de desinstalar la aplicación
  • Mantener el ID de registro de la aplicación GCM válido durante las actualizaciones automáticas
  • ¿Cómo soluciono el error MMUMapper?
  • ¿Los viejos ficheros GCM siguen activos incluso después de una desinstalación?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.