Android中基于XMPP协议实现IM聊天程序与多人聊天室

2019-12-10 18:59:56于丽

 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://www.easck.com// Service Discovery # Items  
    pm.addIQProvider("query", "http://www.easck.com//jabber.org/protocol/disco#info", new DiscoverInfoProvider()); 
      
    // Service Discovery # Items  
    pm.addIQProvider("query", "http://www.easck.com//jabber.org/protocol/disco#info", new DiscoverInfoProvider()); 
      
    //Offline Message Requests  
    pm.addIQProvider("offline","http://www.easck.com//Offline Message Indicator  
        pm.addExtensionProvider("offline","http://www.easck.com//vCard  
    pm.addIQProvider("vCard","vcard-temp", new VCardProvider());  
 
    //FileTransfer  
    pm.addIQProvider("si","http://www.easck.com//jabber.org/protocol/bytestreams", new BytestreamsProvider()); 
        pm.addIQProvider("open","http://www.easck.com//jabber.org/protocol/ibb", new IBBProviders.Close()); 
        pm.addExtensionProvider("data","http://www.easck.com//Data Forms  
      pm.addExtensionProvider("x", "jabber:x:data", new DataFormProvider());  
      //Html  
      pm.addExtensionProvider("html", "http://www.easck.com//jabber.org/protocol/commands", new AdHocCommandDataProvider());     
    // Chat State  
    ChatStateExtension.Provider chatState = new ChatStateExtension.Provider();  
    pm.addExtensionProvider("active", "http://www.easck.com//jabber.org/protocol/chatstates",  
      chatState);  
    pm.addExtensionProvider("paused", "http://www.easck.com//jabber.org/protocol/chatstates", chatState); 
    pm.addExtensionProvider("gone", "http://www.easck.com//jabber.org/protocol/muc#user", new MUCUserProvider()); 
    pm.addIQProvider("query", "http://www.easck.com//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://www.easck.com//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://www.easck.com//jabber.org/protocol/nick+notify");  
    sdm.addFeature("http://www.easck.com//jabber.org/protocol/muc");  
    sdm.addFeature("http://www.easck.com//jabber.org/protocol/si/profile/file-transfer");  
    sdm.addFeature("http://www.easck.com//jabber.org/protocol/bytestreams");  
    sdm.addFeature("http://www.easck.com//jabber.org/protocol/feature-neg");  
    sdm.addFeature("jabber:iq:privacy");  
  }  
 
}