首先是android 端使用到的jar包
下面是自己使用的工具类,需要的注意事项有
1.首先是先保证和服务器的连接,这里使用的端口是5222,可以不用配证书(tls/ssl)
2.就是设置主机名的时候要和服务器端的主机名保持一致,否则的话在注册新账号的时候会出现异常 bad-request - modify
3.smack 4.34的api,官方文档地址http://download.igniterealtime.org/smack/docs/latest/javadoc/org/jivesoftware/smack/XMPPConnection.html
public class SmarkUtil {
public static final StringSERVER_NAME ="127.0.0.1";//主机名和服务器上保持一致,否则会出现异常
public static final StringSERVER_IP ="192.168.2.223";//ip
public static final int PORT =5222;//端口 使用5222端口,其它端口需要配置证书或者绑定
private static SmarkUtilxmppConnection =new SmarkUtil();
private XMPPTCPConnectionconnection;
public SmarkUtil() {
getConnection();
}
/**
* 单例模式
* @return
*/
public synchronized static SmarkUtil getInstance() {
return xmppConnection;
}
/**
* 创建连接
*/
public AbstractXMPPConnection getConnection() {
if (connection ==null) {
// 开线程打开连接,避免在主线程里面执行HTTP请求
// Caused by: android.os.NetworkOnMainThreadException
new Thread(new Runnable() {
@Override
public void run() {
openConnection();
}
}).start();
}
return connection;
}
/**
* 判断是否已连接
*/
public boolean checkConnection() {
return null !=connection &&connection.isConnected();
}
/**
* 打开连接
*/
public boolean openConnection() {
try {
if (null ==connection || !connection.isAuthenticated()) {
SmackConfiguration.DEBUG =true;
XMPPTCPConnectionConfiguration.Builder config = XMPPTCPConnectionConfiguration.builder();
//设置openfire主机IP
config.setHostAddress(InetAddress.getByName(SERVER_IP));
//config.setHost(SERVER_IP);
//设置openfire服务器名称
config.setXmppDomain(SERVER_NAME);
//设置端口号:默认5222
config.setPort(PORT);
//禁用SSL连接
config.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled).setCompressionEnabled(false);
//设置离线状态
config.setSendPresence(false);
//设置开启压缩,可以节省流量
config.setCompressionEnabled(true);
//需要经过同意才可以添加好友
Roster.setDefaultSubscriptionMode(Roster.SubscriptionMode.manual);
// 将相应机制隐掉
//SASLAuthentication.blacklistSASLMechanism("SCRAM-SHA-1");
//SASLAuthentication.blacklistSASLMechanism("DIGEST-MD5");
connection =new XMPPTCPConnection(config.build());
connection.connect();// 连接到服务器
return true;
}
}catch (XMPPException | SmackException | IOException | InterruptedException xe) {
xe.printStackTrace();
connection =null;
}
return false;
}
/**
* 登录
*
* @param account 登录帐号
* @param password 登录密码
* @return true登录成功
*/
public boolean login(String account, String password, ConnectionListener connectionListener) {
try {
if (getConnection() ==null){
Log.i("sun","连接失败");
return false;
}
// 添加连接监听
getConnection().addConnectionListener(connectionListener);
Log.i("sun","开始登录操作");
getConnection().login(account, password);
return true;
}catch (XMPPException | IOException | SmackException | InterruptedException xe) {
xe.printStackTrace();
}
return false;
}
/**
* 创建一个新用户
*
* @param userName
* 用户名
* @param password
* 密码
* @param attr
* 用户资料
* @return
* @throws Exception
*/
public boolean registerAccount(String userName, String password, Map attr)throws Exception {
AccountManager manager = AccountManager.getInstance(connection);
manager.sensitiveOperationOverInsecureConnection(true);
Localpart l_username = Localpart.from(userName);
if (attr ==null) {
manager.createAccount(l_username, password);
}else {
manager.createAccount(l_username, password, attr);
}
return true;
}
/**
* 修改当前登陆用户密码
*
* @param password
* @return
* @throws Exception
*/
public boolean changePassword(String password)throws Exception {
AccountManager manager = AccountManager.getInstance(connection);
manager.sensitiveOperationOverInsecureConnection(true);
manager.changePassword(password);
return true;
}
/**
* 删除当前登录用户
*
* @return
* @throws Exception
*/
public boolean deleteAccount()throws Exception {
AccountManager manager = AccountManager.getInstance(connection);
manager.sensitiveOperationOverInsecureConnection(true);
manager.deleteAccount();
return true;
}
/**
* 获取用户属性名称
*
* @return
* @throws Exception
*/
public List getAccountInfo()throws Exception {
List list =new ArrayList();
AccountManager manager = AccountManager.getInstance(connection);
manager.sensitiveOperationOverInsecureConnection(true);
Set set = manager.getAccountAttributes();
list.addAll(set);
return list;
}
/**
* 获取所有组
*
* @return
* @throws Exception
*/
public List getGroups()throws Exception {
List grouplist =new ArrayList();
Roster roster = Roster.getInstanceFor(connection);
Collection rosterGroup = roster.getGroups();
Iterator i = rosterGroup.iterator();
while (i.hasNext()) {
grouplist.add(i.next());
}
return grouplist;
}
/**
* 添加分组
*
* @param groupName
* @return
* @throws Exception
*/
public boolean addGroup(String groupName)throws Exception {
Roster roster = Roster.getInstanceFor(connection);
roster.createGroup(groupName);
return true;
}
/**
* 获取指定分组的好友
*
* @param groupName
* @return
* @throws Exception
*/
public List getEntriesByGroup(String groupName)throws Exception {
Roster roster = Roster.getInstanceFor(connection);
List Entrieslist =new ArrayList();
RosterGroup rosterGroup = roster.getGroup(groupName);
Collection rosterEntry = rosterGroup.getEntries();
Iterator i = rosterEntry.iterator();
while (i.hasNext()) {
Entrieslist.add(i.next());
}
return Entrieslist;
}
/**
* 获取全部好友
*
* @return
* @throws Exception
*/
public List getAllEntries()throws Exception {
if(connection ==null){
Log.i("sun","获取好友时连接为空");
return null;
}
Roster roster = Roster.getInstanceFor(connection);
List Entrieslist =new ArrayList();
Collection rosterEntry = roster.getEntries();
Iterator i = rosterEntry.iterator();
while (i.hasNext()) {
Entrieslist.add(i.next());
}
return Entrieslist;
}
/**
* 获取用户VCard信息
*
* @param userName
* @return
* @throws Exception
*/
public VCard getUserVCard(String userName)throws Exception {
VCard vcard =new VCard();
EntityBareJid jid = JidCreate.entityBareFrom(userName +"@" +this.SERVER_NAME);
vcard.load(connection, jid);
return vcard;
}
/**
* 添加好友 无分组
*
* @param userName
* @param name
* @return
* @throws Exception
*/
public boolean addUser(String userName, String name)throws Exception {
Roster roster = Roster.getInstanceFor(connection);
EntityBareJid jid = JidCreate.entityBareFrom(userName +"@" +this.SERVER_NAME);
roster.createEntry(jid, name,null);
return true;
}
/**
* 添加好友 有分组
*
* @param userName
* @param name
* @param groupName
* @return
* @throws Exception
*/
public boolean addUser(String userName, String name, String groupName)throws Exception {
Roster roster = Roster.getInstanceFor(connection);
EntityBareJid jid = JidCreate.entityBareFrom(userName +"@" +this.SERVER_NAME);
roster.createEntry(jid, name,new String[] { groupName });
return true;
}
/**
* 删除好友
*
* @param userName
* @return
* @throws Exception
*/
public boolean removeUser(String userName)throws Exception {
Roster roster = Roster.getInstanceFor(connection);
EntityBareJid jid = JidCreate.entityBareFrom(userName +"@" +SERVER_NAME);
RosterEntry entry = roster.getEntry(jid);
System.out.println("删除好友:" + userName);
System.out.println("User." + roster.getEntry(jid) ==null);
roster.removeEntry(entry);
return true;
}
/**
* 创建发布订阅节点
*
* @param nodeId
* @return
* @throws Exception
*/
public boolean createPubSubNode(String nodeId)throws Exception {
PubSubManager mgr = PubSubManager.getInstance(connection);
// Create the node
LeafNode leaf = mgr.createNode(nodeId);
ConfigureForm form =new ConfigureForm(DataForm.Type.submit);
form.setAccessModel(AccessModel.open);
form.setDeliverPayloads(true);
form.setNotifyRetract(true);
form.setPersistentItems(true);
form.setPublishModel(PublishModel.open);
form.setMaxItems(10000000);// 设置最大的持久化消息数量
leaf.sendConfigurationForm(form);
return true;
}
/**
* 创建发布订阅节点
*
* @param nodeId
* @param title
* @return
* @throws Exception
*/
public boolean createPubSubNode(String nodeId, String title)throws Exception {
PubSubManager mgr = PubSubManager.getInstance(connection);
// Create the node
LeafNode leaf = mgr.createNode(nodeId);
ConfigureForm form =new ConfigureForm(DataForm.Type.submit);
form.setAccessModel(AccessModel.open);
form.setDeliverPayloads(true);
form.setNotifyRetract(true);
form.setPersistentItems(true);
form.setPublishModel(PublishModel.open);
form.setTitle(title);
form.setBodyXSLT(nodeId);
form.setMaxItems(10000000);// 设置最大的持久化消息数量
form.setMaxPayloadSize(1024*12);//最大的有效载荷字节大小
leaf.sendConfigurationForm(form);
return true;
}
public boolean deletePubSubNode(String nodeId)throws Exception {
PubSubManager mgr = PubSubManager.getInstance(connection);
mgr.deleteNode(nodeId);
return true;
}
/**
* 发布消息
*
* @param nodeId
* 主题ID
* @param eventId
* 事件ID
* @param messageType
* 消息类型:publish(发布)/receipt(回执)/state(状态)
* @param messageLevel
* 0/1/2
* @param messageSource
* 消息来源
* @param messageCount
* 消息数量
* @param packageCount
* 总包数
* @param packageNumber
* 当前包数
* @param createTime
* 创建时间 2018-06-07 09:43:06
* @param messageContent
* 消息内容
* @return
* @throws Exception
*/
public boolean publish(String nodeId, String eventId, String messageType,int messageLevel, String messageSource,
int messageCount,int packageCount,int packageNumber, String createTime, String messageContent)
throws Exception {
if (messageContent.length() >1024 *10) {
throw new Exception("消息内容长度超出1024*10,需要进行分包发布");
}
PubSubManager mgr = PubSubManager.getInstance(connection);
LeafNode node =null;
node = mgr.getNode(nodeId);
StringBuffer xml =new StringBuffer();
xml.append("
xml.append("
xml.append("
xml.append("
xml.append("
xml.append("
xml.append("
xml.append("
xml.append("
xml.append("
xml.append("
xml.append("");
SimplePayload payload =new SimplePayload("pubmessage","pub:message", xml.toString().toLowerCase());
PayloadItem item =new PayloadItem(System.currentTimeMillis() +"", payload);
node.publish(item);
return true;
}
/**
* 订阅主题
*
* @param nodeId
* @return
* @throws Exception
*/
public boolean subscribe(String nodeId,String userName)throws Exception {
PubSubManager mgr = PubSubManager.getInstance(connection);
// Get the node
LeafNode node = mgr.getNode(nodeId);
SubscribeForm subscriptionForm =new SubscribeForm(DataForm.Type.submit);
subscriptionForm.setDeliverOn(true);
subscriptionForm.setDigestFrequency(5000);
subscriptionForm.setDigestOn(true);
subscriptionForm.setIncludeBody(true);
List subscriptions = node.getSubscriptions();
boolean flag =true;
for (Subscription s : subscriptions) {
if (s.getJid().toString().toLowerCase().equals(connection.getUser().asEntityBareJidString().toLowerCase())) {// 已订阅过
flag =false;
break;
}
}
if (flag) {// 未订阅,开始订阅
node.subscribe(userName +"@" +this.SERVER_NAME, subscriptionForm);
}
return true;
}
/**
* 获取订阅的全部主题
*
* @return
* @throws Exception
*/
public List querySubscriptions()throws Exception {
PubSubManager mgr = PubSubManager.getInstance(connection);
List subs = mgr.getSubscriptions();
return subs;
}
/**
* 获取订阅节点的配置信息
*
* @param nodeId
* @return
* @throws Exception
*/
public ConfigureForm getConfig(String nodeId)throws Exception {
PubSubManager mgr = PubSubManager.getInstance(connection);
LeafNode node = mgr.getNode(nodeId);
ConfigureForm config = node.getNodeConfiguration();
return config;
}
/**
* 获取订阅主题的全部历史消息
*
* @return
* @throws Exception
*/
public List queryHistoryMeassage()throws Exception {
List result =new ArrayList();
PubSubManager mgr = PubSubManager.getInstance(connection);
List subs = mgr.getSubscriptions();
if (subs !=null && subs.size() >0) {
for (Subscription sub : subs) {
String nodeId = sub.getNode();
LeafNode node = mgr.getNode(nodeId);
List list = node.getItems();
result.addAll(list);
}
}
/*
* for (Item item : result) { System.out.println(item.toXML()); }
*/
return result;
}
/**
* 获取指定主题的全部历史消息
*
* @return
* @throws Exception
*/
public List queryHistoryMeassage(String nodeId)throws Exception {
List result =new ArrayList();
PubSubManager mgr = PubSubManager.getInstance(connection);
LeafNode node = mgr.getNode(nodeId);
List list = node.getItems();
result.addAll(list);
/*
* for (Item item : result) { System.out.println(item.toXML()); }
*/
return result;
}
/**
* 获取指定主题指定数量的历史消息
*
* @param nodeId
* @param num
* @return
* @throws Exception
*/
public List queryHistoryMeassage(String nodeId,int num)throws Exception {
List result =new ArrayList();
PubSubManager mgr = PubSubManager.getInstance(connection);
LeafNode node = mgr.getNode(nodeId);
List list = node.getItems(num);
result.addAll(list);
/*
* for (Item item : result) { System.out.println(item.toXML()); }
*/
return result;
}
/**
* 向指定用户发送消息
*
* @param username
* @param message
* @throws Exception
*/
public void sendMessage(String username, String message)throws Exception {
ChatManager chatManager = ChatManager.getInstanceFor(connection);
EntityBareJid jid = JidCreate.entityBareFrom(username+"@" +this.SERVER_NAME);
Chat chat = chatManager.createChat(jid);
Message newMessage =new Message();
newMessage.setBody(message);
chat.sendMessage(newMessage);
}
/**
* 添加聊天消息监听
*
* @param chatManagerListener
* @throws Exception
*/
public void addChatMessageListener(ChatManagerListener chatManagerListener)throws Exception {
ChatManager chatManager = ChatManager.getInstanceFor(connection);
chatManager.addChatListener(chatManagerListener);
}
/**
* 断开连接
*/
public void close() {
connection.disconnect();
}
/**
* 更改用户状态
*/
public void setPresence(int code) {
XMPPConnection con = getConnection();
if (con ==null)
return;
Presence presence;
try {
switch (code) {
case 0:
presence =new Presence(Presence.Type.available);
con.sendStanza(presence);
Log.v("state","设置在线");
break;
case 1:
presence =new Presence(Presence.Type.available);
presence.setMode(Presence.Mode.chat);
con.sendStanza(presence);
Log.v("state","设置Q我吧");
break;
case 2:
presence =new Presence(Presence.Type.available);
presence.setMode(Presence.Mode.dnd);
con.sendStanza(presence);
Log.v("state","设置忙碌");
break;
case 3:
presence =new Presence(Presence.Type.available);
presence.setMode(Presence.Mode.away);
con.sendStanza(presence);
Log.v("state","设置离开");
break;
case 4:
// Roster roster = con.getRoster();
// Collection entries = roster.getEntries();
// for (RosterEntry entry : entries) {
// presence = new Presence(Presence.Type.unavailable);
// presence.setPacketID(Packet.ID_NOT_AVAILABLE);
// presence.setFrom(con.getUser());
// presence.setTo(entry.getUser());
// con.sendPacket(presence);
// Log.v("state", presence.toXML());
// }
// // 向同一用户的其他客户端发送隐身状态
// presence = new Presence(Presence.Type.unavailable);
// presence.setPacketID(Packet.ID_NOT_AVAILABLE);
// presence.setFrom(con.getUser());
// presence.setTo(StringUtils.parseBareAddress(con.getUser()));
// con.sendStanza(presence);
// Log.v("state", "设置隐身");
// break;
case 5:
presence =new Presence(Presence.Type.unavailable);
con.sendStanza(presence);
Log.v("state","设置离线");
break;
default:
break;
}
}catch (SmackException.NotConnectedException | InterruptedException e) {
e.printStackTrace();
}
}
}
至于具体的实现,大家就看着文档自己搞吧