国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android中基于XMPP協議實現IM聊天程序與多人聊天室

2020-04-11 10:45:00
字體:
來源:轉載
供稿:網友

簡單的IM聊天程序
由于項目需要做一個基于XMPP協議的Android通訊軟件。故開始研究XMPP。
XMPP協議采用的是客戶端-服務器架構,所有從一個客戶端發到另一個客戶端的消息和數據都必須經過XMPP服務器轉發,而且支持服務器間DNS的路由,也就是說可以構建服務器集群,使不同的

服務器下的客戶端也可以通信,XMPP的前身是一個開源組織制定的網絡通信協議――Jabber,XMPP的核心是在網絡上分片段發送XML流的協議,這個協議是XMPP的即時通訊指令的傳遞手段。
      為了防止服務器間發送的數據被篡改或偷聽,XMPP服務器通信引入了TLS機制,使用TLS機制能實現數據的加密,從而保證了在數據傳輸過程種數據的安全。
      一個XMPP實體的地址稱為Jabber Identifier或JID,作用類似于IP地址。一個合法的JID包括節點名,域名資源名,其格式為:jid=[node'@']domain['/'resource]

XMPP協議的命名空間:

  • jabber:iq:private   -- 私有數據存儲,用于本地用戶私人設置信息,比如用戶備注等。
  • jabber:iq:conference  -- 一般會議,用于多個用戶之間的信息共享
  • jabber:x:encrypted -- 加密的消息,用于發送加密消息
  • jabber:x:expire  -- 消息終止
  • jabber:iq:time  -- 客戶端時間
  • jabber:iq:auth  -- 簡單用戶認證,一般用于服務器之間或者服務器和客戶端之間的認證
  • jabber:x:roster  -- 內部花名冊
  • jabber:x:signed  -- 標記的在線狀態
  • jabber:iq:search -- 用戶數據庫查詢,用于向服務器發送查詢請求
  • jabber:iq:register -- 注冊請求,用于用戶注冊相關信息
  • jabber:x:iq:roster -- 花名冊管理
  • jabber:x:conference -- 會議邀請,用于向參加會議用戶發送開會通知
  • jabber:x:event  -- 消息事件
  • vcard-temp  -- 臨時的vCard,用于設置用戶的頭像以及昵稱等

 在網上找了下,有開源的項目BEEM,開源的用于android的xmpp框架asmack,asmack是smack的android版本。現在開始學習smack

。Xmpp就是神馬東西,就不廢話了。首先在網上下一個Openfire和Spack,不知道這兩個是什么東西,就直接google吧。安裝openfire需要mysql的支持,當然,oracle,sqlserver肯定是可以的。還是先上圖吧:

Openfire + Spark + MyXMPPP

2016224155319690.gif (1024×394)

2016224155354184.gif (518×647)

import java.io.InputStreamReader; import java.util.Collection;  import org.jivesoftware.smack.Chat; import org.jivesoftware.smack.ChatManager; import org.jivesoftware.smack.ChatManagerListener; import org.jivesoftware.smack.ConnectionConfiguration; import org.jivesoftware.smack.MessageListener; import org.jivesoftware.smack.PrivacyListManager; import org.jivesoftware.smack.Roster; import org.jivesoftware.smack.RosterEntry; import org.jivesoftware.smack.RosterGroup; import org.jivesoftware.smack.RosterListener; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Presence;  public class TestSmack {   public static void main(String[] args) {XMPPConnection.DEBUG_ENABLED = true;     //我的電腦IP:10.16.25.90     final ConnectionConfiguration connectionConfig = new ConnectionConfiguration("10.16.25.91", 5222, "");     connectionConfig.setSASLAuthenticationEnabled(false);         try {                      XMPPConnection connection = new XMPPConnection(connectionConfig);           connection.connect();//連接           connection.login("test", "test");//登陸           System.out.println(connection.getUser());           ChatManager chatmanager = connection.getChatManager();            //新建一個會話           Chat newChat = chatmanager.createChat("test3@pc2010102716", new MessageListener() {             public void processMessage(Chat chat, Message message) {               System.out.println("Received from 【" + message.getFrom() + "】 message: " + message.getBody());             }           });                      // 監聽被動接收消息,或廣播消息監聽器           chatmanager.addChatListener(new ChatManagerListener() {             @Override             public void chatCreated(Chat chat, boolean createdLocally) {               chat.addMessageListener(new MessageListener() {                 @Override                 public void processMessage(Chat chat, Message message) {                   System.out.println("Received from 【" + message.getFrom() + "】 message: " + message.getBody());                 }                                  });             }           });           //發送消息           newChat.sendMessage("我是菜鳥");                      //獲取花名冊           Roster roster = connection.getRoster();           Collection<RosterEntry> entries = roster.getEntries();           for(RosterEntry entry : entries) {             System.out.print(entry.getName() + " - " + entry.getUser() + " - " + entry.getType() + " - " + entry.getGroups().size());             Presence presence = roster.getPresence(entry.getUser());             System.out.println(" - " + presence.getStatus() +" - "+ presence.getFrom());           }                      //添加花名冊監聽器,監聽好友狀態的改變。           roster.addRosterListener(new RosterListener() {              @Override             public void entriesAdded(Collection<String> addresses) {               System.out.println("entriesAdded");             }              @Override             public void entriesUpdated(Collection<String> addresses) {               System.out.println("entriesUpdated");             }              @Override             public void entriesDeleted(Collection<String> addresses) {               System.out.println("entriesDeleted");             }              @Override             public void presenceChanged(Presence presence) {               System.out.println("presenceChanged - >" + presence.getStatus());             }                        });                      //創建組 //         /RosterGroup group = roster.createGroup("大學"); //         for(RosterEntry entry : entries) { //           group.addEntry(entry); //         }           for(RosterGroup g : roster.getGroups()) {             for(RosterEntry entry : g.getEntries()) {               System.out.println("Group " +g.getName() +" >> " + entry.getName() + " - " + entry.getUser() + " - " + entry.getType() + " - " + entry.getGroups().size());             }           }                      //發送消息           BufferedReader cmdIn = new BufferedReader(new InputStreamReader(System.in));           while(true) {            try {              String cmd = cmdIn.readLine();              if("!q".equalsIgnoreCase(cmd)) {                break;              }              newChat.sendMessage(cmd);            }catch(Exception ex) {            }           }           connection.disconnect();           System.exit(0);         } catch (Exception e) {           e.printStackTrace();         }   } } 

以上代碼如果在一般的Java Project上運行需要加入smack.jar 和klmx2.jar,如果是Android Project,基本代碼不需改變只需將其放入onCreate(...)方法下即可,需要加入asmack.jar包.

1、ConnectionConfiguration
 作為用于與XMPP服務建立連接的配置。它能配置;連接是否使用TLS,SASL加密。
 包含內嵌類:ConnectionConfiguration.SecurityMode

2、XMPPConnection.
 XMPPConnection這個類用來連接XMPP服務.
 可以使用connect()方法建立與服務器的連接。disconnect()方法斷開與服務器的連接.
 在創建連接前可以使用XMPPConnection.DEBUG_ENABLED = true; 使開發過程中可以彈出一個GUI窗口,用于顯示我們的連接與發送Packet的信息。

2016224155444002.gif (713×349)

3、ChatManager
 用于監控當前所有chat。可以使用createChat(String userJID, MessageListener listener)創建一個聊天。
 
4、Chat
 Chat用于監控兩個用戶間的一系列message。使用addMessageListener(MessageListener listener)當有任何消息到達時將會觸發listener的processMessage(Chat chat, Message message)
方法.
 我們可以使用sendMessage()發送消息,這個方法有兩個重載方法,一種類類型的參數時String類型,另一種則是傳入Message對象(后面介紹)。
 那么有這樣一種情況,當別人主動跟我們建立連接發送消息,或者系統發送消息時我們怎么才能接收消息呢?
    我現在是這樣操作的:

 chatmanager.addChatListener(new ChatManagerListener() { @Override public void chatCreated(Chat chat, boolean createdLocally) {  chat.addMessageListener(new MessageListener() {  @Override  public void processMessage(Chat chat, Message message) {   System.out.println("Received message: " + message.getBody());  }       }); } });

 
5、Message

  •  Message用于表示一個消息包(可以用調試工具看到發送包和接收包的具體內容)。它有以下多種類型。
  •   Message.Type.NORMAL -- (默認)文本消息(比如郵件)
  •   Message.Type.CHAT -- 典型的短消息,如QQ聊天的一行一行顯示的消息
  •   Message.Type.GROUP_CHAT -- 群聊消息
  •   Message.Type.HEADLINE -- 滾動顯示的消息
  •   Message.TYPE.ERROR -- 錯誤的消息
  •  Message有兩個內部類:
  •   Message.Body -- 表示消息體
  •   Message.Type -- 表示消息類型

6、Roster
 表示存儲了很多RosterEntry的一個花名冊.為了易于管理,花名冊的項被分貝到了各個group中.
 當建立與XMPP服務的連接后可以使用connection.getRoster()獲取Roster對象。
 別的用戶可以使用一個訂閱請求(相當于QQ加好友)嘗試訂閱目的用戶。可以使用枚舉類型Roster.SubscriptionMode的值處理這些請求:
 accept_all: 接收所有訂閱請求
 reject_all:拒絕所有訂閱請求
 manual:  手工處理訂閱請求
 
 創建組:RosterGroup group = roster.createGroup("大學");
 向組中添加RosterEntry對象: group.addEntry(entry);
 
7、RosterEntry
 表示Roster(花名冊)中的每條記錄.它包含了用戶的JID,用戶名,或用戶分配的昵稱.
 
8、RosterGroup
 表示RosterEntry的組。可以使用addEntry(RosterEntry entry)添加。contains(String user) 判斷某用戶是否在組中.當然removeEntry(RosterEntry entry)就是從組中移除了。getEntries()

獲取所有RosterEntry.
 
9、Presence
 表示XMPP狀態的packet。每個presence packet都有一個狀態。用枚舉類型Presence.Type的值表示:
 available -- (默認)用戶空閑狀態
 unavailable -- 用戶沒空看消息
 subscribe -- 請求訂閱別人,即請求加對方為好友
 subscribed -- 統一被別人訂閱,也就是確認被對方加為好友
 unsubscribe -- 他取消訂閱別人,請求刪除某好友
 unsubscribed -- 拒絕被別人訂閱,即拒絕對放的添加請求
 error -- 當前狀態packet有錯誤
 內嵌兩個枚舉類型:Presence.Mode和Presence.Type.
 可以使用setStatus自定義用戶當前的狀態(像QQ一樣的)


MultiUserChat聊天室

import java.io.BufferedReader;  import java.io.InputStreamReader;  import java.util.ArrayList;  import java.util.Collection;  import java.util.Iterator;  import java.util.List;   import org.jivesoftware.smack.Chat;  import org.jivesoftware.smack.ConnectionConfiguration;  import org.jivesoftware.smack.MessageListener;  import org.jivesoftware.smack.PacketListener;  import org.jivesoftware.smack.SmackConfiguration;  import org.jivesoftware.smack.XMPPConnection;  import org.jivesoftware.smack.XMPPException;  import org.jivesoftware.smack.packet.Message;  import org.jivesoftware.smack.packet.Packet;  import org.jivesoftware.smack.provider.ProviderManager;  import org.jivesoftware.smackx.Form;  import org.jivesoftware.smackx.FormField;  import org.jivesoftware.smackx.ServiceDiscoveryManager;  import org.jivesoftware.smackx.muc.DefaultParticipantStatusListener;  import org.jivesoftware.smackx.muc.DefaultUserStatusListener;  import org.jivesoftware.smackx.muc.DiscussionHistory;  import org.jivesoftware.smackx.muc.HostedRoom;  import org.jivesoftware.smackx.muc.InvitationListener;  import org.jivesoftware.smackx.muc.InvitationRejectionListener;  import org.jivesoftware.smackx.muc.MultiUserChat;  import org.jivesoftware.smackx.muc.RoomInfo;  import org.jivesoftware.smackx.muc.SubjectUpdatedListener;  import org.jivesoftware.smackx.packet.ChatStateExtension;  import org.jivesoftware.smackx.packet.DiscoverInfo;  import org.jivesoftware.smackx.packet.DiscoverItems;  import org.jivesoftware.smackx.packet.OfflineMessageInfo;  import org.jivesoftware.smackx.packet.OfflineMessageRequest;  import org.jivesoftware.smackx.provider.AdHocCommandDataProvider;  import org.jivesoftware.smackx.provider.BytestreamsProvider;  import org.jivesoftware.smackx.provider.DataFormProvider;  import org.jivesoftware.smackx.provider.DiscoverInfoProvider;  import org.jivesoftware.smackx.provider.DiscoverItemsProvider;  import org.jivesoftware.smackx.provider.IBBProviders;  import org.jivesoftware.smackx.provider.MUCAdminProvider;  import org.jivesoftware.smackx.provider.MUCOwnerProvider;  import org.jivesoftware.smackx.provider.MUCUserProvider;  import org.jivesoftware.smackx.provider.StreamInitiationProvider;  import org.jivesoftware.smackx.provider.VCardProvider;  import org.jivesoftware.smackx.provider.XHTMLExtensionProvider;   public class TestSmack2 {    public static void main(String[] args) {XMPPConnection.DEBUG_ENABLED = true;      final ConnectionConfiguration connectionConfig = new ConnectionConfiguration("PC2010102716", 5222, "");     connectionConfig.setSASLAuthenticationEnabled(false);      ProviderManager pm = ProviderManager.getInstance();      configure(pm);      try {        XMPPConnection connection = new XMPPConnection(connectionConfig);        connection.connect();//連接        initFeatures(connection);        connection.login("test", "test");//登陸        //聊天室        //MultiUserChat multiUserChat = new MultiUserChat(connection, new InvitationListener() {});        //查找服務        System.out.println(connection.getServiceName());        List<String> col = getConferenceServices(connection.getServiceName(), connection);       for (Object aCol : col) {          String service = (String) aCol;           //查詢服務器上的聊天室          Collection<HostedRoom> rooms = MultiUserChat.getHostedRooms(connection, service);         for(HostedRoom room : rooms) {            //查看Room消息            System.out.println(room.getName() + " - " +room.getJid());            RoomInfo roomInfo = MultiUserChat.getRoomInfo(connection, room.getJid());           if(roomInfo != null) {              System.out.println(roomInfo.getOccupantsCount() + " : " + roomInfo.getSubject());           }            }         }             /*---創建默認配置的聊天室 ---       先看看官方的文檔:       Creates a new multi user chat with the specified connection and room name. Note: no          * information is sent to or received from the server until you attempt to          * {@link #join(String) join} the chat room. On some server implementations,          * the room will not be created until the first person joins it          * 最重要一句:直到用戶調用join方法的時候聊天室才會被創建          */        MultiUserChat muc = new MultiUserChat(connection, "instant@conference.pc2010102716");        muc.create("user1");        muc.sendConfigurationForm(new Form(Form.TYPE_SUBMIT));             //----創建手動配置聊天室----        muc = new MultiUserChat(connection, "reserved4@conference.pc2010102716");             //銷毀聊天室        //muc.destroy("Test", null);        muc.create("user2");        //獲取聊天室的配置表單        Form form = muc.getConfigurationForm();        //根據原始表單創建一個要提交的新表單        Form submitForm = form.createAnswerForm();        //向提交的表單添加默認答復        for(Iterator<FormField> fields = form.getFields(); fields.hasNext();) {          FormField field = (FormField) fields.next();          if(!FormField.TYPE_HIDDEN.equals(field.getType()) && field.getVariable() != null) {           submitForm.setDefaultAnswer(field.getVariable());          }        }        //重新設置聊天室名稱        submitForm.setAnswer("muc#roomconfig_roomname", "Reserved4 Room");        //設置聊天室的新擁有者        List<String> owners = new ArrayList<String>();        owners.add("test@pc2010102716");        submitForm.setAnswer("muc#roomconfig_roomowners", owners);        //設置密碼        submitForm.setAnswer("muc#roomconfig_passwordprotectedroom", true);        submitForm.setAnswer("muc#roomconfig_roomsecret", "reserved");        //設置描述        submitForm.setAnswer("muc#roomconfig_roomdesc", "新創建的reserved聊天室");        //設置聊天室是持久聊天室,即將要被保存下來        //submitForm.setAnswer("muc#roomconfig_persistentroom", true);        //發送已完成的表單到服務器配置聊天室        muc.sendConfigurationForm(submitForm);             //加入聊天室(使用昵稱喝醉的毛毛蟲 ,使用密碼ddd)        muc = new MultiUserChat(connection, "ddd@conference.pc2010102716");        muc.join("喝醉的毛毛蟲", "ddd");             //監聽消息        muc.addMessageListener(new PacketListener() {          @Override          public void processPacket(Packet packet) {            Message message = (Message) packet;            System.out.println(message.getFrom() + " : " + message.getBody());;          }        });             //muc = new MultiUserChat(connection, "ddd@conference.pc2010102716");        //muc.join("喝醉的毛毛蟲", "ddd");             //加入聊天室(使用昵稱喝醉的毛毛蟲 ,使用密碼ddd)并且獲取聊天室里最后5條信息,        //注:addMessageListener監聽器必須在此join方法之前,否則無法監聽到需要的5條消息        muc = new MultiUserChat(connection, "ddd@conference.pc2010102716");        DiscussionHistory history = new DiscussionHistory();        history.setMaxStanzas(5);        muc.join("喝醉的毛毛蟲", "ddd", history, SmackConfiguration.getPacketReplyTimeout());             //監聽拒絕加入聊天室的用戶        muc.addInvitationRejectionListener(new InvitationRejectionListener() {          @Override          public void invitationDeclined(String invitee, String reason) {          System.out.println(invitee + " reject invitation, reason is " + reason);          }        });        //邀請用戶加入聊天室        muc.invite("test3@pc2010102716", "大家來談談人生");        //監聽邀請加入聊天室請求        MultiUserChat.addInvitationListener(connection, new InvitationListener() {          @Override          public void invitationReceived(XMPPConnection conn, String room, String inviter, String reason, String password, Message message) {          //例:直接拒絕邀請          MultiUserChat.decline(conn, room, inviter, "你丫很閑啊!");          }        });                  //根據roomJID獲取聊天室信息        RoomInfo roomInfo = MultiUserChat.getRoomInfo(connection, "ddd@conference.pc2010102716");        System.out.println(roomInfo.getRoom() + "-" + roomInfo.getSubject() + "-" + roomInfo.getOccupantsCount());               //判斷用戶是否支持Multi-User聊天協議        //注:需要加上資源標識符        boolean supports = MultiUserChat.isServiceEnabled(connection, "test3@pc2010102716/spark");        //獲取某用戶所加入的聊天室        if(supports) {          Iterator<String> joinedRooms = MultiUserChat.getJoinedRooms(connection, "test3@pc2010102716/spark");         while(joinedRooms.hasNext()) {            System.out.println("test3 has joined Room " + joinedRooms.next());          }        }             //與聊天室用戶私聊        Chat chat = muc.createPrivateChat("ddd@conference.pc2010102716/飛鳥", new MessageListener() {          @Override           public void processMessage(Chat chat, Message message) {             System.out.println("Private Chat: Received message from " + message.getFrom() + "-" + message.getBody());          }        });        chat.sendMessage("今天不用加班吧?");             //改變聊天室主題        muc.addSubjectUpdatedListener(new SubjectUpdatedListener() {          @Override          public void subjectUpdated(String subject, String from) {            System.out.println("Subject updated to " + subject +" by " + from);          }        });        //muc.changeSubject("New Subject11");             /*一個成員可能有四種角色:       1:主持者(Moderator) (權限最大的角色,管理其他成員在聊天室中的角色       2:參與者(Participant       3:游客 (Visitor) (不能向所有成員發送消息)       4:無(沒有角色)(NONE)       */             /*聊天室用戶可以有5種從屬關系        * 1、所有者 Owner        * 2、管理員 Admin        * 3、成員 Member        * 4、被驅逐者 Outcast        * 5、無(不存在從屬關系) None        */             //配置聊天室為Moderated聊天室        form = muc.getConfigurationForm();        Form answerForm = form.createAnswerForm();        answerForm.setAnswer("muc#roomconfig_moderatedroom", "1");        muc.sendConfigurationForm(answerForm);             //監聽自己的狀態變更和事件        muc.addUserStatusListener(new DefaultUserStatusListener() {          @Override          public void voiceRevoked() {            super.voiceRevoked();            System.out.println("你被禁言了!");          }                 @Override          public void voiceGranted() {            super.voiceGranted();            System.out.println("你被批準發言了!");          }                 @Override          public void membershipGranted() {            super.membershipGranted();            System.out.println("你被賦予了Member權限");          }                 @Override          public void membershipRevoked() {            super.membershipRevoked();            System.out.println("你被解除了Member權限");          }                 @Override          public void adminGranted() {            super.adminGranted();            System.out.println("你被賦予了管理員權限");          }                 @Override          public void adminRevoked() {          super.adminRevoked();          System.out.println("你被解除了管理員權限");          }        //......        });        //房主(Owner)批準test3發言權        muc.grantVoice("test3@pc2010102716");             //監聽他人狀態變更        muc.addParticipantStatusListener(new DefaultParticipantStatusListener() {               @Override          public void voiceGranted(String participant) {            super.voiceGranted(participant);          System.out.println(participant + "被批準發言了!");          }                 @Override          public void voiceRevoked(String participant) {            super.voiceRevoked(participant);            System.out.println(participant + "被禁言了!");          }                 @Override          public void membershipRevoked(String participant) {            super.membershipRevoked(participant);          }                 @Override          public void adminGranted(String participant) {            super.adminGranted(participant);          }                 @Override          public void adminRevoked(String participant) {            super.adminRevoked(participant);          }             });             //房主(Owner)批準test3管理員特權        muc.grantAdmin("test3@pc2010102716");              //發送消息        BufferedReader cmdIn = new BufferedReader(new InputStreamReader(System.in));        while(true) {          try {             String cmd = cmdIn.readLine();             if("!q".equalsIgnoreCase(cmd)) {               break;             }           }catch(Exception ex) {           }        }        connection.disconnect();        System.exit(0);         } catch (Exception e) {        e.printStackTrace();      }    }     public static List<String> getConferenceServices(String server, XMPPConnection connection) throws Exception {    List<String> answer = new ArrayList<String>();        ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(connection);        DiscoverItems items = discoManager.discoverItems(server);        for (Iterator<DiscoverItems.Item> it = items.getItems(); it.hasNext();) {          DiscoverItems.Item item = (DiscoverItems.Item)it.next();          if (item.getEntityID().startsWith("conference") || item.getEntityID().startsWith("private")) {            answer.add(item.getEntityID());          }          else {            try {              DiscoverInfo info = discoManager.discoverInfo(item.getEntityID());              if (info.containsFeature("http://jabber.org/protocol/muc")) {                answer.add(item.getEntityID());              }            }            catch (XMPPException e) {            }          }        }        return answer;      }      private static void configure(ProviderManager pm) {      // Service Discovery # Items      pm.addIQProvider("query", "http://jabber.org/protocol/disco#items", new DiscoverItemsProvider());      // Service Discovery # Info      pm.addIQProvider("query", "http://jabber.org/protocol/disco#info", new DiscoverInfoProvider());           // Service Discovery # Items      pm.addIQProvider("query", "http://jabber.org/protocol/disco#items", new DiscoverItemsProvider());      // Service Discovery # Info      pm.addIQProvider("query", "http://jabber.org/protocol/disco#info", new DiscoverInfoProvider());           //Offline Message Requests      pm.addIQProvider("offline","http://jabber.org/protocol/offline", new OfflineMessageRequest.Provider());         //Offline Message Indicator          pm.addExtensionProvider("offline","http://jabber.org/protocol/offline", new OfflineMessageInfo.Provider());                   //vCard      pm.addIQProvider("vCard","vcard-temp", new VCardProvider());       //FileTransfer      pm.addIQProvider("si","http://jabber.org/protocol/si", new StreamInitiationProvider());         pm.addIQProvider("query","http://jabber.org/protocol/bytestreams", new BytestreamsProvider());         pm.addIQProvider("open","http://jabber.org/protocol/ibb", new IBBProviders.Open());         pm.addIQProvider("close","http://jabber.org/protocol/ibb", new IBBProviders.Close());         pm.addExtensionProvider("data","http://jabber.org/protocol/ibb", new IBBProviders.Data());             //Data Forms        pm.addExtensionProvider("x", "jabber:x:data", new DataFormProvider());        //Html        pm.addExtensionProvider("html", "http://jabber.org/protocol/xhtml-im", new XHTMLExtensionProvider());       //Ad-Hoc Command        pm.addIQProvider("command", "http://jabber.org/protocol/commands", new AdHocCommandDataProvider());         // Chat State      ChatStateExtension.Provider chatState = new ChatStateExtension.Provider();      pm.addExtensionProvider("active", "http://jabber.org/protocol/chatstates", chatState);     pm.addExtensionProvider("composing", "http://jabber.org/protocol/chatstates",        chatState);      pm.addExtensionProvider("paused", "http://jabber.org/protocol/chatstates", chatState);     pm.addExtensionProvider("inactive", "http://jabber.org/protocol/chatstates", chatState);     pm.addExtensionProvider("gone", "http://jabber.org/protocol/chatstates", chatState);     //MUC User,Admin,Owner      pm.addExtensionProvider("x", "http://jabber.org/protocol/muc#user", new MUCUserProvider());     pm.addIQProvider("query", "http://jabber.org/protocol/muc#admin", new MUCAdminProvider());     pm.addIQProvider("query", "http://jabber.org/protocol/muc#owner", new MUCOwnerProvider());   }     private static void initFeatures(XMPPConnection xmppConnection) {      ServiceDiscoveryManager.setIdentityName("Android_IM");      ServiceDiscoveryManager.setIdentityType("phone");      ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(xmppConnection);      if(sdm == null) {      sdm = new ServiceDiscoveryManager(xmppConnection);      }      sdm.addFeature("http://jabber.org/protocol/disco#info");      sdm.addFeature("http://jabber.org/protocol/caps");      sdm.addFeature("urn:xmpp:avatar:metadata");      sdm.addFeature("urn:xmpp:avatar:metadata+notify");      sdm.addFeature("urn:xmpp:avatar:data");      sdm.addFeature("http://jabber.org/protocol/nick");      sdm.addFeature("http://jabber.org/protocol/nick+notify");      sdm.addFeature("http://jabber.org/protocol/xhtml-im");      sdm.addFeature("http://jabber.org/protocol/muc");      sdm.addFeature("http://jabber.org/protocol/commands");      sdm.addFeature("http://jabber.org/protocol/si/profile/file-transfer");      sdm.addFeature("http://jabber.org/protocol/si");      sdm.addFeature("http://jabber.org/protocol/bytestreams");      sdm.addFeature("http://jabber.org/protocol/ibb");      sdm.addFeature("http://jabber.org/protocol/feature-neg");      sdm.addFeature("jabber:iq:privacy");    }   }  

上面有兩張Spark客戶端的聊天室列表占有者一列不同的原因:當使用以下代碼獲取時不能獲取occupantsCount和subject的值:  

System.out.println(roomInfo.getOccupantsCount() + " : " + roomInfo.getSubject()); 

這是由于Openfire端有個bug(暫且這樣說吧,我不知為什么Openfire這樣做).首先修改Smack的一個bug,修改RoomInfo類的RoomInfo(DiscoverInfo info) 方法:         

Iterator<String> values = form.getField("muc#roominfo_subject").getValues(); if (values.hasNext()) {   this.subject = values.next(); } else {   this.subject = ""; }  

改為:   

final FormField subjField = form.getField("muc#roominfo_subject");  this.subject = subjField == null ? "" : subjField.getValues().next(); 

  修改Openfire的源碼,org/jivesoftware/openfire/muc/spi/MultiUserChatServiceImpl類的public DataForm getExtendedInfo(String name, String node, JID senderJID) 方法:         

      /*final FormField fieldOcc = dataForm.addField(); */       fieldSubj.setVariable("muc#roominfo_occupants");       fieldSubj.setLabel(LocaleUtils.getLocalizedString("muc.extended.info.occupants"));       fieldSubj.addValue(Integer.toString(room.getOccupantsCount())); 

  
改為:         

final FormField fieldOccu= dataForm.addField(); 
fieldOccu.setVariable("muc#roominfo_occupants"); 
fieldOccu.setLabel(LocaleUtils.getLocalizedString("muc.extended.info.occupants")); 
fieldOccu.addValue(Integer.toString(room.getOccupantsCount()));  

2016224155734617.gif (496×393)

2016224155755589.gif (497×397)

2016224155813935.gif (495×397)

2016224155833876.gif (499×403)

2016224155851017.gif (1024×419)

2016224155906465.gif (1024×510)

使用asmack開發基于Android的IM系統同理.

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 潼南县| 崇义县| 专栏| 长垣县| 杭锦后旗| 偏关县| 松江区| 宜春市| 山阴县| 怀来县| 丹江口市| 福海县| 大宁县| 东阳市| 青田县| 鸡西市| 湟源县| 嘉黎县| 登封市| 洛浦县| 喀喇沁旗| 饶平县| 若羌县| 利辛县| 富顺县| 固阳县| 沧州市| 邢台县| 昌平区| 洛南县| 广元市| 鸡西市| 奇台县| 万宁市| 随州市| 云霄县| 嘉义县| 博湖县| 天气| 遂宁市| 合山市|