简体   繁体   中英

Not able receiving all messages, only every second, from Google Cloud Messaging with CCS using Smack

I'm trying to set up a connection to Google Cloud Messaging via Cloud Connection Server (XMPP-Connection) using Smack 4.1.2. I was already able to establish connection and receive incoming messages. But my problem is the StanzaListener isn't triggered by each message (but only every second one). The Smack Debugging Console shows all "Raw Received Packets", so the sending from Device-to-Cloud works for each message.

Thank you for your help!

Here's my code from the Server App:

My Class GCMServer with Main:

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);
        }

}

Class 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);
                }
    }

}

Methods 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);
        }
    }

This is a bug ( SMACK-695 ) in Smack 4.1.3, which is fixed/will be fixed in 4.1.4. For more information see https://community.igniterealtime.org/thread/56610 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM