studio notificaciones how google gcm airport android google-cloud-messaging

android - notificaciones - GCM: MulticastResult: ¿cuál es el resultado de qué dispositivo?



notificaciones push android google cloud messaging(gcm) (3)

Esta solución la realiza el desarrollador de Google. Muestra de la aplicación de demostración de GCM.

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

Después de la última sección de la Guía de introducción de GCM: hay una cierta contabilidad que debe realizarse después de recibir los resultados.

Citando de la guía:

Ahora es necesario analizar el resultado y tomar la acción adecuada en los siguientes casos:

  • Si el mensaje fue creado pero el resultado arrojó una identificación canónica de registro, es necesario reemplazar el registro actual.
    ID con el canónico.
  • Si el error devuelto no es registrado, es necesario eliminar ese ID de registro, ya que la aplicación se desinstaló del dispositivo.

Aquí hay un fragmento de código que maneja estas 2 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 de multidifusión. 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 Resultado no contiene el ID de registro, sino solo un ID canónico si el primero está obsoleto. No está documentado si las dos listas están relacionadas entre sí (es decir, conserva el orden y el tamaño).

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

- ACTUALIZAR

He pegado un fragmento de la solución en una respuesta separada 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 obtenga tendrá el mismo orden para id1, id4, id7 e id8.

Solo necesita analizar cada resultado en consecuencia, por ejemplo, si el segundo resultado tiene ''message_id'' e ''registration_id'' de ''id9'', sabe que ''id4'' ahora está obsoleto y debe ser reemplazado por id9.


Para conveniencia de los lectores, aquí hay un fragmento que maneja la respuesta para múltiples 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); } }