Java 无法通过使用Smack的CCS接收来自Google云消息的所有消息(仅每秒一次)

Java 无法通过使用Smack的CCS接收来自Google云消息的所有消息(仅每秒一次),java,google-cloud-messaging,smack,Java,Google Cloud Messaging,Smack,我正在尝试使用Smack 4.1.2通过云连接服务器(XMPP连接)与Google云消息建立连接。 我已经能够建立连接并接收传入消息。但我的问题是StanzaListener并不是由每条消息触发的(而只是每秒钟一条)。Smack调试控制台显示所有“原始接收数据包”,因此从设备到云的发送对每条消息都有效 谢谢你的帮助 以下是我在服务器应用程序中的代码: My Class GCMServer与主服务器: public class GCMServer { public static final Lo

我正在尝试使用Smack 4.1.2通过云连接服务器(XMPP连接)与Google云消息建立连接。 我已经能够建立连接并接收传入消息。但我的问题是StanzaListener并不是由每条消息触发的(而只是每秒钟一条)。Smack调试控制台显示所有“原始接收数据包”,因此从设备到云的发送对每条消息都有效

谢谢你的帮助

以下是我在服务器应用程序中的代码:

My Class GCMServer与主服务器:

public class GCMServer {

public static final Logger logger = Logger.getLogger(GCMServer.class.getName());
public static SSLContext sslCtx;
public static XMPPTCPConnection connection;

private static final String GCM_SERVER = "gcm.googleapis.com";
private static final int GCM_PORT = 5235;

private static final String GCM_ELEMENT_NAME = "gcm";
private static final String GCM_NAMESPACE = "google:mobile:data";

private static final String YOUR_PROJECT_ID = "xxxxxxxxxxxx";
private static final String YOUR_API_KEY = "xxxx";



public static void main(String[] args) {

    ConnectionListener cl;

    try {        

        KeyStore windowsRootTruststore = KeyStore.getInstance("Windows-ROOT", "SunMSCAPI");
        windowsRootTruststore.load(null, null);
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(windowsRootTruststore);
        sslCtx = SSLContext.getInstance("TLS");
        sslCtx.init(null, tmf.getTrustManagers(), null);

       } catch (KeyStoreException | NoSuchProviderException | IOException | NoSuchAlgorithmException | CertificateException | KeyManagementException ex) {
            Logger.getLogger(GCMServer.class.getName()).log(Level.SEVERE, null, ex);
        } 



        XMPPTCPConnectionConfiguration conf = XMPPTCPConnectionConfiguration.builder()
                .setSecurityMode(SecurityMode.ifpossible)
                .setUsernameAndPassword(YOUR_PROJECT_ID, YOUR_API_KEY)
                .setHost(GCM_SERVER)
                .setServiceName(GCM_SERVER)
                .setPort(5235)
                .setDebuggerEnabled(true)
                .setCompressionEnabled(false)
                .setSocketFactory(sslCtx.getSocketFactory())
                .build();


    cl = new ConnectionListener() {

        @Override
        public void connected(XMPPConnection xmppc) {
             Logger.getLogger(GCMServer.class.getName()).log(Level.INFO, "connected");
             System.out.println("Conncetion is secure: "+connection.isSecureConnection());
        }

        @Override
        public void authenticated(XMPPConnection xmppc, boolean bln) {
            Logger.getLogger(GCMServer.class.getName()).log(Level.INFO, "authenticated");
        }

        @Override
        public void connectionClosed() {
            Logger.getLogger(GCMServer.class.getName()).log(Level.INFO, "connection closed");
        }

        @Override
        public void connectionClosedOnError(Exception excptn) {
            Logger.getLogger(GCMServer.class.getName()).log(Level.INFO, "conncetion closed on error");
        }

        @Override
        public void reconnectionSuccessful() {
            Logger.getLogger(GCMServer.class.getName()).log(Level.INFO, "reconnection successful");
        }

        @Override
        public void reconnectingIn(int i) {
            Logger.getLogger(GCMServer.class.getName()).log(Level.INFO, "reconnecting..");
        }

        @Override
        public void reconnectionFailed(Exception excptn) {
            Logger.getLogger(GCMServer.class.getName()).log(Level.INFO, "reconnection failed");
        }
    };

        connection = new XMPPTCPConnection(conf);

        //disable Roster; it seems it's not supported by GCM
        Roster roster = Roster.getInstanceFor(connection);  
        roster.setRosterLoadedAtLogin(false);  


        try {
            connection.connect();
            connection.addAsyncStanzaListener(new MyStanzaListener(),new StanzaTypeFilter(Message.class));
            connection.addConnectionListener(cl);
            connection.login(YOUR_PROJECT_ID + "@gcm.googleapis.com", YOUR_API_KEY);
        } catch (SmackException ex) {
            Logger.getLogger(GCMServer.class.getName()).log(Level.SEVERE, null, ex);

        } catch (IOException ex) {
            Logger.getLogger(GCMServer.class.getName()).log(Level.SEVERE, null, ex);
        } catch (XMPPException ex) {
            Logger.getLogger(GCMServer.class.getName()).log(Level.SEVERE, null, ex);
        }

}
类MyStanzaListener:

private static class MyStanzaListener implements StanzaListener{

    @Override
    public void processPacket(Stanza stanza) {
                System.out.println("hei ho, new message: " + stanza.toXML());

                Message incomingMessage = (Message) stanza;
                GcmPacketExtension gcmPacket = (GcmPacketExtension) incomingMessage.getExtension(GCM_NAMESPACE);
                String json = gcmPacket.getJson();

                try {
                    Map<String, Object> jsonObject = (Map<String, Object>) JSONValue.parseWithException(json);

                    Object messageType = jsonObject.get("message_type");
                    String from = (String)jsonObject.get("from");
                    String messageId = (String)jsonObject.get("message_id");
                    String category = (String)jsonObject.get("category");


                    if(messageType == null) {
                        String ack = createJsonAck(from, messageId);
                        System.out.println(ack);
                        send(ack);

                        handleMessage(jsonObject);
                    }
                    else{
                        Logger.getLogger(GCMServer.class.getName()).log(Level.SEVERE, "ERROR IN HANDLING MESSAGE");
                    } 
                } catch (ParseException ex) {
                    Logger.getLogger(GCMServer.class.getName()).log(Level.SEVERE, null, ex);
                }
    }

}
私有静态类MyStanzaListener实现了StanzaListener{
@凌驾
公共无效处理包(节){
System.out.println(“hei-ho,新消息:“+stanza.toXML());
消息输入消息=(消息)节;
gcmpacktextension gcmPacket=(gcmpacktextension)incomingMessage.getExtension(GCM_名称空间);
字符串json=gcmPacket.getJson();
试一试{
Map jsonObject=(Map)JSONValue.parseWithException(json);
objectmessagetype=jsonObject.get(“message_type”);
stringfrom=(String)jsonObject.get(“from”);
String messageId=(String)jsonObject.get(“message_id”);
String category=(String)jsonObject.get(“category”);
if(messageType==null){
字符串ack=createJsonAck(from,messageId);
系统输出打印项次(确认);
发送(确认);
handleMessage(jsonObject);
}
否则{
Logger.getLogger(GCMServer.class.getName()).log(Level.severy,“处理消息时出错”);
} 
}捕获(解析异常){
Logger.getLogger(GCMServer.class.getName()).log(Level.SEVERE,null,ex);
}
}
}
方法HandleMessage、CreateJSONAck、Send:

public static void handleMessage(Map<String, Object> jsonObject) {
      DBConnect db = new DBConnect();

      Map<String, Object> messageData = (Map<String, Object>) jsonObject.get("data");
      String phoneNumber = (String)messageData.get("phoneNumber");
      String text = (String)messageData.get("message");


      db.inBoundMessage(phoneNumber, text);

  }

   public static String createJsonAck(String to, String messageId) {
        Map<String, Object> message = new LinkedHashMap<String, Object>();
        message.put("to", to);
        message.put("message_id", messageId);
        message.put("message_type", "ack");

        return JSONValue.toJSONString(message);
    }

   /**
     * Sends a downstream GCM message.
     */
    public static void send(String jsonRequest) {
        Stanza request = (Stanza)new GcmPacketExtension(jsonRequest).toPacket();
        try {
            connection.sendStanza(request);
        } catch (NotConnectedException ex) {
            Logger.getLogger(GCMServer.class.getName()).log(Level.SEVERE, "ERROR WHILE SENDING: ", ex);
        }
    }
publicstaticvoidhandlemessage(Map-jsonObject){
DBConnect db=新的DBConnect();
Map messageData=(Map)jsonObject.get(“数据”);
字符串phoneNumber=(字符串)messageData.get(“phoneNumber”);
String text=(String)messageData.get(“message”);
db.inBoundMessage(电话号码、文本);
}
公共静态字符串createJsonAck(字符串到,字符串消息ID){
映射消息=新建LinkedHashMap();
信息。放入(“to”,to);
message.put(“message_id”,messageId);
message.put(“message_type”、“ack”);
返回JSONValue.toJSONString(消息);
}
/**
*发送下游GCM消息。
*/
公共静态void发送(字符串jsonRequest){
节请求=(节)新的gcmpacktextension(jsonRequest).toPacket();
试一试{
连接。发送节(请求);
}捕获(未连接异常){
Logger.getLogger(GCMServer.class.getName()).log(Level.severy,“发送时出错:”,ex);
}
}

这是Smack 4.1.3中的一个bug(),在4.1.4中已修复/将修复。有关更多信息,请参阅。

这是Smack 4.1.3中的一个bug(),它已在4.1.4中修复/将在4.1.4中修复。有关更多信息,请参阅。

可能是您的数据包筛选器导致了这种行为?我尝试了数据包筛选器的一些不同变体,但似乎没有人能够解决此问题。作为一种解决方法,我将每个GCM消息发送两次,只捕获第一条消息,其中包含实际信息。目前正在调查此问题,Smack中可能存在一个错误。更多信息请点击“也许你有一个导致这种行为的包过滤器”?我尝试了包过滤器的一些不同变体,但似乎没有人能解决这个问题。作为一种解决方法,我将每个GCM消息发送两次,只捕获第一条消息,其中包含实际信息。目前正在调查此问题,Smack中可能存在一个错误。更多信息请访问