gpt4 book ai didi

xmpp - 使用 Smack 4.1.0 的 GCM XMPP 服务器

转载 作者:行者123 更新时间:2023-12-03 14:41:28 26 4
gpt4 key购买 nike

我正在尝试调整提供的示例 here对于 Smack 4.1.0。并有点困惑。

具体来说,我正在努力理解 GcmPacketExtension 现在应该扩展什么,构造函数应该如何工作以及 Providermanager.addExtensionProvider 应该如何更新以与之配合。

我确定之前一定有人做过这件事,但我找不到任何例子
我似乎只使用文档就在兜圈子。

任何帮助将不胜感激,我相信答案很简单!

当前代码(正在编译但未运行):

    static {

ProviderManager.addExtensionProvider(GCM_ELEMENT_NAME, GCM_NAMESPACE, new ExtensionElementProvider<ExtensionElement>() {
@Override
public DefaultExtensionElement parse(XmlPullParser parser,int initialDepth) throws org.xmlpull.v1.XmlPullParserException,
IOException {
String json = parser.nextText();
return new GcmPacketExtension(json);
}
});
}

和:
private static final class GcmPacketExtension extends DefaultExtensionElement   {

private final String json;

public GcmPacketExtension(String json) {
super(GCM_ELEMENT_NAME, GCM_NAMESPACE);
this.json = json;
}

public String getJson() {
return json;
}

@Override
public String toXML() {
return String.format("<%s xmlns=\"%s\">%s</%s>",
GCM_ELEMENT_NAME, GCM_NAMESPACE,
StringUtils.escapeForXML(json), GCM_ELEMENT_NAME);
}

public Stanza toPacket() {
Message message = new Message();
message.addExtension(this);
return message;
}
}

当前异常:
Exception in thread "main" java.lang.NoClassDefFoundError: de/measite/minidns/DNSCache
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at org.jivesoftware.smack.SmackInitialization.loadSmackClass(SmackInitialization.java:213)
at org.jivesoftware.smack.SmackInitialization.parseClassesToLoad(SmackInitialization.java:193)
at org.jivesoftware.smack.SmackInitialization.processConfigFile(SmackInitialization.java:163)
at org.jivesoftware.smack.SmackInitialization.processConfigFile(SmackInitialization.java:148)
at org.jivesoftware.smack.SmackInitialization.<clinit>(SmackInitialization.java:116)
at org.jivesoftware.smack.SmackConfiguration.getVersion(SmackConfiguration.java:96)
at org.jivesoftware.smack.provider.ProviderManager.<clinit>(ProviderManager.java:121)
at SmackCcsClient.<clinit>(SmackCcsClient.java:58)
Caused by: java.lang.ClassNotFoundException: de.measite.minidns.DNSCache
at java.net.URLClassLoader$1.run(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 10 more

最佳答案

好的,所以我在经过大量阅读和痛苦之后设法让它工作,所以这里是一个非常粗略的服务器实现,实际上可以工作。显然不是为了生产,可以随意纠正任何错误。我并不是说这是最好的方法,但它确实有效。它将发送消息和接收消息,但只在日志中显示它们。

import org.jivesoftware.smack.ConnectionConfiguration.SecurityMode;
import org.jivesoftware.smack.ConnectionListener;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.DefaultExtensionElement;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Stanza;
import org.jivesoftware.smack.filter.StanzaFilter;
import org.jivesoftware.smack.provider.ProviderManager;
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
import org.jivesoftware.smack.util.StringUtils;
import org.json.simple.JSONValue;
import org.json.simple.parser.ParseException;
import org.xmlpull.v1.XmlPullParser;
import org.jivesoftware.smack.*;
import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.provider.ExtensionElementProvider;
import org.jivesoftware.smack.roster.Roster;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;


import javax.net.ssl.SSLSocketFactory;

/**
* Sample Smack implementation of a client for GCM Cloud Connection Server. This
* code can be run as a standalone CCS client.
*
* <p>For illustration purposes only.
*/
public class SmackCcsClient {

private static final Logger logger = Logger.getLogger("SmackCcsClient");

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 = "<your ID here>";
private static final String YOUR_API_KEY = "<your API Key here>"; // your API Key
private static final String YOUR_PHONE_REG_ID = "<your test phone's registration id here>";


static {

ProviderManager.addExtensionProvider(GCM_ELEMENT_NAME, GCM_NAMESPACE, new ExtensionElementProvider<ExtensionElement>() {
@Override
public DefaultExtensionElement parse(XmlPullParser parser,int initialDepth) throws org.xmlpull.v1.XmlPullParserException,
IOException {
String json = parser.nextText();
return new GcmPacketExtension(json);
}
});
}

private XMPPTCPConnection connection;

/**
* Indicates whether the connection is in draining state, which means that it
* will not accept any new downstream messages.
*/
protected volatile boolean connectionDraining = false;

/**
* Sends a downstream message to GCM.
*
* @return true if the message has been successfully sent.
*/
public boolean sendDownstreamMessage(String jsonRequest) throws
NotConnectedException {
if (!connectionDraining) {
send(jsonRequest);
return true;
}
logger.info("Dropping downstream message since the connection is draining");
return false;
}

/**
* Returns a random message id to uniquely identify a message.
*
* <p>Note: This is generated by a pseudo random number generator for
* illustration purpose, and is not guaranteed to be unique.
*/
public String nextMessageId() {
return "m-" + UUID.randomUUID().toString();
}

/**
* Sends a packet with contents provided.
*/
protected void send(String jsonRequest) throws NotConnectedException {
Stanza request = new GcmPacketExtension(jsonRequest).toPacket();
connection.sendStanza(request);
}

/**
* Handles an upstream data message from a device application.
*
* <p>This sample echo server sends an echo message back to the device.
* Subclasses should override this method to properly process upstream messages.
*/
protected void handleUpstreamMessage(Map<String, Object> jsonObject) {
// PackageName of the application that sent this message.
String category = (String) jsonObject.get("category");
String from = (String) jsonObject.get("from");
@SuppressWarnings("unchecked")
Map<String, String> payload = (Map<String, String>) jsonObject.get("data");
payload.put("ECHO", "Application: " + category);

// Send an ECHO response back
String echo = createJsonMessage(from, nextMessageId(), payload,
"echo:CollapseKey", null, false);

try {
sendDownstreamMessage(echo);
} catch (NotConnectedException e) {
logger.log(Level.WARNING, "Not connected anymore, echo message is not sent", e);
}

}

/**
* Handles an ACK.
*
* <p>Logs a INFO message, but subclasses could override it to
* properly handle ACKs.
*/
protected void handleAckReceipt(Map<String, Object> jsonObject) {
String messageId = (String) jsonObject.get("message_id");
String from = (String) jsonObject.get("from");
logger.log(Level.INFO, "handleAckReceipt() from: " + from + ",messageId: " + messageId);
}

/**
* Handles a NACK.
*
* <p>Logs a INFO message, but subclasses could override it to
* properly handle NACKs.
*/
protected void handleNackReceipt(Map<String, Object> jsonObject) {
String messageId = (String) jsonObject.get("message_id");
String from = (String) jsonObject.get("from");
logger.log(Level.INFO, "handleNackReceipt() from: " + from + ",messageId: " + messageId);
}

protected void handleControlMessage(Map<String, Object> jsonObject) {
logger.log(Level.INFO, "handleControlMessage(): " + jsonObject);
String controlType = (String) jsonObject.get("control_type");
if ("CONNECTION_DRAINING".equals(controlType)) {
connectionDraining = true;
} else {
logger.log(Level.INFO, "Unrecognized control type: %s. This could happen if new features are " + "added to the CCS protocol.",
controlType);
}
}

/**
* Creates a JSON encoded GCM message.
*
* @param to RegistrationId of the target device (Required).
* @param messageId Unique messageId for which CCS sends an
* "ack/nack" (Required).
* @param payload Message content intended for the application. (Optional).
* @param collapseKey GCM collapse_key parameter (Optional).
* @param timeToLive GCM time_to_live parameter (Optional).
* @param delayWhileIdle GCM delay_while_idle parameter (Optional).
* @return JSON encoded GCM message.
*/
public static String createJsonMessage(String to, String messageId,
Map<String, String> payload, String collapseKey, Long timeToLive,
Boolean delayWhileIdle) {
Map<String, Object> message = new HashMap<String, Object>();
message.put("to", to);
if (collapseKey != null) {
message.put("collapse_key", collapseKey);
}
if (timeToLive != null) {
message.put("time_to_live", timeToLive);
}
if (delayWhileIdle != null && delayWhileIdle) {
message.put("delay_while_idle", true);
}
message.put("message_id", messageId);
message.put("data", payload);
return JSONValue.toJSONString(message);
}

/**
* Creates a JSON encoded ACK message for an upstream message received
* from an application.
*
* @param to RegistrationId of the device who sent the upstream message.
* @param messageId messageId of the upstream message to be acknowledged to CCS.
* @return JSON encoded ack.
*/
protected static String createJsonAck(String to, String messageId) {
Map<String, Object> message = new HashMap<String, Object>();
message.put("message_type", "ack");
message.put("to", to);
message.put("message_id", messageId);
return JSONValue.toJSONString(message);
}

/**
* Connects to GCM Cloud Connection Server using the supplied credentials.
*
* @param senderId Your GCM project number
* @param apiKey API Key of your project
*/
public void connect(String senderId, String apiKey)
throws XMPPException, IOException, SmackException {
XMPPTCPConnectionConfiguration config =
XMPPTCPConnectionConfiguration.builder()
.setServiceName(GCM_SERVER)
.setHost(GCM_SERVER)
.setCompressionEnabled(false)
.setPort(GCM_PORT)
.setConnectTimeout(30000)
.setSecurityMode(SecurityMode.disabled)
.setSendPresence(false)
.setSocketFactory(SSLSocketFactory.getDefault())
.build();

connection = new XMPPTCPConnection(config);

//disable Roster as I don't think this is supported by GCM
Roster roster = Roster.getInstanceFor(connection);
roster.setRosterLoadedAtLogin(false);

logger.info("Connecting...");
connection.connect();

connection.addConnectionListener(new LoggingConnectionListener());

// Handle incoming packets
connection.addAsyncStanzaListener(new MyStanzaListener() , new MyStanzaFilter() );

// Log all outgoing packets
connection.addPacketInterceptor(new MyStanzaInterceptor(), new MyStanzaFilter() );

connection.login(senderId + "@gcm.googleapis.com" , apiKey);

}

private class MyStanzaFilter implements StanzaFilter
{

@Override
public boolean accept(Stanza arg0) {
// TODO Auto-generated method stub
if(arg0.getClass() == Stanza.class )
return true;
else
{
if(arg0.getTo()!= null)
if(arg0.getTo().startsWith(YOUR_PROJECT_ID) )
return true;

}

return false;
}
}

private class MyStanzaListener implements StanzaListener{

@Override
public void processPacket(Stanza packet) {
logger.log(Level.INFO, "Received: " + packet.toXML());
Message incomingMessage = (Message) packet;
GcmPacketExtension gcmPacket =
(GcmPacketExtension) incomingMessage.
getExtension(GCM_NAMESPACE);
String json = gcmPacket.getJson();
try {
@SuppressWarnings("unchecked")
Map<String, Object> jsonObject =
(Map<String, Object>) JSONValue.
parseWithException(json);

// present for "ack"/"nack", null otherwise
Object messageType = jsonObject.get("message_type");

if (messageType == null) {
// Normal upstream data message
handleUpstreamMessage(jsonObject);

// Send ACK to CCS
String messageId = (String) jsonObject.get("message_id");
String from = (String) jsonObject.get("from");
String ack = createJsonAck(from, messageId);
send(ack);
} else if ("ack".equals(messageType.toString())) {
// Process Ack
handleAckReceipt(jsonObject);
} else if ("nack".equals(messageType.toString())) {
// Process Nack
handleNackReceipt(jsonObject);
} else if ("control".equals(messageType.toString())) {
// Process control message
handleControlMessage(jsonObject);
} else {
logger.log(Level.WARNING,
"Unrecognized message type (%s)",
messageType.toString());
}
} catch (ParseException e) {
logger.log(Level.SEVERE, "Error parsing JSON " + json, e);
} catch (Exception e) {
logger.log(Level.SEVERE, "Failed to process packet", e);
}
}

}

private class MyStanzaInterceptor implements StanzaListener
{
@Override
public void processPacket(Stanza packet) {
logger.log(Level.INFO, "Sent: {0}", packet.toXML());
}

}


public static void main(String[] args) throws Exception {

SmackCcsClient ccsClient = new SmackCcsClient();

ccsClient.connect(YOUR_PROJECT_ID, YOUR_API_KEY);

// Send a sample hello downstream message to a device.
String messageId = ccsClient.nextMessageId();
Map<String, String> payload = new HashMap<String, String>();
payload.put("Message", "Ahha, it works!");
payload.put("CCS", "Dummy Message");
payload.put("EmbeddedMessageId", messageId);
String collapseKey = "sample";
Long timeToLive = 10000L;
String message = createJsonMessage(YOUR_PHONE_REG_ID, messageId, payload,
collapseKey, timeToLive, true);

ccsClient.sendDownstreamMessage(message);
logger.info("Message sent.");

//crude loop to keep connection open for receiving messages
while(true)
{;}
}

/**
* XMPP Packet Extension for GCM Cloud Connection Server.
*/
private static final class GcmPacketExtension extends DefaultExtensionElement {

private final String json;

public GcmPacketExtension(String json) {
super(GCM_ELEMENT_NAME, GCM_NAMESPACE);
this.json = json;
}

public String getJson() {
return json;
}

@Override
public String toXML() {
return String.format("<%s xmlns=\"%s\">%s</%s>",
GCM_ELEMENT_NAME, GCM_NAMESPACE,
StringUtils.escapeForXML(json), GCM_ELEMENT_NAME);
}

public Stanza toPacket() {
Message message = new Message();
message.addExtension(this);
return message;
}
}

private static final class LoggingConnectionListener
implements ConnectionListener {

@Override
public void connected(XMPPConnection xmppConnection) {
logger.info("Connected.");
}


@Override
public void reconnectionSuccessful() {
logger.info("Reconnecting..");
}

@Override
public void reconnectionFailed(Exception e) {
logger.log(Level.INFO, "Reconnection failed.. ", e);
}

@Override
public void reconnectingIn(int seconds) {
logger.log(Level.INFO, "Reconnecting in %d secs", seconds);
}

@Override
public void connectionClosedOnError(Exception e) {
logger.info("Connection closed on error.");
}

@Override
public void connectionClosed() {
logger.info("Connection closed.");
}

@Override
public void authenticated(XMPPConnection arg0, boolean arg1) {
// TODO Auto-generated method stub

}
}
}


我还导入了以下外部 JAR:
(它们可能不是全部必需的,但大多数是必需的!)

json-simple-1.1.1.jar

jxmpp-core-0.4.1.jar

jxmpp-util-cache-0.5.0-alpha2.jar

minidns-0.1.3.jar

commons-logging-1.2.jar

httpclient-4.3.4.jar

xpp3_xpath-1.1.4c.jar

xpp3-1.1.4c.jar

对于客户端,我使用了 GCM 示例项目 here . (滚动到页面底部的源链接)

希望这可以帮助某人!

[2015 年 10 月 23 日] 我正在为使用 Gradle 的其他人编辑这个答案......下面是我编译它所需的所有依赖项(添加到 build.gradle 文件的底部)。
dependencies {
compile 'com.googlecode.json-simple:json-simple:1.1.1'
compile 'org.igniterealtime.smack:smack-java7:4.1.4'
compile 'org.igniterealtime.smack:smack-tcp:4.1.4'
compile 'org.igniterealtime.smack:smack-im:4.1.4'
compile 'org.jxmpp:jxmpp-core:0.5.0-alpha6'
compile 'org.jxmpp:jxmpp-util-cache:0.5.0-alpha6'
}

关于xmpp - 使用 Smack 4.1.0 的 GCM XMPP 服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30056939/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com