以前学习过用Scoket 建立聊天,简单的建立聊天是没问题的,但如果要实现多人复杂的聊天,后台服务器代码就比较复杂,对于我这新手来讲就比较难了。后来在网上看到用openfire做服务器,利用强大的Smack API库来实现IM聊天就简单多了。
网上也有很多关于这方面的资料,我就在这里把网上的资料和自己的理解总结一下和大家一起交流学习。
需要用到以下几个工具:
Openfire 最新版本(openfire 3.8.1)
下载地址:http://www.igniterealtime.org/downloads/index.jsp
安装配置可参考:http://www.cnblogs.com/hoojo/archive/2012/05/17/2506769.html
Spark 最新版本(Spark 2.6.3)
下载地址:http://www.igniterealtime.org/downloads/index.jsp
ASmack 最新版本 (asmack-jse-buddycloud-2010.12.11.jar)
由于在Android平台下开发 所以我们用到的是 aSmack,与Smack没有很大的区别
下载地址1:http://download.csdn.net/detail/h7870181/6372585 (现在用的就是这个,修改了一些BUG)
下载地址2:http://code.google.com/p/asmack/downloads/list
需要安装的安装好,需要下载的下载好(这里就不多作介绍)。创建项目工程,导入ASmack jar包,OK,下面就一起去学习怎么实现 用户注册、登录、修改密码和注销等一些功能!
首先第一、与服务器建立好连接
关键代码: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;
}
/**
127.0.0.1, 5222);
/ 是否启用安全验证 / connection = new XMPPConnection(config);
/** 建立连接 */
connection.connect();
return true;
} catch (XMPPException e) {e.printStackTrace();
} 关键代码:
以下代码注释都很清楚了,如有不懂的地方可以留言,这里就不多做解释了。
[java] view plaincopyprint?
/**
注册
@param account 注册帐号
@param password 注册密码
@return 1、注册成功 0、服务器没有返回结果2、这个账号已经存在3、注册失败
*/
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";
}
}
}
/**
return "0";
Registration reg = new Registration(); reg.getPacketID()), new PacketTypeFilter(IQ.class));
PacketCollector collector = ClientConServer.connection .createPacketCollector(filter);
ClientConServer.connection.sendPacket(reg); .getPacketReplyTimeout());
// Stop queuing results 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";
}
} 第三、实现登录
关键代码: 代码很简单不做太多解释
[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;
}
/**
if (connection == null)
return false;
/** 登录 */
connection.login(a, p);
return true;
} catch (Exception e) {e.printStackTrace();
} 关键代码:同样很简单
[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;
}
}
/**
connection.getAccountManager().changePassword(pwd);
return true;
} catch (Exception e) {return false;
} 第五、更改用户状态
关键代码:好吧,代码有点多,不过很清晰
[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;
}
}
/**
return;
Presence presence; 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;
}
}
/**
connection.getAccountManager().deleteAccount();
return true;
} catch (Exception e) {return false;
} 好吧,这篇就先介绍到这!