我正在尝试向Google App Engine服务器添加推送通知,而且我遇到了一个奇怪的问题,即设备只会收到每秒推送通知。
我已设置推送队列以在后端发送通知。每个实例的第一个请求创建一个后台线程,该队列将推送并发送它们。然后,每个推送请求将请求添加到队列,等待推送被发送,然后用代码200响应成功或代码500响应失败。这是我的后台线程代码:
void doSendThread() {
// Open certificate (certificate is a class URL var)
InputStream cert = certificate.openStream();
// Connect to Apple Push service (password and apnsManager are class vars)
AppleNotificationServer appleServer = new AppleNotificationServerBasicImpl(cert, password, ConnectionToAppleServer.KEYSTORE_TYPE_PKCS12, "gateway.push.apple.com", 2195);
apnsManager = new PushNotificationManager();
apnsManager.initializeConnection(appleServer);
// Send loop
while (true) {
// Wait for a bit
Thread.sleep(500);
// Check for new pushes in queue (pushQueue is a class ArrayDequeue var)
while (!pushQueue.isEmpty()) {
// Get next push data (PushData is a custom class that holds the push notification state)
PushData data = pushQueue.poll();
// Send data (the HTTP request thread stops waiting when data.done is true)
sendPushData(data);
data.done = true;
}
}
// There's also some feedback checking stuff here which I've left out
...
}
void sendPushData(PushData) {
try {
// Get tokens
Logger.getLogger(PushManager.class.getName()).log(Level.INFO, "Sending push...");
List<Device> devices = Devices.asDevices(data.tokens);
// Create payload
PushNotificationPayload payload = PushNotificationPayload.complex();
if (data.text.length() > 0)
payload.addAlert(data.text);
if (data.badge > 0)
payload.addBadge(data.badge);
if (data.sound.length() > 0)
payload.addSound(data.sound);
// Go through devices and send each push
for (Device dev : devices) {
// Send payload and don't close the connection
PushedNotification pn = apnsManager.sendNotification(dev, payload, false);
// Check for error (HTTP thread returns 500 if data.error is true)
if (!pn.isSuccessful())
data.error = true;
// Log error
if (pn.getException() != null)
Logger.getLogger(PushManager.class.getName()).log(Level.SEVERE, "Push error: " + pn.getException().getMessage());
}
} catch (Exception e) {
Logger.getLogger(PushManager.class.getName()).log(Level.SEVERE, "Push error: " + e.getMessage());
e.printStackTrace();
disconnect(); // <- Disconnects the apnsManager and shuts down the thread, the next push request will create a new thread and reconnect
data.error = true;
}
}
在GAE上记录很困难,因为一旦实例关闭,日志只会通过后台线程,但如果我使用应用程序发送5次推送然后关闭实例,这是我的日志:
W 2014-01-13 13:41:18.028 [s~*****chat/push-notification-worker.373021320690690677].<stderr>: log4j:WARN No appenders could be found for logger (javapns.communication.Connecti
W 2014-01-13 13:41:18.028 [s~*****chat/push-notification-worker.373021320690690677].<stderr>: log4j:WARN Please initialize the log4j system properly.
W 2014-01-13 13:41:18.028 [s~*****chat/push-notification-worker.373021320690690677].<stderr>: log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more inf
I 2014-01-13 13:41:19.222 com.*****apps.*****Server.Push.PushManager sendPushData: Sending push...
I 2014-01-13 13:41:23.027 com.*****apps.*****Server.Push.PushManager sendPushData: Sending push...
I 2014-01-13 13:41:23.663 com.*****apps.*****Server.Push.PushManager sendPushData: Sending push...
I 2014-01-13 13:41:24.225 com.*****apps.*****Server.Push.PushManager sendPushData: Sending push...
I 2014-01-13 13:41:24.790 com.*****apps.*****Server.Push.PushManager sendPushData: Sending push...
I 2014-01-13 13:42:25.022 com.*****apps.*****Server.Push.PushManager disconnect: Shutting down push manager...
...所以看起来它发送全部5个,但我只得到第二个和第四个在设备上通过。真正奇怪的是,每次推送实际上发送了2次推送,因为我有2个设备(因此实际上有10个推送通知被发送到Apple),并且它既可以在两者上也不在任何一个上接收消息,而不仅仅是一个。< / p>
答案 0 :(得分:0)
在短时间内向同一设备发送多个通知可能会导致其中一些通知被传递。在同一设备的消息之间强制执行某些任意延迟(可能是也可能不够)并不是一个好习惯。您的应用必须能够处理不接收您发送给它的所有通知(通过与您的服务器同步)。
这是Apple的tech note对此的说法:
收到了一些通知,但并非全部
如果要向同一设备发送多个通知或 计算机在短时间内,推送服务将发送 只有最后一个。
这就是原因。设备或计算机确认收到每个 通知。直到推送服务收到该确认,它 只能假设设备或计算机已脱机 理由并将通知存储在服务质量(QoS)中 排队等待将来重新开始。这里的往返网络延迟是 当然是一个主要因素。
如本地和推送通知编程指南中所述 QoS队列为每个设备或计算机的每个应用程序保留一个通知。 如果服务在收到通知之前收到另一个通知 队列被发送,新通知将覆盖前一个通知。
所有这些都指出意图是通知 向应用程序表明感兴趣的内容已经发生了变化 提供商,应用程序应该与提供商签入以获取 细节。通知不应包含不同的数据 可以在其他地方找到,也不应该是有状态的。
任何未立即发送的推送通知都已排队等候 未来的重新发送,因为您的设备未连接到 服务。 “立即”当然需要为你的延迟 连接考虑在内。边远案件将超过60秒 APN将在那时超时。