本文属早期从网络搜集的文章,实践证明:一天时间不能开发出自己的聊天工具!但是可以用openfire+spark搭建一套属于自己的聊天系统。相关文章:openfire学习之二 使用openfire + spark 搭建聊天系统
Openfire 采用Java开发,开源的实时协作(RTC)服务器基于XMPP(Jabber)协议。Openfire安装和使用都非常简单,并利用Web进行管理。单台服务器可支持上万并发用户。
服务端可以用本服务器测试,地址:www.ithtw.com。如果想自己搭可在本博客其它XMPP文章找到相关搭建资料。
实现了用户注册,登录,添加好友,聊天核心功能。可正常聊天!
核心通讯代码:
package com.lee.xqq.control;
import java.io.ByteArrayInputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import org.jivesoftware.smack.Connection;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.ConnectionCreationListener;
import org.jivesoftware.smack.ConnectionListener;
import org.jivesoftware.smack.PacketCollector;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.RosterEntry;
import org.jivesoftware.smack.RosterGroup;
import org.jivesoftware.smack.SmackConfiguration;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.filter.AndFilter;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.filter.PacketIDFilter;
import org.jivesoftware.smack.filter.PacketTypeFilter;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.packet.Presence.Type;
import org.jivesoftware.smack.packet.Registration;
import org.jivesoftware.smack.provider.PrivacyProvider;
import org.jivesoftware.smack.provider.ProviderManager;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smackx.Form;
import org.jivesoftware.smackx.GroupChatInvitation;
import org.jivesoftware.smackx.PrivateDataManager;
import org.jivesoftware.smackx.ReportedData;
import org.jivesoftware.smackx.ReportedData.Row;
import org.jivesoftware.smackx.bytestreams.socks5.provider.BytestreamsProvider;
import org.jivesoftware.smackx.packet.ChatStateExtension;
import org.jivesoftware.smackx.packet.LastActivity;
import org.jivesoftware.smackx.packet.OfflineMessageInfo;
import org.jivesoftware.smackx.packet.OfflineMessageRequest;
import org.jivesoftware.smackx.packet.SharedGroupsInfo;
import org.jivesoftware.smackx.packet.VCard;
import org.jivesoftware.smackx.provider.AdHocCommandDataProvider;
import org.jivesoftware.smackx.provider.DataFormProvider;
import org.jivesoftware.smackx.provider.DelayInformationProvider;
import org.jivesoftware.smackx.provider.DiscoverInfoProvider;
import org.jivesoftware.smackx.provider.DiscoverItemsProvider;
import org.jivesoftware.smackx.provider.MUCAdminProvider;
import org.jivesoftware.smackx.provider.MUCOwnerProvider;
import org.jivesoftware.smackx.provider.MUCUserProvider;
import org.jivesoftware.smackx.provider.MessageEventProvider;
import org.jivesoftware.smackx.provider.MultipleAddressesProvider;
import org.jivesoftware.smackx.provider.RosterExchangeProvider;
import org.jivesoftware.smackx.provider.StreamInitiationProvider;
import org.jivesoftware.smackx.provider.VCardProvider;
import org.jivesoftware.smackx.provider.XHTMLExtensionProvider;
import org.jivesoftware.smackx.search.UserSearch;
import org.jivesoftware.smackx.search.UserSearchManager;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import com.lee.xqq.ChatActivity;
import com.lee.xqq.MainActivity;
import com.lee.xqq.SplashActivity;
import com.lee.xqq.base.BroadSender;
import com.lee.xqq.base.MLog;
import com.lee.xqq.item.XUserItem;
import com.lee.xqq.net.HttpResult;
import com.lee.xqq.net.HttpUtil;
import com.lee.xqq.util.CachedThreadPool;
/**
* 所有的数据控制,逻辑可以在这里实现
*
*/
public class DataUtils implements ConnectionListener,
ConnectionCreationListener, PacketListener {
private static DataUtils instance;
private Connection connection;
private static String host;
private static int port;
private String user;
private DataUtils() {
}
public void setHost(String host, int port) {
DataUtils.host = host;
DataUtils.port = port;
}
public static DataUtils getInstance() {
if (instance == null)
instance = new DataUtils();
return instance;
}
public Connection getConnection() {
return connection;
}
public String getUser() {
return user;
}
public void requestBaidu() {
CachedThreadPool.execute(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
HttpUtil httpUtil = HttpUtil.requestText(
"http://www.baidu.com", "GET");
HttpResult result = httpUtil.getResponse();
if (result.getCode() == 200) {
// 向界面发送接收广播
}
}
});
}
public void initXMPP() {
CachedThreadPool.execute(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
connectXmppServer();
}
});
}
private void connectXmppServer() {
ConnectionConfiguration config = new ConnectionConfiguration(host, port);
/** 是否启用安全验证 */
config.setSASLAuthenticationEnabled(false);
config.setReconnectionAllowed(true);// 断线重连
/** 是否启用调试 */
// config.setDebuggerEnabled(true);
/** 创建connection链接 */
try {
Connection.addConnectionCreationListener(this);
configure(ProviderManager.getInstance());
connection = new XMPPConnection(config);
/** 建立连接 */
connection.connect();
connection.addConnectionListener(this);
PacketTypeFilter filter = new PacketTypeFilter(Packet.class);
connection.addPacketListener(this, filter);
} catch (XMPPException e) {
e.printStackTrace();
MLog.makeText("服务器连接失败");
}
}
/**
* Android读不到/META-INF下的配置文件,需要手工配置。
*
* @param pm
*/
private void configure(ProviderManager pm) {
// Private Data Storage
pm.addIQProvider("query", "jabber:iq:private",
new PrivateDataManager.PrivateDataIQProvider());
// Time
try {
pm.addIQProvider("query", "jabber:iq:time",
Class.forName("org.jivesoftware.smackx.packet.Time"));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
// Roster Exchange
pm.addExtensionProvider("x", "jabber:x:roster",
new RosterExchangeProvider());
// Message Events
pm.addExtensionProvider("x", "jabber:x:event",
new MessageEventProvider());
// Chat State
pm.addExtensionProvider("active",
"http://jabber.org/protocol/chatstates",
new ChatStateExtension.Provider());
pm.addExtensionProvider("composing",
"http://jabber.org/protocol/chatstates",
new ChatStateExtension.Provider());
pm.addExtensionProvider("paused",
"http://jabber.org/protocol/chatstates",
new ChatStateExtension.Provider());
pm.addExtensionProvider("inactive",
"http://jabber.org/protocol/chatstates",
new ChatStateExtension.Provider());
pm.addExtensionProvider("gone",
"http://jabber.org/protocol/chatstates",
new ChatStateExtension.Provider());
// XHTML
pm.addExtensionProvider("html", "http://jabber.org/protocol/xhtml-im",
new XHTMLExtensionProvider());
// Group Chat Invitations
pm.addExtensionProvider("x", "jabber:x:conference",
new GroupChatInvitation.Provider());
// Service Discovery # Items
pm.addIQProvider("query", "http://jabber.org/protocol/disco#items",
new DiscoverItemsProvider());
// Service Discovery # Info
pm.addIQProvider("query", "http://jabber.org/protocol/disco#info",
new DiscoverInfoProvider());
// Data Forms
pm.addExtensionProvider("x", "jabber:x:data", new DataFormProvider());
// MUC User
pm.addExtensionProvider("x", "http://jabber.org/protocol/muc#user",
new MUCUserProvider());
// MUC Admin
pm.addIQProvider("query", "http://jabber.org/protocol/muc#admin",
new MUCAdminProvider());
// MUC Owner
pm.addIQProvider("query", "http://jabber.org/protocol/muc#owner",
new MUCOwnerProvider());
// Delayed Delivery
pm.addExtensionProvider("x", "jabber:x:delay",
new DelayInformationProvider());
// Version
try {
pm.addIQProvider("query", "jabber:iq:version",
Class.forName("org.jivesoftware.smackx.packet.Version"));
} catch (ClassNotFoundException e) {
// Not sure what's happening here.
e.printStackTrace();
}
// VCard
pm.addIQProvider("vCard", "vcard-temp", new VCardProvider());
// Offline Message Requests
pm.addIQProvider("offline", "http://jabber.org/protocol/offline",
new OfflineMessageRequest.Provider());
// Offline Message Indicator
pm.addExtensionProvider("offline",
"http://jabber.org/protocol/offline",
new OfflineMessageInfo.Provider());
// Last Activity
pm.addIQProvider("query", "jabber:iq:last", new LastActivity.Provider());
// User Search
pm.addIQProvider("query", "jabber:iq:search", new UserSearch.Provider());
// SharedGroupsInfo
pm.addIQProvider("sharedgroup",
"http://www.jivesoftware.org/protocol/sharedgroup",
new SharedGroupsInfo.Provider());
// JEP-33: Extended Stanza Addressing
pm.addExtensionProvider("addresses",
"http://jabber.org/protocol/address",
new MultipleAddressesProvider());
// FileTransfer
pm.addIQProvider("si", "http://jabber.org/protocol/si",
new StreamInitiationProvider());
pm.addIQProvider("query", "http://jabber.org/protocol/bytestreams",
new BytestreamsProvider());
// Privacy
pm.addIQProvider("query", "jabber:iq:privacy", new PrivacyProvider());
pm.addIQProvider("command", "http://jabber.org/protocol/commands",
new AdHocCommandDataProvider());
pm.addExtensionProvider("malformed-action",
"http://jabber.org/protocol/commands",
new AdHocCommandDataProvider.MalformedActionError());
pm.addExtensionProvider("bad-locale",
"http://jabber.org/protocol/commands",
new AdHocCommandDataProvider.BadLocaleError());
pm.addExtensionProvider("bad-payload",
"http://jabber.org/protocol/commands",
new AdHocCommandDataProvider.BadPayloadError());
pm.addExtensionProvider("bad-sessionid",
"http://jabber.org/protocol/commands",
new AdHocCommandDataProvider.BadSessionIDError());
pm.addExtensionProvider("session-expired",
"http://jabber.org/protocol/commands",
new AdHocCommandDataProvider.SessionExpiredError());
}
public boolean register(String account, String password) {
Registration reg = new Registration();
reg.setType(IQ.Type.SET);
reg.setTo(connection.getServiceName());
reg.setUsername(account);// 注意这里createAccount注册时,参数是username,不是jid,是“@”前面的部分。
reg.setPassword(password);
reg.addAttribute("android", "geolo_createUser_android");// 这边addAttribute不能为空,否则出错。所以做个标志是android手机创建的吧!!!!!
PacketFilter filter = new AndFilter(new PacketIDFilter(
reg.getPacketID()), new PacketTypeFilter(IQ.class));
PacketCollector collector = connection.createPacketCollector(filter);
connection.sendPacket(reg);
IQ result = (IQ) collector.nextResult(SmackConfiguration
.getPacketReplyTimeout());
if (result == null) {
MLog.makeText("连接超时");
} else if (result.getType() == IQ.Type.RESULT) {
MLog.makeText("注册成功");
return true;
} else {
MLog.makeText(result.getError().toString());
}
return false;
}
public boolean login(String userName, String userPwd) {
try {
connection.login(userName, userPwd);
user = userName + "@" + connection.getServiceName();
return true;
} catch (Exception e) {
e.printStackTrace();
}
MLog.makeText("登录失败");
return false;
}
public void changePassword(String pwd) {
try {
connection.getAccountManager().changePassword(pwd);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 更改用户状态
*/
public void setPresence(int code) {
Presence presence = null;
switch (code) {
case 0:
presence = new Presence(Presence.Type.available);
connection.sendPacket(presence);
MLog.makeText("设置在线");
break;
case 1:
presence = new Presence(Presence.Type.available);
presence.setMode(Presence.Mode.chat);
connection.sendPacket(presence);
MLog.makeText("设置Q我吧");
break;
case 2:
presence = new Presence(Presence.Type.available);
presence.setMode(Presence.Mode.dnd);
connection.sendPacket(presence);
MLog.makeText("设置忙碌");
break;
case 3:
presence = new Presence(Presence.Type.available);
presence.setMode(Presence.Mode.away);
connection.sendPacket(presence);
MLog.makeText("设置离开");
break;
case 4:
Roster roster = connection.getRoster();
Collection entries = roster.getEntries();
for (RosterEntry entry : entries) {
presence = new Presence(Presence.Type.unavailable);
presence.setPacketID(Packet.ID_NOT_AVAILABLE);
presence.setFrom(connection.getUser());
presence.setTo(entry.getUser());
connection.sendPacket(presence);
}
// 向同一用户的其他客户端发送隐身状态
presence = new Presence(Presence.Type.unavailable);
presence.setPacketID(Packet.ID_NOT_AVAILABLE);
presence.setFrom(connection.getUser());
presence.setTo(StringUtils.parseBareAddress(connection.getUser()));
connection.sendPacket(presence);
MLog.makeText("设置隐身");
break;
case 5:
presence = new Presence(Presence.Type.unavailable);
connection.sendPacket(presence);
MLog.makeText("设置离线");
break;
default:
break;
}
}
public void logoutAccount() {
try {
connection.getAccountManager().deleteAccount();
} catch (Exception e) {
e.printStackTrace();
}
}
public Collection getGroups() {
return connection.getRoster().getGroups();
}
public List getEntriesByGroup(String groupName) {
List Entrieslist = new ArrayList();
RosterGroup rosterGroup = connection.getRoster().getGroup(groupName);
Collection rosterEntry = rosterGroup.getEntries();
Iterator i = rosterEntry.iterator();
while (i.hasNext()) {
Entrieslist.add(i.next());
}
return Entrieslist;
}
public Drawable getUserImage(String user) {
ByteArrayInputStream bais = null;
try {
VCard vcard = new VCard();
// 加入这句代码,解决No VCard for
ProviderManager.getInstance().addIQProvider("vCard", "vcard-temp",
new org.jivesoftware.smackx.provider.VCardProvider());
if (user == "" || user == null || user.trim().length() <= 0) {
return null;
}
vcard.load(connection, user + "@" + connection.getServiceName());
if (vcard == null || vcard.getAvatar() == null)
return null;
bais = new ByteArrayInputStream(vcard.getAvatar());
BitmapDrawable drawable = new BitmapDrawable(bais);
bais.close();
return drawable;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public List getAllEntries() {
List Entrieslist = new ArrayList();
Collection rosterEntry = connection.getRoster()
.getEntries();
Iterator i = rosterEntry.iterator();
while (i.hasNext()) {
Entrieslist.add(i.next());
}
return Entrieslist;
}
public boolean addGroup(String groupName) {
try {
connection.getRoster().createGroup(groupName);
MLog.makeText("创建成功");
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
/**
* 添加好友 无分组
*
* @param userName
* @param name
* @return
*/
public boolean addUser(String userName, String name) {
try {
String account = userName + "@" + connection.getServiceName();
connection.getRoster().createEntry(account, name, null);
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
public boolean addUserWithName(String userName, String name,
Presence.Type type) {
return addUserWithName(userName, name, XMsgConst.X_DEFAULT_GROUP, type);
}
/**
* 添加好友 有分组
*
* @param userName
* @param name
* @param groupName
* @return
*/
public boolean addUserWithName(String userName, String name,
String groupName, Presence.Type type) {
try {
Presence subscription = new Presence(type);
subscription.setTo(userName);
userName += "@" + connection.getServiceName();
connection.sendPacket(subscription);
if (type == Type.subscribed)
connection.getRoster().createEntry(userName, name,
new String[] { groupName });
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
public boolean removeUser(String userName) {
try {
RosterEntry entry = null;
if (userName.contains("@"))
entry = connection.getRoster().getEntry(userName);
else
entry = connection.getRoster().getEntry(
userName + "@" + connection.getServiceName());
if (entry == null)
entry = connection.getRoster().getEntry(userName);
connection.getRoster().removeEntry(entry);
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
public List searchUsers(String userName) {
List results = new ArrayList();
try {
UserSearchManager usm = new UserSearchManager(connection);
String serverDomain = "search." + connection.getServiceName();
Form searchForm = usm.getSearchForm(serverDomain);
Form answerForm = searchForm.createAnswerForm();
answerForm.setAnswer("Username", true);
answerForm.setAnswer("search", userName);
ReportedData data = usm.getSearchResults(answerForm, serverDomain);
Iterator it = data.getRows();
Row row = null;
XUserItem user = null;
while (it.hasNext()) {
row = it.next();
String uName = row.getValues("Username").next().toString();
String Name = row.getValues("Name").next().toString();
String Email = row.getValues("Email").next().toString();
user = new XUserItem(uName, Name, Email);
results.add(user);
}
return results;
} catch (XMPPException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return results;
}
public void sendMessage(String toJID, String message) {
// TODO Auto-generated method stub
final Message newMessage = new Message(toJID, Message.Type.chat);
newMessage.setBody(message);
connection.sendPacket(newMessage);
}
@Override
public void connectionClosed() {
// TODO Auto-generated method stub
MLog.makeText("连接已关闭");
}
@Override
public void connectionClosedOnError(Exception arg0) {
// TODO Auto-generated method stub
MLog.makeText("连接关闭异常");
arg0.printStackTrace();
}
@Override
public void reconnectingIn(int arg0) {
// TODO Auto-generated method stub
MLog.makeText("reconnectingIn:" + arg0);
}
@Override
public void reconnectionFailed(Exception arg0) {
// TODO Auto-generated method stub
MLog.makeText("连接失败");
arg0.printStackTrace();
}
@Override
public void reconnectionSuccessful() {
// TODO Auto-generated method stub
MLog.makeText("重连成功");
}
@Override
public void connectionCreated(Connection arg0) {
// TODO Auto-generated method stub
BroadSender.sendBroadcast(SplashActivity.class);
}
@Override
public void processPacket(Packet packet) {
// TODO Auto-generated method stub
if (packet instanceof Message) {
Message msg = (Message) packet;
CacheUtils.getInstance().addMessage(msg);
BroadSender.sendBroadcast(ChatActivity.class, "action",
XMsgConst.X_PACKET_TYPE_MESSAGE);
} else if (packet instanceof Presence) {
Presence presence = (Presence) packet;
String from = presence.getFrom();// 发送方
String to = presence.getTo();// 接收方
Type type = presence.getType();
int typeValue = 0;
if (type.equals(Presence.Type.subscribe)) {
// 好友申请
typeValue = XMsgConst.X_PRESENCE_SUBSCRIBE;
} else if (type.equals(Presence.Type.subscribed)) {
// 同意添加好友
typeValue = XMsgConst.X_PRESENCE_SUBSCRIBED;
} else if (type.equals(Presence.Type.unsubscribe)) {
// 拒绝添加好友
typeValue = XMsgConst.X_PRESENCE_UNSUBSCRIBE;
} else if (type.equals(Presence.Type.unsubscribed)) {
// 删除好友
typeValue = XMsgConst.X_PRESENCE_UNSUBSCRIBED;
} else if (type.equals(Presence.Type.unavailable)) {
// 好友下线
typeValue = XMsgConst.X_PRESENCE_UNAVAILABLE;
from = processFrom(from);
CacheUtils.getInstance().putPresence(from, presence);
} else {
// 好友上线
typeValue = XMsgConst.X_PRESENCE_ONLINE;
from = processFrom(from);
CacheUtils.getInstance().putPresence(from, presence);
}
String[] params = new String[] { "action",
XMsgConst.X_PACKET_TYPE_PRESENCE, "type",
String.valueOf(typeValue), "from", from, "to", to };
BroadSender.sendBroadcast(MainActivity.class, params);
}
}
/**
* 去掉多余的服务器字符串
*
* @param from
* @return
*/
private String processFrom(String from) {
int endPos = from.lastIndexOf("/");
if (endPos != -1)
from = from.substring(0, endPos);
return from;
}
}
版权声明:部分文章、图片等内容为用户发布或互联网整理而来,仅供学习参考。如有侵犯您的版权,请联系我们,将立刻删除。