Android xmpp开发 asmack获取离线在线添加好友消息 及 好友上线下线通知
如下文章引用自: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,告知是否同意。如下:
- Presence presence = new Presence(
- Presence.Type.subscribed);//同意是
- subscribed 拒绝是unsubscribe
- presence.setTo(...);//接收方jid
- presence.setFrom(...);//发送方jid
- connection.sendPacket(presence);//connection是你自己的XMPPConnection链接
复制代码
要想B看到A的状态,流程和上面一样。
但是比较麻烦的一点是本地缓存信息的判断。包括你的好友列表、添加好友消息信息不可能每次都去服务端获取,肯定是要做本地缓存,网络总规是有不稳定性的。
因为情况不同,这里只想说可以根据发送方jid、接收方jid、登陆用户jid以及type进行比较去重。这四个变量对于每一条Presence数据包来讲,肯定不会是完全一样的,大家可以自己琢磨一下。
注意:A主动加B,B同意的话发的状态是subscribed,此时如果B在加A,A同意的话也是subscribed。看上去没什么,但是做本地缓存的时候要做好判断。
下面是我的Presence包的监听方法,供大家参考
- public class PresenceService extends Service {
- private _ConnectionControl cc = _ConnectionControl.getCC();// 保存了当前的链接 XMPPConnection
- @Override
- public IBinder onBind(Intent arg0) {
- return null;
- }
- @Override
- public void onCreate() {
- super.onCreate();
- }
- @Override
- public void onDestroy() {
- super.onDestroy();
- }
- @Override
- public int onStartCommand(Intent intent, int flags, int startId) {
- Log.i("Presence", "PresenceService-----" + (cc.connection == null));
- if (cc.connection != null && cc.connection.isConnected()
- && cc.connection.isAuthenticated()) {//已经认证的情况下,才能正确收到Presence包(也就是登陆)
- final String loginuser = cc.connection.getUser().substring(0, //这里要解释一下,这是要去除系统在登陆用户尾部添加的域名信息,例如 xxx<span id="kM0.021647081011906266">@域名.....</span>
- cc.connection.getUser().lastIndexOf("@"));
- //理解为条件过滤器 过滤出Presence包
- PacketFilter filter = new AndFilter(new PacketTypeFilter(
- Presence.class));
- PacketListener listener = new PacketListener() {
- @Override
- public void processPacket(Packet packet) {
- Log.i("Presence", "PresenceService------" + packet.toXML());
- //看API可知道 Presence是Packet的子类
- if (packet instanceof Presence) {
- Log.i("Presence", packet.toXML());
- Presence presence = (Presence) packet;
- //Presence还有很多方法,可查看API
- String from = presence.getFrom();//发送方
- String to = presence.getTo();//接收方
- //Presence.Type有7中状态
- if (presence.getType().equals(Presence.Type.subscribe)) {//好友申请
- } else if (presence.getType().equals(
- Presence.Type.subscribed)) {//同意添加好友
- } else if (presence.getType().equals(
- Presence.Type.unsubscribe)) {//拒绝添加好友 和 删除好友
- } else if (presence.getType().equals(
- Presence.Type.unsubscribed))
- } else if (presence.getType().equals(
- Presence.Type.unavailable)) {//好友下线 要更新好友列表,可以在这收到包后,发广播到指定页面 更新列表
- } else {//好友上线
- }
- }
- }
- };
- cc.connection.addPacketListener(listener, filter); //注册监听
- }
- return super.onStartCommand(intent, flags, startId);
- }
- }
复制代码
再加点东西吧,就是断线自动重连。
XMPP是提供了这个功能的:
configuration.setReconnectionAllowed( true );
connection.addConnectionListener(connectionListener); //这个监听接口的实现就不写了,基本没什么,我只做了登陆冲突的处理。
开始是上面这么写的,测试发现没有效果,之后各种百度谷歌,才知道必须提前加载 ReconnectionManager这个类,写个静态代码块就行了:
- try {
- Class.forName("org.jivesoftware.smack.ReconnectionManager");
- } catch (Exception e1) {
- e1.printStackTrace();
- }
复制代码
个人浅见,技术的提升在于交流。
Android xmpp开发 asmack获取离线在线添加好友消息 及 好友上线下线通知相关推荐
- Android软件开发之获取通讯录联系人信息
点击打开链接http://blog.csdn.net/snwrking/article/details/7601794 Android软件开发之获取通讯录联系人信息 + android联系人信息的存储 ...
- Android流媒体开发之-获取直播节目预告
1.Android流媒体开发之-直播实现 2.Android流媒体开发之-直播自定义列表 3.Android流媒体开发之-服务器图片的加载 4.Android流媒体开发之-直播自定义分类 5.Andr ...
- 8.腾讯微博Android客户端开发——自动获取验证码(2)
上一节给大家讲解通过调用android系统自带的浏览器进行授权认证的,使用该种方式能很容易的完成认证,但是该种方式有个弊端,也就是如果使用第三方的浏览器如UC.天天等,输入完QQ账号信息点击" ...
- 腾讯微博Android客户端开发——自动获取验证码
上一节给大家讲解通过调用android系统自带的浏览器进行授权认证的,使用该种方式能很容易的完成认证,但是该种方式有个弊端,也就是如果使用第三方的浏览器如UC.天天等,输入完QQ账号信息点击" ...
- Android通讯录开发之获取运营商号码段(移动、联通、电信)
本篇博客是自己在开发时用到的一个点,获取运营商的号码段,截至2013年12月30日,三大运营商的号码段增加了不少,还出现了1700这样4位的号码段.号码段有什么用呢?每个运营商都有不同的号码段,比如1 ...
- android 获取wifi的加密类型,Android WIFI开发:获取wifi列表,连接指定wifi,获取wifi加密方式,监听wifi网络变化等...
下面是 Android 开发中 WiFi 的常用配置,如:获取当前 WiFi ,扫描 WiFi 获取列表,连接指定 WiFi ,监听网络变化等等. 下面是效果图: GitHub 下载地址:https: ...
- 7.腾讯微博Android客户端开发——自动获取验证码(1)
通过前面的介绍,我们成功获取了Access Token,但是在该过程中有个不好的地方:用户输入完QQ信息后,需要记录验证码,然后返回至Activity手动输入验证码,这将会使我们的程序显得非常不友好. ...
- Android Studio开发之获取Apk相关版本信息
序言: 本博客备忘一下,如何获取Apk的app名称,包名以及VersonName等等信息! 将这些方式封装成类,并给出调用示例.希望可以帮助到一些同道中人. 正文: 1.类的封装,直接附上源码: 类名 ...
- android蓝牙开发简单获取android设备已经连接过(已适配)的蓝牙设备信息
本文没有深入到如何搜索蓝牙,如何适配蓝牙(既然android系统本身有这部分功能,不需要的情况下就由系统完成就行) 本文主要是获取已适配的蓝牙设备
最新文章
- python用于什么-Python用于哪些领域
- 恩施茶旅谋定乡村-农业大健康·万祥军:侗乡第一寨促生态
- 优化PHP程序的方法(温故知新)
- 房贷断供会有什么严重后果?
- php访问mysql函数吗,PHP访问MySQL数据库函数简介
- LeetCode 733. 图像渲染(DFS/BFS)
- “绿色高效 模块智能”金融业数据中心系列规范发布会将于12月7日召开
- java中mvc事务_Spring MVC 事务配置
- Java之多线程断点下载的实现
- HMM、MEMM、CRF模型的比较
- 【Unity Shader入门】☀️ | 使用Shader实现一个彩虹球效果✨!闪闪发光的特效离我又近了一步!
- 离散数学7__第2章命题逻辑的推理理论__主析取范式和主合取范式
- Android 项目正式签名打包教程
- 关于4418开发和6818开发
- Eclipse的Debug调试技巧大全
- 谢烟客---------Linux之CentOS 7 systemd
- matlab解决力学问题程序,力学专业程序实践:用MATLAB解决力学问题的方法与实例...
- 白嫖几十款的微信红包封面
- ADSL后台初始密码大全
- Python 发送每日新闻