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,告知是否同意。如下:

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

再加点东西吧,就是断线自动重连。
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.                                 }
复制代码

个人浅见,技术的提升在于交流。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
获取好友列表和加入好友都是 XMPP 协议中常见的操作,可以使用 XMPP 客户端库来实现。 获取好友列表: 获取好友列表需要先建立与服务器的连接,然后向服务器发送获取好友列表的请求,服务器会返回当前用户的好友列表。 在使用 XMPP 客户端库时,可以通过调用 `getRoster()` 方法来获取好友列表: ```java Roster roster = connection.getRoster(); Collection<RosterEntry> entries = roster.getEntries(); for (RosterEntry entry : entries) { System.out.println(entry.getName() + " (" + entry.getUser() + ")"); } ``` 这段代码会输出当前用户的好友列表,每个好友的名称和 JID。 加入好友: 加入好友需要知道好友的 JID,然后向服务器发送加入好友的请求,服务器会向好友发送一个订阅请求,好友同意后就成为了当前用户的好友。 在使用 XMPP 客户端库时,可以通过调用 `sendPacket()` 方法来发送加入好友的请求: ```java Presence subscribe = new Presence(Presence.Type.subscribe); subscribe.setTo(buddyJID); connection.sendPacket(subscribe); ``` 这段代码会向好友发送一个订阅请求,其中 `buddyJID` 是好友的 JID。 好友同意后,当前用户会收到一个订阅通知,可以通过监听 `RosterListener` 的 `entriesAdded()` 方法来处理: ```java roster.addRosterListener(new RosterListener() { public void entriesAdded(Collection<String> addresses) { for (String address : addresses) { System.out.println("New buddy added: " + address); } } // ... }); ``` 这段代码会在当前用户的好友列表中添加新的好友,并输出好友的 JID。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值