java - 发送批量 iOS 通知时出现问题

标签 java ios push-notification payload

我在为 iOS 设备发送批量通知时遇到问题,当我发送一些设备(或多或少 1-20 个)时,它可以正常工作,但是当我必须发送批量发送(3000+)时,它会出现以下错误:

[2017-04-27 15:12:07] ERROR (Notificaciones:347) - IOS: Error en envio notificaciones - CommunicationException: javapns.communication.exceptions.CommunicationException: Communication exception: java.net.ConnectException: Expir󠥬 tiempo de conexi󮠨Connection timed out) at javapns.communication.ConnectionToAppleServer.getSSLSocket(ConnectionToAppleServer.java:156) at javapns.notification.PushNotificationManager.initializeConnection(PushNotificationManager.java:106) at javapns.notification.transmission.NotificationThread.runList(NotificationThread.java:215) at javapns.notification.transmission.NotificationThread.run(NotificationThread.java:199) at java.lang.Thread.run(Thread.java:745) Caused by: java.net.ConnectException: Expir󠥬 tiempo de conexi󮠨Connection timed out) at java.net.PlainSocketImpl.socketConnect(Native Method) at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339) at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200) at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182) at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) at java.net.Socket.connect(Socket.java:576) at sun.security.ssl.SSLSocketImpl.connect(SSLSocketImpl.java:635) at sun.security.ssl.SSLSocketImpl.(SSLSocketImpl.java:423) at sun.security.ssl.SSLSocketFactoryImpl.createSocket(SSLSocketFactoryImpl.java:88) at javapns.communication.ConnectionToAppleServer.getSSLSocket(ConnectionToAppleServer.java:153) ... 4 more

我的代码如下:

private static  void realizaEnvioIOSLista (final List<DispositivoDto> dispositivos, final String textoES, final String textoCA, final String textoEN, final String tipoNotificacion){       

        Thread thread = new Thread(){
            public void run(){              
                try {           
                    final List<String> idsDispositivos = new ArrayList<String>();                   

                    final String keystore = XmlUtils.dirCertIOS + XmlUtils.nomCertificado;
                    final String password = XmlUtils.password;
                    final boolean production = XmlUtils.production;

                    //Obtenemos los ids de los dispositivos
                    for(DispositivoDto r : dispositivos)
                         idsDispositivos.add(r.getIdDispositivo());                  

                    PushNotificationPayload payload = PushNotificationBigPayload.complex();

                    /* Customize the payload */ 
                    payload.addAlert(textoES);    
//                  payload.addSound('default');
                    payload.setContentAvailable(true);

                    payload.addCustomDictionary("es", textoES);
                    payload.addCustomDictionary("en", textoCA);
                    payload.addCustomDictionary("ca", textoEN);
                    payload.addCustomDictionary("tiponotificacion", tipoNotificacion);  

                    List<PushedNotification> notifications = new ArrayList<PushedNotification>();

                    if(idsDispositivos.size()<= 200){   
                        notifications = Push.payload(payload, keystore, password, production, idsDispositivos);

                    } else {
                        int threads = 1;

                        if(dispositivos.size() > 200) {
                            threads = (int) Math.ceil(dispositivos.size()/200);
                        }

                        notifications = Push.payload(payload, keystore, password, production, threads, idsDispositivos);  
                    }

                    int dispEliminados = 0;
                    int dispNotificados = 0;

                    for (PushedNotification notification : notifications) {
                        if (notification.isSuccessful()) {
                            dispNotificados ++;
                        } else {
                            String invalidToken = notification.getDevice().getToken();

                            int index = idsDispositivos.indexOf(invalidToken);

                            Integer usuario = dispositivos.get(index).getUsuario();
                            String idHardware = dispositivos.get(index).getIdHardwareDis();

                            aBD.unregisterDispositivo(usuario, invalidToken,idHardware);
                            dispEliminados ++;

        //                  Exception theProblem = notification.getException();
        //                  theProblem.printStackTrace();

                            //If the problem was an error-response packet returned by Apple, get it
                            ResponsePacket theErrorResponse = notification.getResponse();

                            if (theErrorResponse != null){
                                logNot.info("IOS: " +theErrorResponse.getMessage());
                            }
                        }
                    }   
                    logNot.info("IOS: Dispositivos Notificados correctamente: " + dispNotificados);
                    logNot.info("IOS: Dispositivos Eliminados: " +dispEliminados);

                } catch (CommunicationException e) {
                    logNot.error("IOS: Error en envio notificaciones - CommunicationException: ",e);
                } catch (KeystoreException e) {
                    logNot.error("IOS: Error en envio notificaciones - KeystoreException: ",e);
                } catch (JSONException e) {
                    logNot.error("IOS: Error en envio notificaciones - JSONException: ",e);
                } catch (Exception e) {
                    logNot.error("IOS: Error en envio notificaciones",e);
                }
            }
        };

        thread.start();
    }

有什么问题吗?最多可以连接多少台设备以及连接到 Apple 服务器?欢迎任何帮助。

最佳答案

我找到了问题的解决方案,代码工作正常,在与系统管理员交谈后,我们可以看到这是服务器配置的问题,因为根据apple这个链接为了能够发送通知,必须考虑以下因素:

To use Apple Push Notification service (APNs), your Mac and iOS clients need a direct and persistent connection to Apple's servers.

这样:

If you use Wi-Fi behind a firewall, or private Access Point Name for cellular data, connect to specific ports. You need a direct, unproxied connection to the APNs servers on these ports:

  • TCP port 5223 to communicate with APNs.
  • TCP port 2195 to send notifications to APNs.
  • TCP port 2196 for the APNs feedback service.
  • TCP port 443 is required during device activation, and afterwards for fallback (on Wi-Fi only) if devices can't reach APNs on port 5223.

此外:

The APNs servers use load balancing, so your devices don't always connect to the same public IP address for notifications. It's best to let your device access these ports on the entire 17.0.0.0/8 address block, which is assigned to Apple.

因此,系统管理员通过配置防火墙以允许这些连接,一切都已得到解决。我希望它对某人有帮助。

关于java - 发送批量 iOS 通知时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43758841/

相关文章:

android - 如何从服务器推送通知到安卓手机

java - 如何在 session 中存储用户ID并在android中的另一个类中检索它?

Java正则表达式获取所有数字

ios - 为 Apple 推送服务重用证书签名请求

swift - Xcode6 Swift 添加远程推送通知并从 PHP 发送

iphone - Apple 推送通知如何在 iPhone 应用程序中传递给用户?

java - 启动默认浏览器并获取 url

java - 如何随机化图像阵列

ios - 在 iOS 中未填充所有 UITextField 时尝试禁用按钮

ios - 如何将多个相同节点添加到 View 中?