之前学习过用Scoket 创建聊天,简单的创建聊天是没问题的,但若是要实现多人复杂的聊天,后台服务器代码就比较复杂,对于我这新手来说就比较难了。后来在网上看到用openfire作服务器,利用强大的Smack API库来实现IM聊天就简单多了。html
网上也有不少关于这方面的资料,我就在这里把网上的资料和本身的理解总结一下和你们一块儿交流学习。java
须要用到如下几个工具:android
Openfire 最新版本(openfire 3.8.1)安全
下载地址:http://www.igniterealtime.org/downloads/index.jsp服务器
安装配置可参考:http://www.cnblogs.com/hoojo/archive/2012/05/17/2506769.htmljsp
Spark 最新版本(Spark 2.6.3)工具
下载地址:http://www.igniterealtime.org/downloads/index.jsp学习
ASmack 最新版本 (asmack-jse-buddycloud-2010.12.11.jar)ui
因为在Android平台下开发 因此咱们用到的是 aSmack,与Smack没有很大的区别google
下载地址1:http://download.csdn.net/detail/h7870181/6372585 (如今用的就是这个,修改了一些BUG)
下载地址2:http://code.google.com/p/asmack/downloads/list
须要安装的安装好,须要下载的下载好(这里就很少做介绍)。建立项目工程,导入ASmack jar包,OK,下面就一块儿去学习怎么实现 用户注册、登陆、修改密码和注销等一些功能!
首先第1、与服务器创建好链接
关键代码:127.0.0.1为服务器IP,5222为服务器端口号
[java] view plaincopyprint? /**
链接服务器
@return /
public boolean conServer() {
ConnectionConfiguration config = new ConnectionConfiguration(
127.0.0.1, 5222);
/* 是否启用安全验证 /
config.setSASLAuthenticationEnabled(false);
/* 是否启用调试 /
// config.setDebuggerEnabled(true);
/* 建立connection连接 /
try {
connection = new XMPPConnection(config);
/* 创建链接 */
connection.connect();
return true;
} catch (XMPPException e) {
e.printStackTrace();
}
return false;
}
/**
关键代码:
如下代码注释都很清楚了,若有不懂的地方能够留言,这里就很少作解释了。
[java] view plaincopyprint? /**
注册
@param account 注册账号
@param password 注册密码
@return 一、注册成功 0、服务器没有返回结果二、这个帐号已经存在三、注册失败 */
public String regist(String account, String password) {
if (connection == null)
return "0";
Registration reg = new Registration();
reg.setType(IQ.Type.SET);
reg.setTo(ClientConServer.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 = ClientConServer.connection
.createPacketCollector(filter);
ClientConServer.connection.sendPacket(reg);
IQ result = (IQ) collector.nextResult(SmackConfiguration
.getPacketReplyTimeout());
// Stop queuing results
collector.cancel();// 中止请求results(是否成功的结果)
if (result == null) {
Log.e("RegistActivity", "No response from server.");
return "0";
} else if (result.getType() == IQ.Type.RESULT) {
return "1";
} else { // if (result.getType() == IQ.Type.ERROR)
if (result.getError().toString().equalsIgnoreCase("conflict(409)")) {
Log.e("RegistActivity", "IQ.Type.ERROR: "
+ result.getError().toString());
return "2";
} else {
Log.e("RegistActivity", "IQ.Type.ERROR: "
+ result.getError().toString());
return "3";
}
}
}
/**
第3、实现登陆
关键代码: 代码很简单不作太多解释
[java] view plaincopyprint? /**
登陆
@param a 登陆账号
@param p 登陆密码
@return /
public boolean login(String a, String p) {
try {
if (connection == null)
return false;
/* 登陆 */
connection.login(a, p);
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
/**
关键代码:一样很简单
[java] view plaincopyprint? /**
修改密码
@param connection
@return
*/
public static boolean changePassword(XMPPConnection connection,String pwd)
{
try {
connection.getAccountManager().changePassword(pwd);
return true;
} catch (Exception e) {
return false;
}
}
/**
第5、更改用户状态
关键代码:好吧,代码有点多,不过很清晰
[java] view plaincopyprint? /**
更改用户状态 */
public void setPresence(int code) {
if (connection == null)
return;
Presence presence;
switch (code) {
case 0:
presence = new Presence(Presence.Type.available);
connection.sendPacket(presence);
Log.v("state", "设置在线");
break;
case 1:
presence = new Presence(Presence.Type.available);
presence.setMode(Presence.Mode.chat);
connection.sendPacket(presence);
Log.v("state", "设置Q我吧");
System.out.println(presence.toXML());
break;
case 2:
presence = new Presence(Presence.Type.available);
presence.setMode(Presence.Mode.dnd);
connection.sendPacket(presence);
Log.v("state", "设置忙碌");
System.out.println(presence.toXML());
break;
case 3:
presence = new Presence(Presence.Type.available);
presence.setMode(Presence.Mode.away);
connection.sendPacket(presence);
Log.v("state", "设置离开");
System.out.println(presence.toXML());
break;
case 4:
Roster roster = connection.getRoster();
Collection<RosterEntry> 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);
System.out.println(presence.toXML());
}
// 向同一用户的其余客户端发送隐身状态
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);
Log.v("state", "设置隐身");
break;
case 5:
presence = new Presence(Presence.Type.unavailable);
connection.sendPacket(presence);
Log.v("state", "设置离线");
break;
default:
break;
}
}
/**
第六:注销
关键代码:很简单吧!
[java] view plaincopyprint? /**
删除当前用户
@param connection
@return
*/
public static boolean deleteAccount(XMPPConnection connection)
{
try {
connection.getAccountManager().deleteAccount();
return true;
} catch (Exception e) {
return false;
}
}
/**
好吧,这篇就先介绍到这!