Java 无法通过使用Smack的CCS接收来自Google云消息的所有消息(仅每秒一次)
我正在尝试使用Smack 4.1.2通过云连接服务器(XMPP连接)与Google云消息建立连接。 我已经能够建立连接并接收传入消息。但我的问题是StanzaListener并不是由每条消息触发的(而只是每秒钟一条)。Smack调试控制台显示所有“原始接收数据包”,因此从设备到云的发送对每条消息都有效 谢谢你的帮助 以下是我在服务器应用程序中的代码: My Class GCMServer与主服务器: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
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中可能存在一个错误。更多信息请访问