GCM:MulticastResult - 哪个结果来自哪个设备?
Posted
技术标签:
【中文标题】GCM:MulticastResult - 哪个结果来自哪个设备?【英文标题】:GCM: MulticastResult - which result is from which device? 【发布时间】:2012-07-21 16:10:16 【问题描述】:按照GCM: Getting Started 指南的最后一部分,在收到结果后需要做一些记账。
引自指南:
现在需要解析结果并在以下情况下采取适当的措施:
如果消息已创建,但结果返回了规范的注册 ID,则需要替换当前注册 带有规范的 ID。 如果返回的错误是 NotRegistered,则需要删除该注册 ID,因为应用程序已从 设备。这是处理这两个条件的代码 sn-p:
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 对象不包含注册 id,但如果第一个已过时,则仅包含规范 id。 如果这两个列表相互关联(即保留顺序和大小),则没有记录。
我如何确定哪个结果是指哪个设备?
-- 更新
我已将解决方案的 sn-p 粘贴到下面的单独答案中
【问题讨论】:
【参考方案1】:结果按照您发送到 GCM 服务器的 registration_id 数组的顺序排列。例如如果您的registration_ids 是:
[id1, id4, id7, id8]
那么你得到的结果数组对于 id1、id4、id7 和 id8 将具有相同的顺序。
您只需要相应地解析每个结果,例如如果第二个结果有 'message_id' 和 'registration_id' of 'id9',你知道 'id4' 现在已经过时了,应该被 id9 取代。
【讨论】:
谢谢!我刚刚在 GCM google 组 (groups.google.com/forum/#!topic/android-gcm/DCHHQwqTs8M) 中找到了这些信息。新的 API 需要时间来获得正确的文档..【参考方案2】:为了方便读者,这里是一个处理多个设备响应的 sn-p
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);
【讨论】:
Result 类有 3 个字段:messageId、canonicalRegistrationId 和 errorCode。所有相关案例都包含在代码 sn-p 中。 canonicalRegistrationId 是一个更新的 gcm 密钥。devices.get(i) has more than one registration ID: update database
- 在这里应该做什么?从数据库中删除 devices.get(i) 或从结果中删除具有 canonicalRegistrationId 的设备?或者检查数据库中是否存在具有 canonicalRegistrationId 的设备?如果是,则删除另一个,如果为false,则更改另一个的id?
您应该用新的 canonicalRegistrationId = new regId 替换旧 regId 的 devices.get(i)。你可能已经有了新的 regId,如果你用新的 regId 注册了同一个用户(认为它是新用户),然后尝试用旧的 id 联系到他。【参考方案3】:
此解决方案由谷歌开发者示例 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);
);
【讨论】:
您链接到的示例应用程序中有一条注释:“本文档中的信息已被 GCM 服务器和 GCM 客户端取代。请使用 GoogleCloudMessaging API 而不是 GCM 客户端帮助程序库。GCM服务器帮助程序库仍然有效。”。你的答案是最新的吗? 它的 2 周更新看起来谷歌已经更新了库并且演示还没有更新:)以上是关于GCM:MulticastResult - 哪个结果来自哪个设备?的主要内容,如果未能解决你的问题,请参考以下文章
GCM Push Server 端,使用哪个 API Key?
GCM 服务器在哪个时间频率刷新注册 ID 以及如何在我的手机中获取 regId 更改事件?