如下文章引用自:http://www.apkbus.com/android-144433-1-1.html

公司项目要求实现消息推送及即时聊天功能,考虑再三,选择了openfire。因为也是第一次接触XMPP开发,属于现学现用,走了很多弯路,印象比较深的是添加好友的实现。这个还曾在CSDN上留了个脚印,主要是想做个记录(http://blog.csdn.net/ming_light/article/details/11889697)。
但是后来又觉得有必要做个详细的总结,正好借这个活动,发个帖子。不保证完全正确,只是一种思路。
Android XMPP开发要借助asmack这个jar包
这些都是开源的,网上可以下到asmack的源码、openfire的源码以及详细的API文档

主要用的类有:
Roster   可以理解为好友花名册,提供创建删除获取列表等功能Roster.SubscriptionMode    这个在建立链接的时候使用,我的理解就是设置接收请求的模式,有三种,我们项目用的是SubscriptionMode.manual 也就是手动处理。
Presence   有关好友的推送消息,都是Presence包
Presence.Type   有7个Type,包含了好友上线下线、添加删除好友及错误信息的Type
PacketFilter    过滤器,此功能中主要实现过滤出Presence
PacketListener   看名字就知道,Packet监听,可以监听到服务端发来的所有信息。因为xmpp发的包都是它的子类

另外还有一点,就是好友双方对彼此的状态,有网友总结如下:
none:是用户和自己roster中的好友彼此不关心,既不想把自己的presence状态告诉对方,也不愿意收到对方presence更新消息
to:是关心roster中好友的presence状态消息,而不将自己的消息告诉对方
from:是只关心,接受对方的状态消息,而不将自己的消息告诉对方
both:即收取对方状态更新,又将自己的更新告知对方
Remove :将对方干掉,不再关心他的任何信息。

可能第一次看上面的东西,不太理解,比如说A  B两个用户(SubscriptionMode.manual这种模式)
A主动请求加B     B如果只是同意但并没有主动请求加A,此时B的状态是对A开放的,而B看不到A的状态。也就是说对于A来说,B的状态是to。对于B来说,A的状态是from。
因此要想AB双方互成好友,则B必须再发一个好友请求,并且A同意。
总结:用户只能看到对于他的状态是to和both的好友

走一边流程:
A+B   A调用Roster的createEntry(String user,String name,String[] groups)  (参数在API里都有解释,注意第一个参数user是当前登陆用户的jid,也就是注册名加域名,这个可以通过XMPPConnection的getUser方法得到)方法,此时A会发一个Presence包给B,且type="subscribe"(实际上都是服务器发的,这里可以不考虑中间过程,便于理解)
因为是手动添加好友,这里就需要在程序中对Presence包进行捕获处理,并且做出响应。所谓响应也就是发一个Presence包给A,告知是否同意。如下:

  1. Presence presence = new Presence(
  2. Presence.Type.subscribed);//同意是
  3. subscribed   拒绝是unsubscribe
  4. presence.setTo(...);//接收方jid
  5. presence.setFrom(...);//发送方jid
  6. connection.sendPacket(presence);//connection是你自己的XMPPConnection链接

复制代码

要想B看到A的状态,流程和上面一样。
但是比较麻烦的一点是本地缓存信息的判断。包括你的好友列表、添加好友消息信息不可能每次都去服务端获取,肯定是要做本地缓存,网络总规是有不稳定性的。
因为情况不同,这里只想说可以根据发送方jid、接收方jid、登陆用户jid以及type进行比较去重。这四个变量对于每一条Presence数据包来讲,肯定不会是完全一样的,大家可以自己琢磨一下。
注意:A主动加B,B同意的话发的状态是subscribed,此时如果B在加A,A同意的话也是subscribed。看上去没什么,但是做本地缓存的时候要做好判断。

下面是我的Presence包的监听方法,供大家参考

  1. public class PresenceService extends Service {
  2. private _ConnectionControl cc = _ConnectionControl.getCC();// 保存了当前的链接 XMPPConnection
  3. @Override
  4. public IBinder onBind(Intent arg0) {
  5. return null;
  6. }
  7. @Override
  8. public void onCreate() {
  9. super.onCreate();
  10. }
  11. @Override
  12. public void onDestroy() {
  13. super.onDestroy();
  14. }
  15. @Override
  16. public int onStartCommand(Intent intent, int flags, int startId) {
  17. Log.i("Presence", "PresenceService-----" + (cc.connection == null));
  18. if (cc.connection != null && cc.connection.isConnected()
  19. && cc.connection.isAuthenticated()) {//已经认证的情况下,才能正确收到Presence包(也就是登陆)
  20. final String loginuser = cc.connection.getUser().substring(0, //这里要解释一下,这是要去除系统在登陆用户尾部添加的域名信息,例如  xxx<span id="kM0.021647081011906266">@域名.....</span>
  21. cc.connection.getUser().lastIndexOf("@"));
  22. //理解为条件过滤器   过滤出Presence包
  23. PacketFilter filter = new AndFilter(new PacketTypeFilter(
  24. Presence.class));
  25. PacketListener listener = new PacketListener() {
  26. @Override
  27. public void processPacket(Packet packet) {
  28. Log.i("Presence", "PresenceService------" + packet.toXML());
  29. //看API可知道   Presence是Packet的子类
  30. if (packet instanceof Presence) {
  31. Log.i("Presence", packet.toXML());
  32. Presence presence = (Presence) packet;
  33. //Presence还有很多方法,可查看API
  34. String from = presence.getFrom();//发送方
  35. String to = presence.getTo();//接收方
  36. //Presence.Type有7中状态
  37. if (presence.getType().equals(Presence.Type.subscribe)) {//好友申请
  38. } else if (presence.getType().equals(
  39. Presence.Type.subscribed)) {//同意添加好友
  40. } else if (presence.getType().equals(
  41. Presence.Type.unsubscribe)) {//拒绝添加好友  和  删除好友
  42. } else if (presence.getType().equals(
  43. Presence.Type.unsubscribed))
  44. } else if (presence.getType().equals(
  45. Presence.Type.unavailable)) {//好友下线   要更新好友列表,可以在这收到包后,发广播到指定页面   更新列表
  46. } else {//好友上线
  47. }
  48. }
  49. }
  50. };
  51. cc.connection.addPacketListener(listener, filter); //注册监听
  52. }
  53. return super.onStartCommand(intent, flags, startId);
  54. }
  55. }

复制代码

再加点东西吧,就是断线自动重连。
XMPP是提供了这个功能的:
configuration.setReconnectionAllowed( true );
connection.addConnectionListener(connectionListener); //这个监听接口的实现就不写了,基本没什么,我只做了登陆冲突的处理。

开始是上面这么写的,测试发现没有效果,之后各种百度谷歌,才知道必须提前加载 ReconnectionManager这个类,写个静态代码块就行了:

  1. try {
  2. Class.forName("org.jivesoftware.smack.ReconnectionManager");
  3. } catch (Exception e1) {
  4. e1.printStackTrace();
  5. }

复制代码

个人浅见,技术的提升在于交流。

Android xmpp开发 asmack获取离线在线添加好友消息 及 好友上线下线通知相关推荐

  1. Android软件开发之获取通讯录联系人信息

    点击打开链接http://blog.csdn.net/snwrking/article/details/7601794 Android软件开发之获取通讯录联系人信息 + android联系人信息的存储 ...

  2. Android流媒体开发之-获取直播节目预告

    1.Android流媒体开发之-直播实现 2.Android流媒体开发之-直播自定义列表 3.Android流媒体开发之-服务器图片的加载 4.Android流媒体开发之-直播自定义分类 5.Andr ...

  3. 8.腾讯微博Android客户端开发——自动获取验证码(2)

    上一节给大家讲解通过调用android系统自带的浏览器进行授权认证的,使用该种方式能很容易的完成认证,但是该种方式有个弊端,也就是如果使用第三方的浏览器如UC.天天等,输入完QQ账号信息点击" ...

  4. 腾讯微博Android客户端开发——自动获取验证码

    上一节给大家讲解通过调用android系统自带的浏览器进行授权认证的,使用该种方式能很容易的完成认证,但是该种方式有个弊端,也就是如果使用第三方的浏览器如UC.天天等,输入完QQ账号信息点击" ...

  5. Android通讯录开发之获取运营商号码段(移动、联通、电信)

    本篇博客是自己在开发时用到的一个点,获取运营商的号码段,截至2013年12月30日,三大运营商的号码段增加了不少,还出现了1700这样4位的号码段.号码段有什么用呢?每个运营商都有不同的号码段,比如1 ...

  6. android 获取wifi的加密类型,Android WIFI开发:获取wifi列表,连接指定wifi,获取wifi加密方式,监听wifi网络变化等...

    下面是 Android 开发中 WiFi 的常用配置,如:获取当前 WiFi ,扫描 WiFi 获取列表,连接指定 WiFi ,监听网络变化等等. 下面是效果图: GitHub 下载地址:https: ...

  7. 7.腾讯微博Android客户端开发——自动获取验证码(1)

    通过前面的介绍,我们成功获取了Access Token,但是在该过程中有个不好的地方:用户输入完QQ信息后,需要记录验证码,然后返回至Activity手动输入验证码,这将会使我们的程序显得非常不友好. ...

  8. Android Studio开发之获取Apk相关版本信息

    序言: 本博客备忘一下,如何获取Apk的app名称,包名以及VersonName等等信息! 将这些方式封装成类,并给出调用示例.希望可以帮助到一些同道中人. 正文: 1.类的封装,直接附上源码: 类名 ...

  9. android蓝牙开发简单获取android设备已经连接过(已适配)的蓝牙设备信息

    本文没有深入到如何搜索蓝牙,如何适配蓝牙(既然android系统本身有这部分功能,不需要的情况下就由系统完成就行) 本文主要是获取已适配的蓝牙设备

最新文章

  1. python用于什么-Python用于哪些领域
  2. 恩施茶旅谋定乡村-农业大健康·万祥军:侗乡第一寨促生态
  3. 优化PHP程序的方法(温故知新)
  4. 房贷断供会有什么严重后果?
  5. php访问mysql函数吗,PHP访问MySQL数据库函数简介
  6. LeetCode 733. 图像渲染(DFS/BFS)
  7. “绿色高效 模块智能”金融业数据中心系列规范发布会将于12月7日召开
  8. java中mvc事务_Spring MVC 事务配置
  9. Java之多线程断点下载的实现
  10. HMM、MEMM、CRF模型的比较
  11. 【Unity Shader入门】☀️ | 使用Shader实现一个彩虹球效果✨!闪闪发光的特效离我又近了一步!
  12. 离散数学7__第2章命题逻辑的推理理论__主析取范式和主合取范式
  13. Android 项目正式签名打包教程
  14. 关于4418开发和6818开发
  15. Eclipse的Debug调试技巧大全
  16. 谢烟客---------Linux之CentOS 7 systemd
  17. matlab解决力学问题程序,力学专业程序实践:用MATLAB解决力学问题的方法与实例...
  18. 白嫖几十款的微信红包封面
  19. ADSL后台初始密码大全
  20. Python 发送每日新闻

热门文章

  1. python随机密码生成小demo
  2. # 《致我的陌生恋人》
  3. 如何设计软件性能测试方案,软件性能测试怎么做?有哪些步骤?
  4. 程序员:微信昵称可以加特效啦?
  5. 《MySQL 入门教程》第 28 篇 字符集与排序规则
  6. NPM酷库:numeral,格式化数字
  7. 加强野外火源管控,森林防火二维码
  8. 文献阅读记录1-YOLOv3:An Incremental Improvement
  9. 树莓派4b之初学者入门人脸识别(手把手完整版)
  10. 在AI与信息交互之间:QQ 浏览器的边界探索