以前學習過用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爲服務器端口號
/**
* 連接服務器
*
* @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;
}
第二、實現註冊
關鍵代碼:
以下代碼註釋都很清楚了,如有不懂的地方可以留言,這裏就不多做解釋了。
/**
* 註冊
*
* @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";
}
}
}
第三、實現登錄
關鍵代碼: 代碼很簡單不做太多解釋
/**
* 登錄
*
* @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;
}
第四、修改密碼
關鍵代碼:同樣很簡單
/**
* 修改密碼
* @param connection
* @return
*/
public static boolean changePassword(XMPPConnection connection,String pwd)
{
try {
connection.getAccountManager().changePassword(pwd);
return true;
} catch (Exception e) {
return false;
}
}
第五、更改用戶狀態
關鍵代碼:好吧,代碼有點多,不過很清晰
/**
* 更改用戶狀態
*/
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;
}
}
第六:註銷
關鍵代碼:很簡單吧!
/**
* 刪除當前用戶
* @param connection
* @return
*/
public static boolean deleteAccount(XMPPConnection connection)
{
try {
connection.getAccountManager().deleteAccount();
return true;
} catch (Exception e) {
return false;
}
}
好吧,這篇就先介紹到這!