之前學習過用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;
}
}
/**
好吧,這篇就先介紹到這!