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

公司刚好让做即时通讯模块,服务器使用openfire,偶然看到有位仁兄的帖子,拷贝过来细细研究,感谢此仁兄的无私,期待此仁兄的下次更新

转自http://blog.csdn.net/lnb333666/article/details/7476177

 

Android基于XMPP Smack openfire 开发的聊天室(一)【会议服务、聊天室列表、加入】

        废话少说,公司没事干,组长叫我写Demo,我狂晕....

        先把先说说这个什么聊天室吧,服务器就别说了,典型的拿来主义。用的是成品的openfire。说道smack,这个是一个jar文件,库,是用在javae的。要想在android端使用这个,就要用到asmack包,这个可以在官网下。其实里边跟smack包没什么区别,具体差异目前我没发现。

        可能有的朋友说这个smack是什么用的,我个人一句话,一个已经包装了XMPP协议的架包。提供了API的操作...好了进入正题

 

1,首先想进入聊天室,那必须要先知道聊天室所在的会议服务(下图,用spark截图)

Android基于XMPP Smack openfire 开发的聊天室_第1张图片

[java]  view plain copy print ?
  1. /** 
  2.      * 初始化聊服务会议列表 
  3.      */  
  4.     private void initHostRoom() {  
  5.         Collection<HostedRoom> hostrooms;  
  6.         try {  
  7.             hostrooms = MultiUserChat.getHostedRooms(Constants.conn,  
  8.                     Constants.conn.getServiceName());  
  9.             for (HostedRoom entry : hostrooms) {  
  10.                 roominfos.add(entry);  
  11.                 Log.i(TAG, "名字:" + entry.getName() + " - ID:" + entry.getJid());  
  12.             }  
  13.             Log.i(TAG, "服务会议数量:" + roominfos.size());  
  14.         } catch (XMPPException e) {  
  15.             e.printStackTrace();  
  16.         }  
  17.     }  

 

2,获取了那个服务的JID后才能进入会议列表:

Android基于XMPP Smack openfire 开发的聊天室_第2张图片

[java]  view plain copy print ?
  1. /** 
  2.      * 初始化房间列表 
  3.      */  
  4.     public void init() {  
  5.         listDiscoverItems = new ArrayList<DiscoverItems.Item>();  
  6.         // 获得与XMPPConnection相关的ServiceDiscoveryManager  
  7.         ServiceDiscoveryManager discoManager = ServiceDiscoveryManager  
  8.                 .getInstanceFor(Constants.conn);  
  9.   
  10.         // 获得指定XMPP实体的项目  
  11.         // 这个例子获得与在线目录服务相关的项目  
  12.         DiscoverItems discoItems;  
  13.         try {  
  14.             discoItems = discoManager.discoverItems(jid);  
  15.             // 获得被查询的XMPP实体的要查看的项目  
  16.             Iterator it = discoItems.getItems();  
  17.             // 显示远端XMPP实体的项目  
  18.             while (it.hasNext()) {  
  19.                 DiscoverItems.Item item = (DiscoverItems.Item) it.next();  
  20.                 System.out.println(item.getEntityID());  
  21.                 System.out.println(item.getName());  
  22.                 listDiscoverItems.add(item);  
  23.             }  
  24.         } catch (XMPPException e) {  
  25.             e.printStackTrace();  
  26.         }  
  27.     }  


3,同样,要进入会议房间(聊天室)也要获取它的ID,才能进入

 

[java]  view plain copy print ?
  1. // 后面服务名称必需是创建房间的那个服务  
  2.         jid = getIntent().getStringExtra("jid");  
  3.         try {  
  4.             muc = new MultiUserChat(Constants.conn, jid);  
  5.             // 创建聊天室,进入房间后的nickname(昵称)  
  6.             muc.join("痞子测试");  
  7.             Log.v(TAG, "join success");  
  8.         } catch (XMPPException e) {  
  9.             e.printStackTrace();  
  10.         }  


简单吧!

 

Android基于XMPP Smack openfire 开发的聊天室(二) 【聊天信息、成员】

       上一篇呢说了怎么进入这个聊天室,这次呢,咱就说聊天室里的功能吧,聊天信息、成员变动什么的。还是少说废话,正题:

1,说要聊天呢,简单就是一个文本信息,当然我们不能时时去服务器获取信息。要充分发挥即时推送嘛。

         (1)首先要添加一个监听,muc.addMessageListener(chatListener);   要是muc不知道是什么请看上一篇吧,这就不多解释。chatListener就是我们的监听器,看代码,其实下边的代码有些啰嗦。我只是懒得改了。最近有点烦躁。这里我们主要获取的就是Packet,这个是一个XMPP包装好的XML流,里边有你想要的东西。有兴趣深入的朋友可以上XMPP中文翻译组去看看,挺犀利的。

[java]  view plain copy print ?
  1. /** 
  2.      * PacketListener 通过一个规定的过滤器提供一个机制来监听数据包 
  3.      *  
  4.      * @author liaonaibo 
  5.      *  
  6.      */  
  7.     class ChatPacketListener implements PacketListener {  
  8.         private String _number;  
  9.         private Date _lastDate;  
  10.         private MultiUserChat _muc;  
  11.         private String _roomName;  
  12.   
  13.         public ChatPacketListener(MultiUserChat muc) {  
  14.             _number = "0";  
  15.             _lastDate = new Date(0);  
  16.             _muc = muc;  
  17.             _roomName = muc.getRoom();  
  18.         }  
  19.   
  20.         @Override  
  21.         public void processPacket(Packet packet) {  
  22.             Message message = (Message) packet;  
  23.             String from = message.getFrom();  
  24.   
  25.             if (message.getBody() != null) {  
  26.                 DelayInformation inf = (DelayInformation) message.getExtension(  
  27.                         "x""jabber:x:delay");  
  28.                 Date sentDate;  
  29.                 if (inf != null) {  
  30.                     sentDate = inf.getStamp();  
  31.                 } else {  
  32.                     sentDate = new Date();  
  33.                 }  
  34.   
  35.                 Log.i(TAG, "Receive old message: date="  
  36.                         + sentDate.toLocaleString() + " ; message="  
  37.                         + message.getBody());  
  38.   
  39.                 android.os.Message msg = new android.os.Message();  
  40.                 msg.what = RECEIVE;  
  41.                 Bundle bd = new Bundle();  
  42.                 bd.putString("from", from);  
  43.                 bd.putString("body", message.getBody());  
  44.                 msg.setData(bd);  
  45.                 handler.sendMessage(msg);  
  46.             }  
  47.         }  
  48.     }  


2,下边就是成员了,一个聊天室没成员多离谱的事情啊,我们主要做的是把成员列表逃出来。其实有几种方法可以弄出来的,我只是简单的获取成员的昵称。可能有朋友会问为什么不获取成员的信息呢。这个下一篇我会告诉你。

[java]  view plain copy print ?
  1. /** 
  2.      * 获取聊天室的所有成员 
  3.      */  
  4.     private void getAllMember() {  
  5.         Log.i(TAG, "获取聊天室的所有成员");  
  6.         affiliates.clear();  
  7.           
  8.         new Thread(new Runnable() {  
  9.             @Override  
  10.             public void run() {  
  11.                 try {  
  12.                     Iterator<String> it = muc.getOccupants();  
  13.                     while (it.hasNext()) {  
  14.                         String name = it.next();  
  15.                         name = name.substring(name.indexOf("/") + 1);  
  16.                         affiliates.add(name);  
  17.                         Log.i(TAG, "成员名字;" + name);  
  18.                     }  
  19.   
  20.                 } catch (Exception e) {  
  21.                     e.printStackTrace();  
  22.                 }  
  23.   
  24.                 android.os.Message msg = new android.os.Message();  
  25.                 msg.what = MEMBER;  
  26.                 handler.sendMessage(msg);  
  27.             }  
  28.         }).start();  
  29.     }  


这篇结束,下篇写写聊天室的一些权限的变更、成员的变更、主题变更什么的。

Android基于XMPP Smack openfire 开发的聊天室(三) 【新旧记录、踢人】

1,聊天室新旧消息的记录,先看看一段服务器返回的XML吧
[html]  view plain copy print ?
  1. <message  
  2.     from='[email protected]/firstwitch'  
  3.     to='[email protected]/broom'  
  4.     type='groupchat'>  
  5.   <body>Thrice the brinded cat hath mew'd.</body>  
  6.   <delay xmlns='urn:xmpp:delay'  
  7.      from='[email protected]/desktop'  
  8.      stamp='2002-10-13T23:58:37Z'/>  
  9. </message>  
  10.    
  11. <message  
  12.     from='[email protected]/secondwitch'  
  13.     to='[email protected]/broom'  
  14.     type='groupchat'>  
  15.   <body>Thrice and once the hedge-pig whined.</body>  
  16.   <delay xmlns='urn:xmpp:delay'  
  17.      from='[email protected]/laptop'  
  18.      stamp='2002-10-13T23:58:43Z'/>  
  19. </message>  
  20.    
  21. <message  
  22.     from='[email protected]/thirdwitch'  
  23.     to='[email protected]/broom'  
  24.     type='groupchat'>  
  25.   <body>Harpier cries 'Tis time, 'tis time.</body>  
  26.   <delay xmlns='urn:xmpp:delay'  
  27.      from='[email protected]/pda'  
  28.      stamp='2002-10-13T23:58:49Z'/>  
  29. </message>  


上边这段是一个聊天室返回的XML数据,是历史消息。就在这里要告诉大家的是,如果是新消息的话就没有<delay>节点。所以我们以这个为根据来判断。下边贴些我的代码,因为服务器被我们给改了,所以返回的有些出入。但八九不离十。原理一样。

[java]  view plain copy print ?
  1. DelayInformation inf = (DelayInformation) message.getExtension(  
  2.                         "x""jabber:x:delay");  
  3.                 System.out.println("判断消息");  
  4.                 if (inf == null && count >= 1) {  
  5.                     System.out.println("新消息来了");  
  6.                     isHistory = true;  
  7.                 } else {  
  8.                     System.out.println("这是旧的消息");  
  9.                 }  


 

这段代码写哪里呢,就是写在消息的监听里头

[java]  view plain copy print ?
  1. /** 
  2.      * PacketListener 通过一个规定的过滤器提供一个机制来监听数据包 
  3.      *  
  4.      * @author liaonaibo 
  5.      *  
  6.      */  
  7.       
  8.     class ChatPacketListener implements PacketListener   


 

重写它的方法
[java]  view plain copy print ?
  1. @Override  
  2.         public void processPacket(Packet packet)  


 

好了,下边讲踢人吧

2,踢人:

        踢人很简单,只要你是房主,或管理员什么的,主持人也行。这些高权限的才能有踢人的权限。

[java]  view plain copy print ?
  1. // 踢人  
  2.             try {  
  3.                 String nickName = affiliates.get(id);  
  4.                 //得到的昵称包含的房间名和服务名的一段很长数据。好像是吧。哈哈,忘记了。所以截取吧  
  5.                 muc.kickParticipant(nickName  
  6.                         .substring(nickName.indexOf("]") + 1), "看你不爽就 踢了你");  
  7.                 android.os.Message msg = new android.os.Message();  
  8.                 msg.what = MEMBER;  
  9.                 handler.sendMessage(msg);  
  10.                 Toast.makeText(this"哈哈,踹了你", Toast.LENGTH_LONG).show();  
  11.             } catch (XMPPException e) {  
  12.                 e.printStackTrace();  
  13.                 Toast.makeText(this"你没有权利踢人", Toast.LENGTH_LONG).show();  
  14.             }  

有的哥们会疑惑,说如果根据昵称来踢人,那会不会把重名的人都一起踢了。这个问题我也想过,这个也是测试的一个弊端。但是如果通过spark来看,即便你用同样的名字加入了房间,要么会报错,要么就是系统自动在你的名字后边加个2,呵呵,够2吧。如果有人坚持要用自己的昵称,这个可以的,具体怎么样做,下次再阐述。

 

Android基于XMPP Smack openfire 开发的聊天室(四) 【创建房间、表单;报文】

这篇就主要讲创建房间和报文吧。

1,创建房间:

其实创建房间很简单,两句话就搞定了。但你要知道,简单的同时,服务器可没帮你配置房间的信息什么的。所以一般用下边的方法来创建房间别人是进不去的。

[java]  view plain copy print ?
  1. // 使用XMPPConnection创建一个MultiUserChat  
  2.       MultiUserChat muc = new MultiUserChat(conn1, "[email protected]");  
  3.   
  4.       //创建聊天室  
  5.       muc.create("testbot");  
  6.   
  7.       // 发送一个空表单配置这显示我们想要一个instant room  
  8.         
  9.       muc.sendConfigurationForm(new Form(Form.TYPE_SUBMIT));  


所以咱们还是手动配置一些信息吧,免得留后患。不过在这里要给朋友们提个醒,我觉得不论是哪种方法都很狗屎,为什么狗屎。你看看那MUC,本来就是一个聊天室了,还要让你在聊天室创建另个聊天室,老妈生孩子,然后孩子和老妈并排。狗屎啊,不过不排除我理解错误。希望高人能给与指点。

[java]  view plain copy print ?
  1. try {  
  2.             // 创建聊天室  
  3.             muc.create(Constants.vCard.getNickName().toString());  
  4.             // 获得聊天室的配置表单  
  5.             Form form = muc.getConfigurationForm();  
  6.             // 根据原始表单创建一个要提交的新表单。  
  7.             Form submitForm = form.createAnswerForm();  
  8.             // 向要提交的表单添加默认答复  
  9.             for (Iterator fields = form.getFields(); fields.hasNext();) {  
  10.                 FormField field = (FormField) fields.next();  
  11.                 if (!FormField.TYPE_HIDDEN.equals(field.getType())  
  12.                         && field.getVariable() != null) {  
  13.                     // 设置默认值作为答复  
  14.                     submitForm.setDefaultAnswer(field.getVariable());  
  15.                 }  
  16.             }  
  17.             // 设置聊天室的新拥有者  
  18.             // List owners = new ArrayList();  
  19.             // owners.add("liaonaibo2\\40slook.cc");  
  20.             // owners.add("liaonaibo1\\40slook.cc");  
  21.             // submitForm.setAnswer("muc#roomconfig_roomowners", owners);  
  22.             // 设置聊天室是持久聊天室,即将要被保存下来  
  23.             submitForm.setAnswer("muc#roomconfig_persistentroom"true);  
  24.             // 房间仅对成员开放  
  25.             submitForm.setAnswer("muc#roomconfig_membersonly"false);  
  26.             // 允许占有者邀请其他人  
  27.             submitForm.setAnswer("muc#roomconfig_allowinvites"true);  
  28.             // 能够发现占有者真实 JID 的角色  
  29.             // submitForm.setAnswer("muc#roomconfig_whois", "anyone");  
  30.             // 登录房间对话  
  31.             submitForm.setAnswer("muc#roomconfig_enablelogging"true);  
  32.             // 仅允许注册的昵称登录  
  33.             submitForm.setAnswer("x-muc#roomconfig_reservednick"true);  
  34.             // 允许使用者修改昵称  
  35.             submitForm.setAnswer("x-muc#roomconfig_canchangenick"false);  
  36.             // 允许用户注册房间  
  37.             submitForm.setAnswer("x-muc#roomconfig_registration"false);  
  38.             // 发送已完成的表单(有默认值)到服务器来配置聊天室  
  39.             muc.sendConfigurationForm(submitForm);  
  40.         } catch (XMPPException e) {  
  41.             e.printStackTrace();  
  42.         }  

 

还有个细节,有朋友估计看到我注释的那里有\\40的代码。原因是在XMPP中的唯一标示JID不允许出现@,所以要转义。OK?

 

2,报文
有朋友说报文干嘛,其实我开始也觉得有点多余,但想想类似QQ群那样,人下线了,头像名字变灰色。如果是openfire服务器的话,你下线了就直接把你去除。所以我们要给服务器发送个广播。具体处理那是以后的是了。看看这段报文:

[html]  view plain copy print ?
  1. <iq id="902U0-48" type="set">  
  2.                 <query xmlns="jabber:iq:private">  
  3.                     <storage xmlns="storage:bookmarks">  
  4.                         <conference name="ccc" autojoin="true" jid="[email protected]" ></conference>  
  5.                     </storage>  
  6.             </query>  
  7.         </iq>  


报文可以根据需要来改服务器的插件。

下边发送的报文:

[java]  view plain copy print ?
  1. /** 
  2.      * 用户加入时向服务器发送的报文 
  3.      * @return 
  4.      */  
  5.     public IQ joinXml(){  
  6.         IQ iq = new IQ() {  
  7.             public String getChildElementXML() {  
  8.                 StringBuilder buf = new StringBuilder();  
  9.                 buf.append("<query xmlns=\"jabber:iq:private\">");  
  10.                 buf.append("<storage xmlns=\"storage:bookmarks\">");  
  11.                 buf.append("<").append("conference").append(" name=\"ccc\"").append(" autojoin=\"false\"").append("");  
  12.                 buf.append("</storage>");  
  13.                 buf.append("</query>");  
  14.                 return buf.toString();  
  15.             }  
  16.         };  
  17.         iq.setType(IQ.Type.SET);  
  18.         //方法如名,这里是设置这份报文来至那个JID,后边的/smack是这段信息来至哪个端,如spark端就是/spark,android就是/Smack  
  19.         iq.setFrom(Constants.USERNAME+"@naibo.liao.com/Smack");  
  20.         return iq;  
  21.     }  

怎么发送呢?可以通过连接,就是XMPPCONNECTION来发送:

[java]  view plain copy print ?
  1. Constants.conn.sendPacket(leaveXml());  


OK,停一会,手酸了

 

Android基于XMPP Smack openfire 开发的聊天室(五) 【邀请、被邀请】

1,邀请:

很简单的一句话,邀请的时候要传入被邀请者的JID,邀请信息可以为空。

 

[java]  view plain copy print ?
  1. muc.invite(userjid, "进来我们聊妹子");  


 

简单的同时我们要知道它发生了什么,当这句话执行会向服务器发送一段报文,如下:

[html]  view plain copy print ?
  1. <message  
  2.         from='[email protected]/desktop'  
  3.         to='[email protected]'>  
  4.       <x xmlns='http://jabber.org/protocol/muc#user'>  
  5.         <invite to='[email protected]'>  
  6.           <reason>  
  7.             进来我们聊妹子  
  8.           </reason>  
  9.         </invite>  
  10.       </x>  
  11.     </message>  


2,被邀请

被邀请呢,我们可以开个监听吧,要不要进房间先不判断了,我这里如果有邀请就直接进房间。有需要的朋友可以自己琢磨:

[java]  view plain copy print ?
  1. MultiUserChat.addInvitationListener(Constants.conn,  
  2.                 new InvitationListener() {  
  3.                     // 对应参数:连接、 房间JID、房间名、附带内容、密码、消息  
  4.                     @Override  
  5.                     public void invitationReceived(Connection conn,  
  6.                             String room, String inviter, String reason,  
  7.                             String password, Message message) {  
  8.   
  9.                         Log.i(TAG, "收到来自 " + inviter + " 的聊天室邀请。邀请附带内容:"  
  10.                                 + reason);  
  11.   
  12.                         Intent intent = new Intent(MucService.this,  
  13.                                 ActivityMultiRoom.class);  
  14.                         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
  15.                         intent.putExtra("jid", room);  
  16.                         intent.putExtra("action""join");  
  17.                         startActivity(intent);  
  18.                     }  
  19.                 });  
 

Android基于XMPP Smack openfire 开发的聊天室(六) 【加入房间、权限错误】

1,加入房间错误,通常一个就是密码错误。此时服务器会返回以下报文:

[html]  view plain copy print ?
  1. <presence  
  2.     from='[email protected]'  
  3.     to='[email protected]/pda'  
  4.     type='error'>  
  5.   <x xmlns='http://jabber.org/protocol/muc'/>  
  6.   <error type='auth'>  
  7.     <not-authorized xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>  
  8.   </error>  
  9. </presence>  


 

官网意思:如果房间要求密码验证而用户不能提供(或密码错误), 服务必须 MUST 拒绝访问这个房间并且通知该用户它们是未被授权的; 具体方法是返回一个类型为"error"的出席信息节并标明 <not-authorized/> 错误

解决如下:

[java]  view plain copy print ?
  1. // 使用XMPPConnection创建一个MultiUserChat  
  2.             MultiUserChat muc2 = new MultiUserChat(conn1,  
  3.                     "[email protected]/thirdwitch");  
  4.   
  5.             // 用户2使用密码加入新聊天室  
  6.             // 聊天室服务将会决定要发送的历史记录数量  
  7.             muc2.join("testbot2""password");  


报文如下:

[html]  view plain copy print ?
  1. <presence  
  2.             from='[email protected]/pda'  
  3.             to='[email protected]/thirdwitch'>  
  4.           <x xmlns='http://jabber.org/protocol/muc'>  
  5.             <password>password</password>  
  6.           </x>  
  7.         </presence>  


2,权限错误:

这个没文本,当然如果你加入一个房间后,要注意的是,如果第一次加入别人的房间,没有被授予成员权限的时候,你仅仅是一个游客。除了说话。也不能检索聊天室成员的信息,仅可以获取成员的昵称,除此别无其他。通常不注意会用这样贸然去获取成员信息是,会照成错误,返回402(进入房间后获取超越权限错误:权限不足)等信息。以下是其他错误信息

 

401 Error Presence  进入一个房间

通知用户需要密码

403 Error Presence  进入一个房间 通知用户他或她被房间禁止了
404 Error Presence  进入一个房间 通知用户房间不存在
405 Error Presence  进入一个房间 通知用户限制创建房间
406 Error Presence  进入一个房间 通知用户必须使用保留的房间昵称
407 Error Presence  进入一个房间 通知用户他或她不在成员列表中
409 Error Presence  进入一个房间 通知用户他或她的房间昵称正在使用或被别的用户注册了
503 Error Presence  进入一个房间 通知用户已经达到最大用户数

用户聊天的使用一个 <status/> 元素(特指, <status/> 元素的的 'code' 属性  ) 来传达关于用户在一个房间里的状态的信息.

 

Android基于XMPP Smack openfire 开发的聊天室(七) 【成员状态、自身状态】

1,聊天是成员的监听,加到MUC里边就行

[java]  view plain copy print ?
  1. /** 
  2.      * 聊天室成员的监听器 
  3.      *  
  4.      * @author 廖乃波 
  5.      *  
  6.      */  
  7.     class MyParticipantStatusListener implements ParticipantStatusListener {  
  8.   
  9.         @Override  
  10.         public void adminGranted(String arg0) {  
  11.             Log.i(TAG, "授予管理员权限" + arg0);  
  12.         }  
  13.   
  14.         @Override  
  15.         public void adminRevoked(String arg0) {  
  16.             Log.i(TAG, "移除管理员权限" + arg0);  
  17.         }  
  18.   
  19.         @Override  
  20.         public void banned(String arg0, String arg1, String arg2) {  
  21.             Log.i(TAG, "禁止加入房间(拉黑,不知道怎么理解,呵呵)" + arg0);  
  22.         }  
  23.   
  24.         @Override  
  25.         public void joined(String arg0) {  
  26.             Log.i(TAG, "执行了joined方法:" + arg0 + "加入了房间");  
  27.             // 更新成员  
  28.             getAllMember();  
  29.             android.os.Message msg = new android.os.Message();  
  30.             msg.what = MEMBER;  
  31.             handler.sendMessage(msg);  
  32.         }  
  33.   
  34.         @Override  
  35.         public void kicked(String arg0, String arg1, String arg2) {  
  36.             Log.i(TAG, "踢人" + arg0 + "被踢出房间");  
  37.         }  
  38.   
  39.         @Override  
  40.         public void left(String arg0) {  
  41.             String lefter = arg0.substring(arg0.indexOf("/") + 1);  
  42.             Log.i(TAG, "执行了left方法:" + lefter + "离开的房间");  
  43.             // 更新成员  
  44.             getAllMember();  
  45.             android.os.Message msg = new android.os.Message();  
  46.             msg.what = MEMBER;  
  47.             handler.sendMessage(msg);  
  48.         }  
  49.   
  50.         @Override  
  51.         public void membershipGranted(String arg0) {  
  52.             Log.i(TAG, "授予成员权限" + arg0);  
  53.         }  
  54.   
  55.         @Override  
  56.         public void membershipRevoked(String arg0) {  
  57.             Log.i(TAG, "成员权限被移除" + arg0);  
  58.         }  
  59.   
  60.         @Override  
  61.         public void moderatorGranted(String arg0) {  
  62.             Log.i(TAG, "授予主持人权限" + arg0);  
  63.         }  
  64.   
  65.         @Override  
  66.         public void moderatorRevoked(String arg0) {  
  67.             Log.i(TAG, "移除主持人权限" + arg0);  
  68.         }  
  69.   
  70.         @Override  
  71.         public void nicknameChanged(String arg0, String arg1) {  
  72.             Log.i(TAG, "昵称改变了" + arg0);  
  73.         }  
  74.   
  75.         @Override  
  76.         public void ownershipGranted(String arg0) {  
  77.             Log.i(TAG, "授予所有者权限" + arg0);  
  78.         }  
  79.   
  80.         @Override  
  81.         public void ownershipRevoked(String arg0) {  
  82.             Log.i(TAG, "移除所有者权限" + arg0);  
  83.         }  
  84.   
  85.         @Override  
  86.         public void voiceGranted(String arg0) {  
  87.             Log.i(TAG, "给" + arg0+"授权发言");  
  88.         }  
  89.   
  90.         @Override  
  91.         public void voiceRevoked(String arg0) {  
  92.             Log.i(TAG, "禁止" + arg0+"发言");  
  93.         }  
  94.     }  


2,自身状态监听

[java]  view plain copy print ?
  1. class MyUserStatusListener  implements UserStatusListener {  
  2.         /*这里实现默认方法即可*/  
  3.     }  

都一样,看不懂可以有道翻译,累了,睡觉先。


你可能感兴趣的:(android,String,smack,聊天,XMPP)