2014-01-13 16 views
0

我试图将推送通知添加到Google App Engine服务器,并且我遇到了一个奇怪的问题,即设备只收到每秒推送通知。GAE上的JavaPNS:只接收每第二次推送通知

我已经设置了推送队列来在后端发送通知。每个实例的第一个请求会创建一个后台线程,这些队列会推送并发送它们。然后,每个推送请求将请求添加到队列中,等待推送被发送,然后用代码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),并且它既可以接收消息也可以接收消息,从不只有一个。

+0

您发送了多少封邮件?日志显示5,但是你写道10个推送通知被发送到Apple。那5个消息是发送给同一个设备令牌的吗? (因为你说你只有两个设备)。如果您在短时间内向同一设备发送多条消息,Apple可能只会提供其中的一部分。这是预期的行为。 – Eran

+0

嗨,是的,他们正在被发送到相同的设备令牌......如果这是预期的行为,我必须让服务器延迟消息到相同的令牌?如果是这样,那么延迟需要多长时间? – jjv360

回答

0

在短时间内向同一设备发送多个通知可能会导致其中一部分被传送。在消息到同一设备之间执行一些任意延迟(这可能会或可能不够)是不好的做法。您的应用必须能够处理未收到您发送给它的所有通知(通过与您的服务器同步)。

下面是苹果的tech note说一下:

某些通知接收,但不是所有的

如果您在很短的时间内发送多个通知到同一个设备或 计算机,推送服务将只发送 最后一个。

这是为什么。设备或计算机确认收到每个 通知。在推送服务收到该确认之前,它只能假设该设备或计算机已离线了一些 原因,并将通知存储在服务质量(QoS) 队列中供将来重新传送。这里的往返网络延迟是当然一个主要因素。

如本地和推送通知编程指南中所述,QoS队列为每个设备或每台计算机保留一个通知。 如果服务在 队列中的队列发送之前收到另一个通知,则新通知将覆盖前一个通知。

所有这一切都指出,意图是,通知 指示感兴趣的东西在 提供商已经改变了应用程序,该应用程序应检查与供应商以获得 细节。通知不应包含不在其他地方提供的数据,也不应该是有状态的。

因为您的设备未连接到 服务,所以未立即交付的任何推送通知已排队等待 未来的重新传送。 “立即”当然需要考虑延迟你的 连接。外围案件将超过60秒,因为 APNs将在该点超时。

+0

谢谢,该应用程序已分别与服务器同步,但现在我已添加更多人用不同设备进行测试,它的工作完美:) – jjv360