我正在尝试使用Smack 4.1.2通过Cloud Connection Server(XMPP-Connection)建立与Google Cloud Messaging的连接。 我已经能够建立连接并接收传入的消息。但我的问题是StanzaListener不是由每条消息触发的(但只是每一秒消息)。 Smack调试控制台显示所有“原始接收数据包”,因此从设备到云的发送适用于每条消息。
感谢您的帮助!
这是来自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);
}
}
}
方法HandleMessage,CreateJSONAck,发送:
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);
}
}
答案 0 :(得分:0)
这是Smack 4.1.3中的一个错误(SMACK-695),它已修复/将在4.1.4中修复。有关详细信息,请参阅https://community.igniterealtime.org/thread/56610。