GCM: MulticastResult - результат из какого устройства?
Следуя последнему разделу руководства GCM: Getting Started, после получения результатов нужно вести учет.
Цитата из руководства:
Теперь необходимо проанализировать результат и принять правильное действие в следующих случаях:
- Если сообщение было создано, но в результате вернулся канонический идентификатор регистрации, необходимо заменить текущую регистрацию
ID с каноническим. - Если возвращенная ошибка NotRegistered, необходимо удалить этот идентификатор регистрации, поскольку приложение было удалено из устройства.
Вот фрагмент кода, который обрабатывает эти 2 условия:
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
}
}
В приведенном выше руководстве говорится о одиночном результате, а не в случае многоадресной рассылки.
Я не уверен, как обращаться с корпусом многоадресной рассылки:
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);
}
Я представляю список устройств и получаю список результатов.
Объект Result не содержит идентификатор регистрации, а только канонический идентификатор, если первый из них устарел.
Это недокументировано, если два списка взаимосвязаны (т.е. Сохраняет порядок и размер).
Как я могу быть уверен, какой результат относится к какому устройству?
- ОБНОВЛЕНИЕ
Я вставлял фрагмент решения в отдельный ответ ниже
Ответы
Ответ 1
Результаты находятся в порядке вашего массива registration_id, отправленного на сервер GCM. например если вашими регистрационными_имя являются:
[id1, id4, id7, id8]
Тогда полученный массив результатов будет иметь тот же порядок для id1, id4, id7 и id8.
Вам просто нужно проанализировать каждый результат соответственно, например. если у 2-го результата есть "message_id" и "registration_id" из "id9", вы знаете, что "id4" теперь устарел и должен быть заменен на id9.
Ответ 2
Для удобства читателей приведен фрагмент, который обрабатывает ответ для нескольких устройств
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);
}
}
Ответ 3
Это решение выполняется с помощью примера разработчика Google GCM Demo application
обратите внимание на asyncSend для дескриптора многоадресной рассылки
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);
}
}
}
}});
}