0

我正在尝试将推送通知添加到 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 台设备(因此实际上向 Apple 发送了 10 条推送通知),并且它要么同时接收消息,要么不接收消息,而不仅仅是一个。

4

1 回答 1

0

在短时间内向同一设备发送多个通知可能会导致仅发送其中一些通知。在发送到同一设备的消息之间强制执行一些任意延迟(可能不够也可能不够)不是一个好习惯。您的应用程序必须能够处理不接收您发送给它的所有通知(通过与您的服务器同步)。

以下是 Apple 的技术说明对此的说明:

收到了一些通知,但不是全部

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

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

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

所有这一切都表明,通知的目的是向应用程序指示提供程序上感兴趣的某些内容发生了变化,并且应用程序应与提供程序签入以获取详细信息。通知不应包含在其他地方也不可用的数据,它们也不应该是有状态的。

由于您的设备未连接到服务,任何未立即发送的推送通知都将排队等待将来重新发送。“立即”当然需要考虑您的连接延迟。异常情况将超过 60 秒,因为此时 APN 将超时。

于 2014-01-13T13:59:38.960 回答