java中的XMPP服务器没有收到来自GCM服务器的所有消息

Posted

技术标签:

【中文标题】java中的XMPP服务器没有收到来自GCM服务器的所有消息【英文标题】:XMPP server in java does not receive all messages from GCM server 【发布时间】:2017-04-15 19:03:51 【问题描述】:

我已经使用 Smack 库实现了 XMPP 服务器,我的服务器从 Google Cloud Messaging 服务器(现在是 Firebase)获取消息,但问题是当我从 android 向 gcm 服务器一一发送消息时,我的 XMPP 服务器接收只有第一条消息和第二条被截获,(我只能看到有消息的通知

<message id="gQaM0-6"><gcm xmlns="google:mobile:data">"message_type":"ack","message_id":"0","to":"eVtypIWW7Q8:APA91bH5oU0AC3zyuCAWVYkMzoGQeIiGe71c2BL4lE5uFHRfB3iPXtD-qIJDmJZ3ySsPDi0VhkKl0Cz3XZG7rWa1Ca7pX9yQqzWSMXBiGK4SEO4Q-Owfr45E_VBJMrXqsSziuJhek"</gcm></message>

但我没有这方面的数据 我在方法 void processPacket(Packet packet) 中收到的第一条消息 这是XMPP服务器的完整代码:

public class XMPPServer implements PacketListener 

    private static XMPPServer sInstance = null;
    private XMPPConnection connection;
    private ConnectionConfiguration config;
    private String mApiKey = null;
    private String mProjectId = null;
    private boolean mDebuggable = false;
    private String fcmServerUsername = null;

    public static XMPPServer getInstance() 
        if (sInstance == null) 
            throw new IllegalStateException("You have to prepare the client first");
        
        return sInstance;
    

    public static XMPPServer prepareClient(String projectId, String apiKey, boolean debuggable) 
        synchronized (XMPPServer.class) 
            if (sInstance == null) 
                sInstance = new XMPPServer(projectId, apiKey, debuggable);
            
        
        return sInstance;
    

    private XMPPServer(String projectId, String apiKey, boolean debuggable) 
        this();
        mApiKey = apiKey;
        mProjectId = projectId;
        mDebuggable = debuggable;
        fcmServerUsername = mProjectId + "@" + Util.FCM_SERVER_CONNECTION;
    

    private XMPPServer() 
        // Add GcmPacketExtension
        ProviderManager.getInstance().addExtensionProvider(Util.FCM_ELEMENT_NAME, Util.FCM_NAMESPACE,
                new PacketExtensionProvider() 

                    @Override
                    public PacketExtension parseExtension(XmlPullParser parser) throws Exception 
                        String json = parser.nextText();
                        GcmPacketExtension packet = new GcmPacketExtension(json);
                        return packet;
                    
                );
    

    /**
     * Connects to FCM Cloud Connection Server using the supplied credentials
     */
    public void connect() throws XMPPException 
        config = new ConnectionConfiguration(Util.FCM_SERVER, Util.FCM_PORT);
        config.setSecurityMode(SecurityMode.enabled);
        config.setReconnectionAllowed(true);
        config.setSocketFactory(SSLSocketFactory.getDefault());
        // Launch a window with info about packets sent and received
        config.setDebuggerEnabled(mDebuggable);

        connection = new XMPPConnection(config);
        connection.connect();

        connection.addConnectionListener(new ConnectionListener() 
                //a few overrided methods
        );
        // Handle incoming packets (the class implements the PacketListener)
        connection.addPacketListener(this, new PacketTypeFilter(Message.class));

        // Second message without data I get in this method (1)
        connection.addPacketWriterInterceptor(new PacketInterceptor() 
            @Override
            public void interceptPacket(Packet packet) 
                System.out.println("INTERCEPT PACKAGE: " + packet.toXML());
            
        , new PacketTypeFilter(Message.class));
        connection.login(fcmServerUsername, mApiKey);
    
    /**
     * Normal message with my data I get in this method (2)
     */
    @SuppressWarnings("unchecked")
    @Override
    public void processPacket(Packet packet) 
        Message incomingMessage = (Message) packet;
        GcmPacketExtension gcmPacket = (GcmPacketExtension) incomingMessage.getExtension(Util.FCM_NAMESPACE);
        String json = gcmPacket.getJson();
        System.out.println("Message : " + json);
     

代码差不多全了,最重要的部分我用(1)和(2)标注了,(使用搜索快速查找) 为什么我只能收到包含我的数据的第一条消息? 为什么第二条消息会发送到 PacketInterceptor (mark (1) ) ?

【问题讨论】:

【参考方案1】:

如果您使用的是Firebase Cloud Messaging(FCM),请检查您的应用服务器是否连接到以下端点:

// Production
fcm-xmpp.googleapis.com:5235

// Testing
fcm-xmpp.googleapis.com:5236

除此之外,您可能还想查看Downstream messages,其中提到一旦建立了 XMPP 连接,CCS 和您的服务器就会使用普通的 XMPP &lt;message&gt; 节来回发送 JSON 编码的消息。 &lt;message&gt; 的正文必须是:

<gcm xmlns:google:mobile:data>
    JSON payload
</gcm>

另外,请注意常规 FCM 消息的 JSON 有效负载中的异常。访问给定的链接以获取更多信息。

这些相关的 SO 帖子也可能有所帮助:

FCM receive message Issue Send FCM messages from server side to android device

【讨论】:

嘿,谢谢你的回答!我使用 FCM_PORT = 5236,我会尝试 5235,也许这会改变情况

以上是关于java中的XMPP服务器没有收到来自GCM服务器的所有消息的主要内容,如果未能解决你的问题,请参考以下文章

在重试同一条消息之前,GCM CCS 等待 XMPP 服务器的确认多长时间?

如何通过xmpp gcm将ack从android应用程序发送到服务器

我应该如何在 java 上部署 XMPP 服务器 GCM 以便 GCM 可以访问它并发送消息?

为啥我的 XMPP 客户端重新发送消息?

Android - GCM 在打开应用程序时收到来自 gcm 的通知

如何构建对 GCM 云连接服务器 (XMPP) 的通知密钥请求?