http://blog.csdn.net/h7870181/article/details/8653865

以前学习过用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为服务器端口号

  1. /**
  2. * 连接服务器
  3. *
  4. * @return
  5. */
  6. public boolean conServer() {
  7. ConnectionConfiguration config = new ConnectionConfiguration(
  8. 127.0.0.1, 5222);
  9. /** 是否启用安全验证 */
  10. config.setSASLAuthenticationEnabled(false);
  11. /** 是否启用调试 */
  12. // config.setDebuggerEnabled(true);
  13. /** 创建connection链接 */
  14. try {
  15. connection = new XMPPConnection(config);
  16. /** 建立连接 */
  17. connection.connect();
  18. return true;
  19. } catch (XMPPException e) {
  20. e.printStackTrace();
  21. }
  22. return false;
  23. }
	/**
* 连接服务器
*
* @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;
}

第二、实现注册

关键代码:

以下代码注释都很清楚了,如有不懂的地方可以留言,这里就不多做解释了。

  1. /**
  2. * 注册
  3. *
  4. * @param account 注册帐号
  5. * @param password 注册密码
  6. * @return 1、注册成功 0、服务器没有返回结果2、这个账号已经存在3、注册失败
  7. */
  8. public String regist(String account, String password) {
  9. if (connection == null)
  10. return "0";
  11. Registration reg = new Registration();
  12. reg.setType(IQ.Type.SET);
  13. reg.setTo(ClientConServer.connection.getServiceName());
  14. reg.setUsername(account);// 注意这里createAccount注册时,参数是username,不是jid,是“@”前面的部分。
  15. reg.setPassword(password);
  16. reg.addAttribute("android", "geolo_createUser_android");// 这边addAttribute不能为空,否则出错。所以做个标志是android手机创建的吧!!!!!
  17. PacketFilter filter = new AndFilter(new PacketIDFilter(
  18. reg.getPacketID()), new PacketTypeFilter(IQ.class));
  19. PacketCollector collector = ClientConServer.connection
  20. .createPacketCollector(filter);
  21. ClientConServer.connection.sendPacket(reg);
  22. IQ result = (IQ) collector.nextResult(SmackConfiguration
  23. .getPacketReplyTimeout());
  24. // Stop queuing results
  25. collector.cancel();// 停止请求results(是否成功的结果)
  26. if (result == null) {
  27. Log.e("RegistActivity", "No response from server.");
  28. return "0";
  29. } else if (result.getType() == IQ.Type.RESULT) {
  30. return "1";
  31. } else { // if (result.getType() == IQ.Type.ERROR)
  32. if (result.getError().toString().equalsIgnoreCase("conflict(409)")) {
  33. Log.e("RegistActivity", "IQ.Type.ERROR: "
  34. + result.getError().toString());
  35. return "2";
  36. } else {
  37. Log.e("RegistActivity", "IQ.Type.ERROR: "
  38. + result.getError().toString());
  39. return "3";
  40. }
  41. }
  42. }
	/**
* 注册
*
* @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";
}
}
}

第三、实现登录

关键代码: 代码很简单不做太多解释

  1. /**
  2. * 登录
  3. *
  4. * @param a 登录帐号
  5. * @param p 登录密码
  6. * @return
  7. */
  8. public boolean login(String a, String p) {
  9. try {
  10. if (connection == null)
  11. return false;
  12. /** 登录 */
  13. connection.login(a, p);
  14. return true;
  15. } catch (Exception e) {
  16. e.printStackTrace();
  17. }
  18. return false;
  19. }
 	 /**
* 登录
*
* @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;
}

第四、修改密码

关键代码:同样很简单

  1. /**
  2. * 修改密码
  3. * @param connection
  4. * @return
  5. */
  6. public static boolean changePassword(XMPPConnection connection,String pwd)
  7. {
  8. try {
  9. connection.getAccountManager().changePassword(pwd);
  10. return true;
  11. } catch (Exception e) {
  12. return false;
  13. }
  14. }
    /**
* 修改密码
* @param connection
* @return
*/
public static boolean changePassword(XMPPConnection connection,String pwd)
{
try {
connection.getAccountManager().changePassword(pwd);
return true;
} catch (Exception e) {
return false;
}
}

第五、更改用户状态

关键代码:好吧,代码有点多,不过很清晰

  1. /**
  2. * 更改用户状态
  3. */
  4. public void setPresence(int code) {
  5. if (connection == null)
  6. return;
  7. Presence presence;
  8. switch (code) {
  9. case 0:
  10. presence = new Presence(Presence.Type.available);
  11. connection.sendPacket(presence);
  12. Log.v("state", "设置在线");
  13. break;
  14. case 1:
  15. presence = new Presence(Presence.Type.available);
  16. presence.setMode(Presence.Mode.chat);
  17. connection.sendPacket(presence);
  18. Log.v("state", "设置Q我吧");
  19. System.out.println(presence.toXML());
  20. break;
  21. case 2:
  22. presence = new Presence(Presence.Type.available);
  23. presence.setMode(Presence.Mode.dnd);
  24. connection.sendPacket(presence);
  25. Log.v("state", "设置忙碌");
  26. System.out.println(presence.toXML());
  27. break;
  28. case 3:
  29. presence = new Presence(Presence.Type.available);
  30. presence.setMode(Presence.Mode.away);
  31. connection.sendPacket(presence);
  32. Log.v("state", "设置离开");
  33. System.out.println(presence.toXML());
  34. break;
  35. case 4:
  36. Roster roster = connection.getRoster();
  37. Collection<RosterEntry> entries = roster.getEntries();
  38. for (RosterEntry entry : entries) {
  39. presence = new Presence(Presence.Type.unavailable);
  40. presence.setPacketID(Packet.ID_NOT_AVAILABLE);
  41. presence.setFrom(connection.getUser());
  42. presence.setTo(entry.getUser());
  43. connection.sendPacket(presence);
  44. System.out.println(presence.toXML());
  45. }
  46. // 向同一用户的其他客户端发送隐身状态
  47. presence = new Presence(Presence.Type.unavailable);
  48. presence.setPacketID(Packet.ID_NOT_AVAILABLE);
  49. presence.setFrom(connection.getUser());
  50. presence.setTo(StringUtils.parseBareAddress(connection.getUser()));
  51. connection.sendPacket(presence);
  52. Log.v("state", "设置隐身");
  53. break;
  54. case 5:
  55. presence = new Presence(Presence.Type.unavailable);
  56. connection.sendPacket(presence);
  57. Log.v("state", "设置离线");
  58. break;
  59. default:
  60. break;
  61. }
  62. }
	/**
* 更改用户状态
*/
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;
}
}

 

第六:注销

关键代码:很简单吧!

  1. /**
  2. * 删除当前用户
  3. * @param connection
  4. * @return
  5. */
  6. public static boolean deleteAccount(XMPPConnection connection)
  7. {
  8. try {
  9. connection.getAccountManager().deleteAccount();
  10. return true;
  11. } catch (Exception e) {
  12. return false;
  13. }
  14. }
    /**
* 删除当前用户
* @param connection
* @return
*/
public static boolean deleteAccount(XMPPConnection connection)
{
try {
connection.getAccountManager().deleteAccount();
return true;
} catch (Exception e) {
return false;
}
}

好吧,这篇就先介绍到这!

Android基于XMPP Smack Openfire下学习开发IM(一)实现用户注册、登录、修改密码和注销等的更多相关文章

  1. Android基于XMPP Smack Openfire下学习开发IM(六)总结

    不管学习什么都应该总结 这里我把关于Xmpp的一些方法整理到一个工具类中了 我就分享给大家 XmppConnection.java package com.techrare.utils; import ...

  2. Android基于XMPP Smack Openfire下学习开发IM(五)连接断开重连

    学习过程中大家都碰到过连接被断开的问题给困扰吧,下面教大家如何做到连接断开后,重新连接 首先要创建连接监听器,用来监听连接状态,这里我写了一个类 继承了ConnectionListener,重写了里面 ...

  3. Android基于XMPP Smack openfire 开发的聊天室

    Android基于XMPP Smack openfire 开发的聊天室(一)[会议服务.聊天室列表.加入] http://blog.csdn.net/lnb333666/article/details ...

  4. Android基于XMPP Smack及Openfire学习笔记(1)

    之前开发的项目中实用到IM聊天功能.可是这块功能公司有专门的IM团队来开发,由他们开发好后.直接接入到我们APP中.我參与写IM相关功能非常地少,所以也一直想学习相关知识 . 眼下Android主要用 ...

  5. openfire Android学习(一)----实现用户注册、登录、修改密码和注销等

    以前学习过用Scoket 建立聊天,简单的建立聊天是没问题的,但如果要实现多人复杂的聊天,后台服务器代码就比较复杂,对于我这新手来讲就比较难了.后来在网上看到用openfire做服务器,利用强大的Sm ...

  6. Android基于XMPP的即时通讯2-文件传输

    本文是在上一篇博文Android基于XMPP的即时通讯1-基本对话的基础上,添加新的功能,文件传输 1.初始化文件传输管理类 public static FileTransferManager get ...

  7. Android基于XMPP的即时通讯3-表情发送

    这篇博文主要讲表情发送的一些东西. 参考:Android基于XMPP的即时通讯1-基本对话 1.准备好资源文件 采用的是emoji的表情,我打包好了,下载地址:http://files.cnblogs ...

  8. MVC5 网站开发之六 管理员 1、登录、验证和注销

    上次业务逻辑和展示层的架构都写了,可以开始进行具体功能的实现,这次先实现管理员的登录.验证和注销功能. 目录 奔跑吧,代码小哥! MVC5网站开发之一 总体概述 MVC5 网站开发之二 创建项目 MV ...

  9. mysql5.7 mysql库下面的user表没有password字段无法修改密码

    如题所述,mysql5.7  mysql库下面的user表没有password字段无法修改密码, 5.7版本已经不再使用password来作为密码的字段了  而改成了authentication_st ...

随机推荐

  1. MT【151】传球问题

    (清华2017.4.29标准学术能力测试10) 甲.乙.丙.丁四人做相互传球的游戏,第一次甲传给其他三人中的一人,第二次由拿到球的人再传给其他三人中的一人,这样的传球共进行了$4$次,则第四次球传回甲 ...

  2. 一文看尽HashMap

    前言 日常开发中,经常会使用到JDK自带的集合类:List.Set.Map三者的实现,ArrayList.LinkedList.HashSet.TreeSet.HashMap.TreeMap等.其中L ...

  3. k最近邻算法(kNN)

    from numpy import * import operator from os import listdir def classify0(inX, dataSet, labels, k): d ...

  4. 团体程序设计天梯赛 L1-009. N个数求和

    易错题 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdboo ...

  5. 图像bayer格式介绍以及bayer插值原理CFA

    1 图像bayer格式介绍 bayer格式图片是伊士曼·柯达公司科学家Bryce Bayer发明的,Bryce Bayer所发明的拜耳阵列被广泛运用数字图像. 对于彩色图像,需要采集多种最基本的颜色, ...

  6. java程序文件读取与保存实例代码

    class RadioHere extends JFrame implements ActionListener { private JTextArea ta=new JTextArea(10,20) ...

  7. Java泛型底层源码解析--ConcurrentHashMap(JDK1.7)

    1. Concurrent相关历史 JDK5中添加了新的concurrent包,相对同步容器而言,并发容器通过一些机制改进了并发性能.因为同步容器将所有对容器状态的访问都串行化了,这样保证了线程的安全 ...

  8. Digia公司投资qt

    sklearn实战-乳腺癌细胞数据挖掘(博主亲自录制视频) https://study.163.com/course/introduction.htm?courseId=1005269003& ...

  9. JavaScript中的arguments详解

    1. arguments arguments不是真正的数组,它是一个实参对象,每个实参对象都包含以数字为索引的一组元素以及length属性. (function () { console.log(ar ...

  10. python 几种不同的格式化输出

    1. % %是最常用的格式化输出形式,后面接类型,%s,%d,%c等等 name = input() print('I am %s' % name) 2.format format也是常用格式化输出 ...