content: /*
   * Copyright (C) 2010 Moduad Co., Ltd.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package net.cgt.weixin.view.manager;
  
  import java.io.BufferedInputStream;
  import java.io.ByteArrayInputStream;
  import java.io.File;
  import java.io.FileInputStream;
  import java.io.IOException;
  import java.text.SimpleDateFormat;
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.Date;
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Map;
  import java.util.Properties;
  
  import net.cgt.weixin.Constants;
  import net.cgt.weixin.GlobalParams;
  import net.cgt.weixin.R;
  import net.cgt.weixin.domain.FriendRooms;
  import net.cgt.weixin.domain.MucHistory;
  import net.cgt.weixin.domain.User;
  import net.cgt.weixin.utils.FormatTools;
  import net.cgt.weixin.utils.L;
  import net.cgt.weixin.utils.LogUtil;
  import net.cgt.weixin.utils.SpUtil;
  import net.cgt.weixin.view.listener.TaxiChatManagerListener;
  
  import org.jivesoftware.smack.Chat;
  import org.jivesoftware.smack.ConnectionConfiguration;
  import org.jivesoftware.smack.ConnectionConfiguration.SecurityMode;
  import org.jivesoftware.smack.MessageListener;
  import org.jivesoftware.smack.PacketCollector;
  import org.jivesoftware.smack.PacketListener;
  import org.jivesoftware.smack.Roster;
  import org.jivesoftware.smack.RosterEntry;
  import org.jivesoftware.smack.RosterGroup;
  import org.jivesoftware.smack.SmackConfiguration;
  import org.jivesoftware.smack.XMPPConnection;
  import org.jivesoftware.smack.XMPPException;
  import org.jivesoftware.smack.filter.AndFilter;
  import org.jivesoftware.smack.filter.PacketFilter;
  import org.jivesoftware.smack.filter.PacketIDFilter;
  import org.jivesoftware.smack.filter.PacketTypeFilter;
  import org.jivesoftware.smack.packet.IQ;
  import org.jivesoftware.smack.packet.Message;
  import org.jivesoftware.smack.packet.Packet;
  import org.jivesoftware.smack.packet.Presence;
  import org.jivesoftware.smack.packet.Registration;
  import org.jivesoftware.smack.provider.ProviderManager;
  import org.jivesoftware.smack.util.StringUtils;
  import org.jivesoftware.smackx.Form;
  import org.jivesoftware.smackx.FormField;
  import org.jivesoftware.smackx.ReportedData;
  import org.jivesoftware.smackx.ReportedData.Row;
  import org.jivesoftware.smackx.ServiceDiscoveryManager;
  import org.jivesoftware.smackx.muc.DiscussionHistory;
  import org.jivesoftware.smackx.muc.HostedRoom;
  import org.jivesoftware.smackx.muc.MultiUserChat;
  import org.jivesoftware.smackx.muc.ParticipantStatusListener;
  import org.jivesoftware.smackx.muc.RoomInfo;
  import org.jivesoftware.smackx.packet.VCard;
  import org.jivesoftware.smackx.search.UserSearchManager;
  
  import android.app.Activity;
  import android.content.Context;
  import android.graphics.drawable.Drawable;
  
  /**
   * XMPP管理
   * 
   * @author lijian
   * @date 2014-11-22
   */
  public class XmppManager {
  
  	private static final String LOGTAG = LogUtil.makeLogTag(XmppManager.class);
  
  	private Context context;
  
  	/** 加载配置文件 **/
  	private Properties props;
  
  	private String version = "0.0.1";
  
  	private String apiKey;
  
  	private String xmppHost;
  
  	private String xmppPort;
  
  	/** 回调Activity的包名 **/
  	private String callbackActivityPackageName;
  
  	/** 回调Activity的全类名 **/
  	private String callbackActivityClassName;
  
  	private XMPPConnection connection;
  
  	private static XmppManager xmppManager;
  
  	/** 聊天监听器 **/
  	private TaxiChatManagerListener chatManagerListener;
  
  	public static XmppManager getInstance() {
  		if (xmppManager == null) {
  			xmppManager = new XmppManager(GlobalParams.activity);
  			return xmppManager;
  		}
  		return xmppManager;
  	}
  
  	private XmppManager(Context context) {
  		this.context = context;
  		init(context);
  	}
  
  	private void init(Context context) {
  		if (context instanceof Activity) {
  			L.i(LOGTAG, "Callback Activity...");
  			Activity callbackActivity = (Activity) context;
  			callbackActivityPackageName = callbackActivity.getPackageName();
  			callbackActivityClassName = callbackActivity.getClass().getName();
  		}
  
  		props = loadProperties();
  		apiKey = props.getProperty("apiKey", "");
  		xmppHost = props.getProperty("xmppHost", "127.0.0.1");
  		xmppPort = props.getProperty("xmppPort", "5222");
  		L.i(LOGTAG, "apiKey=" + apiKey);
  		L.i(LOGTAG, "xmppHost=" + xmppHost);
  		L.i(LOGTAG, "xmppPort=" + xmppPort);
  
  		SpUtil sp = new SpUtil(context);
  		sp.saveString(Constants.API_KEY, apiKey);
  		sp.saveString(Constants.VERSION, version);
  		sp.saveString(Constants.XMPP_HOST, xmppHost);
  		sp.saveInt(Constants.XMPP_PORT, Integer.parseInt(xmppPort));
  		sp.saveString(Constants.CALLBACK_ACTIVITY_PACKAGE_NAME, callbackActivityPackageName);
  		sp.saveString(Constants.CALLBACK_ACTIVITY_CLASS_NAME, callbackActivityClassName);
  
  		connectServer();
  	}
  
  	/**
  	 * 加载Properties配置文件
  	 * 
  	 * @return
  	 */
  	private Properties loadProperties() {
  		Properties props = new Properties();
  		try {
  			int id = context.getResources().getIdentifier("weixin", "raw", context.getPackageName());
  			props.load(context.getResources().openRawResource(id));
  		} catch (Exception e) {
  			L.e(LOGTAG, "Could not find the properties file.", e);
  		}
  		return props;
  	}
  
  	/**
  	 * 得到xmpp连接
  	 * 
  	 * @return
  	 */
  	public XMPPConnection getConnection() {
  		return connection;
  	}
  
  	/**
  	 * 设置连接
  	 * 
  	 * @param connection 一个xmpp连接
  	 */
  	public void setConnection(XMPPConnection connection) {
  		this.connection = connection;
  	}
  
  	/**
  	 * xmpp连接是否建立并连接成功
  	 * 
  	 * @return
  	 */
  	private boolean isConnected() {
  		return connection != null && connection.isConnected();
  	}
  
  	/**
  	 * 与服务器建立连接
  	 * 
  	 * @return
  	 */
  	public boolean connectServer() {
  		ConnectionConfiguration connConfig = new ConnectionConfiguration(xmppHost, Integer.parseInt(xmppPort));
  		//设置安全模式
  		connConfig.setSecurityMode(SecurityMode.required);
  		//设置SASL认证是否启用
  		connConfig.setSASLAuthenticationEnabled(false);
  		//设置数据压缩是否启用
  		connConfig.setCompressionEnabled(false);
  		//是否启用调试模式
  		connConfig.setDebuggerEnabled(true);
  
  		/** 创建connection连接 */
  		XMPPConnection connection = new XMPPConnection(connConfig);
  		this.setConnection(connection);
  
  		try {
  			// 连接到服务器
  			connection.connect();
  			L.i(LOGTAG, "XMPP connected successfully");
  			return true;
  		} catch (XMPPException e) {
  			L.e(LOGTAG, "XMPP connection failed", e);
  		}
  		return false;
  	}
  
  	/**
  	 * 注册
  	 * 
  	 * @param account 注册帐号
  	 * @param password 注册密码
  	 * @return 0、 服务器没有返回结果<br>
  	 *         1、注册成功 <br>
  	 *         2、这个帐号已经存在 <br>
  	 *         3、注册失败
  	 */
  	public String regist(String account, String password) {
  		if (!isConnected()) {
  			return "0";
  		}
  		Registration reg = new Registration();
  		reg.setType(IQ.Type.SET);
  		reg.setTo(getConnection().getServiceName());
  		reg.setUsername(account);
  		reg.setPassword(password);
  		reg.addAttribute("android", "geolo_createUser_android");
  
  		//数据包过滤器
  		PacketFilter filter = new AndFilter(new PacketIDFilter(reg.getPacketID()), new PacketTypeFilter(IQ.class));
  		PacketCollector collector = getConnection().createPacketCollector(filter);
  		getConnection().sendPacket(reg);
  
  		IQ result = (IQ) collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
  		//停止请求result(是否成功的结果)
  		collector.cancel();
  		if (result == null) {
  			L.e(LOGTAG, "No response from server.");
  			return "0";
  		} else if (result.getType() == IQ.Type.RESULT) {
  			return "1";
  		} else {
  			if (result.getError().toString().equalsIgnoreCase("conflict(409)")) {
  				L.e(LOGTAG, "IQ.Type.ERROR: " + result.getError().toString());
  				return "2";
  			} else {
  				L.e(LOGTAG, "IQ.Type.ERROR: " + result.getError().toString());
  				return "3";
  			}
  		}
  	}
  
  	/**
  	 * 获取一个聊天监听器
  	 * 
  	 * @return
  	 */
  	public TaxiChatManagerListener getChatManagerListener() {
  		return this.chatManagerListener;
  	}
  
  	/**
  	 * 登陆
  	 * 
  	 * @param account 账户名
  	 * @param password 密码
  	 * @return
  	 */
  	public boolean login(String account, String password) {
  		try {
  			//登陆
  			getConnection().login(account, password);
  
  			/** 开启读写线程，并加入到管理类中 */
  			//ClientSendThread cst = new ClientSendThread(connection);
  			//cst.start();
  			//ManageClientThread.addClientSendThread(account,cst);
  
  			// 添加监听，最好是放在登录方法中，在关闭连接方法中，移除监听，原因是为了避免重复添加监听，接受重复消息
  			// 退出程序应该关闭连接，移除监听，该监听可以接受所有好友的消息，很方便吧~
  			chatManagerListener = new TaxiChatManagerListener();
  			getConnection().getChatManager().addChatListener(chatManagerListener);
  
  			return true;
  		} catch (XMPPException e) {
  			L.e(LOGTAG, "XMPP connection failed", e);
  		}
  		return false;
  	}
  
  	/**
  	 * 登出
  	 * 
  	 * @return
  	 */
  	public boolean logout() {
  		// 添加监听，最好是放在登录方法中，在关闭连接方法中，移除监听，原因是为了避免重复添加监听，接受重复消息
  		// 退出程序应该关闭连接，移除监听，该监听可以接受所有好友的消息，很方便吧~
  		getConnection().getChatManager().removeChatListener(chatManagerListener);
  
  		//退出登录
  		getConnection().disconnect();
  
  		if (isConnected()) {
  			return true;
  		}
  		return false;
  	}
  
  	/**
  	 * 修改密码
  	 * 
  	 * @param password
  	 * @return
  	 */
  	public boolean changePassword(String password) {
  		try {
  			getConnection().getAccountManager().changePassword(password);
  			return true;
  		} catch (XMPPException e) {
  			e.printStackTrace();
  		}
  		return false;
  	}
  
  	/**
  	 * 更改用户状态
  	 * 
  	 * @param code--><br>
  	 *            0、在线<br>
  	 *            1、Q我吧<br>
  	 *            2、忙碌<br>
  	 *            3、离开<br>
  	 *            4、隐身<br>
  	 *            5、离线
  	 */
  	public void setPresence(int code) {
  		if (!isConnected()) {
  			return;
  		}
  		Presence presence;
  		switch (code) {
  		case 0:
  			presence = new Presence(Presence.Type.available);
  			getConnection().sendPacket(presence);
  			L.v(LOGTAG, "设置在线");
  			break;
  		case 1:
  			presence = new Presence(Presence.Type.available);
  			presence.setMode(Presence.Mode.chat);
  			getConnection().sendPacket(presence);
  			L.v(LOGTAG, "设置Q我吧");
  			L.d(LOGTAG, "Q我吧--->" + presence.toXML());
  			break;
  		case 2:
  			presence = new Presence(Presence.Type.available);
  			presence.setMode(Presence.Mode.dnd);
  			getConnection().sendPacket(presence);
  			L.v(LOGTAG, "设置忙碌");
  			L.d(LOGTAG, "忙碌--->" + presence.toXML());
  			break;
  		case 3:
  			presence = new Presence(Presence.Type.available);
  			presence.setMode(Presence.Mode.away);
  			getConnection().sendPacket(presence);
  			L.v(LOGTAG, "设置离开");
  			L.d(LOGTAG, "离开--->" + presence.toXML());
  			break;
  		case 4:
  			Roster roster = getConnection().getRoster();
  			Collection<RosterEntry> entries = roster.getEntries();
  			for (RosterEntry entry : entries) {
  				presence = new Presence(Presence.Type.unavailable);
  				presence.setPacketID(Packet.ID_NOT_AVAILABLE);
  				presence.setFrom(getConnection().getUser());
  				presence.setTo(entry.getUser());
  				getConnection().sendPacket(presence);
  				L.d(LOGTAG, entry.getUser() + "--->" + presence.toXML());
  			}
  			//向同一用户的其他客户端发送隐身状态
  			presence = new Presence(Presence.Type.unavailable);
  			presence.setPacketID(Packet.ID_NOT_AVAILABLE);
  			presence.setFrom(getConnection().getUser());
  			presence.setTo(StringUtils.parseBareAddress(getConnection().getUser()));
  			getConnection().sendPacket(presence);
  			L.v(LOGTAG, "设置隐身");
  			break;
  		case 5:
  			presence = new Presence(Presence.Type.unavailable);
  			getConnection().sendPacket(presence);
  			L.v(LOGTAG, "设置离线");
  			break;
  		default:
  			break;
  		}
  	}
  
  	/**
  	 * 删除当前账户
  	 * 
  	 * @return
  	 */
  	public boolean deleteAccount() {
  		try {
  			getConnection().getAccountManager().deleteAccount();
  			return true;
  		} catch (XMPPException e) {
  			e.printStackTrace();
  		}
  		return false;
  	}
  
  	/**
  	 * 获得所有组
  	 * 
  	 * @param roster
  	 * @return 所有组集合
  	 */
  	public List<RosterGroup> getGroups(Roster roster) {
  		List<RosterGroup> groupList = new ArrayList<RosterGroup>();
  		Collection<RosterGroup> rosterGroups = roster.getGroups();
  		Iterator<RosterGroup> i = rosterGroups.iterator();
  		while (i.hasNext()) {
  			groupList.add(i.next());
  		}
  		return groupList;
  	}
  
  	/**
  	 * 添加分组
  	 * 
  	 * @param roster
  	 * @param groupName 分组名
  	 * @return
  	 */
  	public boolean addGroup(Roster roster, String groupName) {
  		try {
  			roster.createGroup(groupName);
  			return true;
  		} catch (Exception e) {
  			e.printStackTrace();
  		}
  		return false;
  	}
  
  	/**
  	 * 获得某个组里面的所有好友
  	 * 
  	 * @param roster
  	 * @param groupName 组名
  	 * @return
  	 */
  	public List<RosterEntry> getEntriesByGroup(Roster roster, String groupName) {
  		List<RosterEntry> entriesList = new ArrayList<RosterEntry>();
  		RosterGroup rosterGroup = roster.getGroup(groupName);
  		Collection<RosterEntry> rosterEntries = rosterGroup.getEntries();
  		Iterator<RosterEntry> i = rosterEntries.iterator();
  		while (i.hasNext()) {
  			entriesList.add(i.next());
  		}
  		return entriesList;
  	}
  
  	/**
  	 * 获取所有好友信息
  	 * 
  	 * @param roster
  	 * @return
  	 */
  	public List<RosterEntry> getAllEntries(Roster roster) {
  		List<RosterEntry> entriesList = new ArrayList<RosterEntry>();
  		Collection<RosterEntry> rosterEntries = roster.getEntries();
  		Iterator<RosterEntry> i = rosterEntries.iterator();
  		while (i.hasNext()) {
  			entriesList.add(i.next());
  		}
  		return entriesList;
  	}
  
  	/**
  	 * 获取所有好友信息
  	 * 
  	 * @param roster
  	 * @return
  	 */
  	public List<User> getAllUser(Roster roster) {
  		List<User> mList_user = new ArrayList<User>();
  		Collection<RosterEntry> entries = roster.getEntries();
  		Iterator<RosterEntry> iterator = entries.iterator();
  		while (iterator.hasNext()) {
  			RosterEntry entry = iterator.next();
  			User user = new User();
  			user.setUserAccount(entry.getName());
  			user.setUserPhote(String.valueOf(R.drawable.user_picture));
  //			user.setUserImage(getUserImage(entry.getName()));
  			mList_user.add(user);
  			L.i(LOGTAG, "------获取好友-getAllUser----------------------");
  			L.i(LOGTAG, "getAllUser-getName-->" + entry.getName());
  			L.i(LOGTAG, "getAllUser-getUser-->" + entry.getUser());
  			L.i(LOGTAG, "getAllUser-getStatus-->" + entry.getStatus());
  		}
  		return mList_user;
  	}
  
  	/**
  	 * 获取用户VCard信息
  	 * 
  	 * @param user
  	 * @return
  	 * @throws XMPPException
  	 */
  	public VCard getUserVCard(String user) throws XMPPException {
  		VCard vCard = new VCard();
  		vCard.load(getConnection(), user);
  		return vCard;
  	}
  
  	/**
  	 * 获取用户头像信息
  	 * 
  	 * @param user
  	 * @return
  	 */
  	public Drawable getUserImage(String user) {
  		ByteArrayInputStream bais = null;
  		try {
  			VCard vCard = new VCard();
  			//加入这句，解决没有No VCard
  			ProviderManager.getInstance().addIQProvider("vCard", "vcard-temp", new org.jivesoftware.smackx.provider.VCardProvider());
  			vCard.load(getConnection(), user + "@" + getConnection().getServiceName());
  			if (vCard == null || vCard.getAvatar() == null) {
  				return null;
  			}
  			bais = new ByteArrayInputStream(vCard.getAvatar());
  		} catch (Exception e) {
  			e.printStackTrace();
  		}
  		if (bais == null) {
  			return null;
  		}
  		return FormatTools.getInstance().InputStream2Drawable(bais);
  	}
  
  	/**
  	 * 添加好友--无分组
  	 * 
  	 * @param roster
  	 * @param userName
  	 * @param name
  	 * @return
  	 */
  	public boolean addUser(Roster roster, String userName, String name) {
  		try {
  			roster.createEntry(userName, name, null);
  			return true;
  		} catch (XMPPException e) {
  			e.printStackTrace();
  		}
  		return false;
  	}
  
  	/**
  	 * 添加好友--有分组
  	 * 
  	 * @param roster
  	 * @param userName
  	 * @param name
  	 * @param groupName
  	 * @return
  	 */
  	public boolean addUser(Roster roster, String userName, String name, String groupName) {
  		try {
  			roster.createEntry(userName, name, new String[] { groupName });
  			return true;
  		} catch (XMPPException e) {
  			e.printStackTrace();
  		}
  		return false;
  	}
  
  	/**
  	 * 删除好友
  	 * 
  	 * @param roster
  	 * @param userName
  	 * @return
  	 */
  	public boolean removeUser(Roster roster, String userName) {
  		try {
  			if (userName.contains("@")) {
  				userName = userName.split("@")[0];
  			}
  			RosterEntry entry = roster.getEntry(userName);
  			L.i(LOGTAG, "删除好友--->" + userName);
  			L.d(LOGTAG, "User." + (roster.getEntry(userName) == null));
  			roster.removeEntry(entry);
  			return true;
  		} catch (Exception e) {
  			e.printStackTrace();
  		}
  		return false;
  	}
  
  	/**
  	 * 查询用户
  	 * 
  	 * @param serverDomain
  	 * @param userName
  	 * @return
  	 * @throws XMPPException
  	 */
  	public List<User> searchUsers(String serverDomain, String userName) throws XMPPException {
  		List<User> results = new ArrayList<User>();
  		L.i(LOGTAG, "查询开始--->Host=" + getConnection().getHost() + "  ServiceName=" + getConnection().getServiceName());
  
  		UserSearchManager usm = new UserSearchManager(getConnection());
  		Form searchForm = usm.getSearchForm(serverDomain);
  		Form answerForm = searchForm.createAnswerForm();
  		answerForm.setAnswer("userAccount", true);
  		answerForm.setAnswer("userPhote", userName);
  		ReportedData data = usm.getSearchResults(answerForm, serverDomain);
  
  		Iterator<Row> i = data.getRows();
  		Row row = null;
  		User user = null;
  		while (i.hasNext()) {
  			user = new User();
  			row = i.next();
  			user.setUserAccount(row.getValues("userAccount").next().toString());
  			user.setUserPhote(row.getValues("userPhote").next().toString());
  			results.add(user);
  			//若存在，则有返回，userName一定非空，其他两个若是有设，一定非空
  		}
  		return results;
  	}
  
  	/**
  	 * 修改用户头像
  	 * 
  	 * @param f
  	 * @throws XMPPException
  	 * @throws IOException
  	 */
  	public void changeUserImage(File f) throws XMPPException, IOException {
  		VCard vCard = new VCard();
  		vCard.load(getConnection());
  		byte[] bytes = getFileBytes(f);
  
  		String encodeImage = StringUtils.encodeBase64(bytes);
  		vCard.setAvatar(bytes, encodeImage);
  		vCard.setEncodedImage(encodeImage);
  		vCard.setField("PHOTO", "<TYPE>image/jpg</TYPE><BINVAL>" + encodeImage + "</BINVAL>", true);
  
  		ByteArrayInputStream bais = new ByteArrayInputStream(vCard.getAvatar());
  		FormatTools.getInstance().InputStream2Bitmap(bais);
  		vCard.save(getConnection());
  	}
  
  	/**
  	 * 获取一个文件的字符流
  	 * 
  	 * @param file
  	 * @return
  	 * @throws IOException
  	 */
  	private byte[] getFileBytes(File file) throws IOException {
  		BufferedInputStream bis = null;
  		try {
  			bis = new BufferedInputStream(new FileInputStream(file));
  			int bytes = (int) file.length();
  			byte[] buffer = new byte[bytes];
  			int readBytes = bis.read(buffer);
  			if (readBytes != buffer.length) {
  				throw new IOException("Entire file not read");
  			}
  			return buffer;
  		} finally {
  			if (bis != null) {
  				bis.close();
  			}
  		}
  	}
  
  	/**
  	 * 创建房间
  	 * 
  	 * @param roomName 房间名称
  	 */
  	public void createRoom(String roomName) {
  		if (!isConnected()) {
  			return;
  		}
  		try {
  			// 创建一个MultiUserChat  
  			MultiUserChat muc = new MultiUserChat(getConnection(), roomName + "@conference." + getConnection().getServiceName());
  			// 创建聊天室  
  			muc.create(roomName); // roomName房间的名字  
  			// 获得聊天室的配置表单  
  			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());
  				}
  			}
  			// 设置聊天室的新拥有者  
  			List<String> owners = new ArrayList<String>();
  			owners.add(getConnection().getUser());// 用户JID  
  			submitForm.setAnswer("muc#roomconfig_roomowners", owners);
  			// 设置聊天室是持久聊天室，即将要被保存下来  
  			submitForm.setAnswer("muc#roomconfig_persistentroom", false);
  			// 房间仅对成员开放  
  			submitForm.setAnswer("muc#roomconfig_membersonly", false);
  			// 允许占有者邀请其他人  
  			submitForm.setAnswer("muc#roomconfig_allowinvites", true);
  			// 进入是否需要密码  
  			//submitForm.setAnswer("muc#roomconfig_passwordprotectedroom", true);  
  			// 设置进入密码  
  			//submitForm.setAnswer("muc#roomconfig_roomsecret", "password");  
  			// 能够发现占有者真实 JID 的角色  
  			// submitForm.setAnswer("muc#roomconfig_whois", "anyone");  
  			// 登录房间对话  
  			submitForm.setAnswer("muc#roomconfig_enablelogging", true);
  			// 仅允许注册的昵称登录  
  			submitForm.setAnswer("x-muc#roomconfig_reservednick", true);
  			// 允许使用者修改昵称  
  			submitForm.setAnswer("x-muc#roomconfig_canchangenick", false);
  			// 允许用户注册房间  
  			submitForm.setAnswer("x-muc#roomconfig_registration", false);
  			// 发送已完成的表单（有默认值）到服务器来配置聊天室  
  			submitForm.setAnswer("muc#roomconfig_passwordprotectedroom", true);
  			// 发送已完成的表单（有默认值）到服务器来配置聊天室  
  			muc.sendConfigurationForm(submitForm);
  		} catch (XMPPException e) {
  			e.printStackTrace();
  		}
  	}
  
  	/**
  	 * 加入会议室
  	 * 
  	 * @param user 昵称
  	 * @param password 会议室密码
  	 * @param roomsName 会议室名
  	 */
  	public MultiUserChat joinMultiUserChat(String user, String password, String roomsName) {
  		try {
  			// 使用XMPPConnection创建一个MultiUserChat窗口  
  			MultiUserChat muc = new MultiUserChat(getConnection(), roomsName + "@conference." + getConnection().getServiceName());
  			// 聊天室服务将会决定要接受的历史记录数量  
  			DiscussionHistory history = new DiscussionHistory();
  			history.setMaxStanzas(0);
  			//history.setSince(new Date());  
  			// 用户加入聊天室  
  			muc.join(user, password, history, SmackConfiguration.getPacketReplyTimeout());
  			L.i(LOGTAG, "会议室加入成功........");
  			return muc;
  		} catch (XMPPException e) {
  			e.printStackTrace();
  			L.i(LOGTAG, "会议室加入失败........");
  			return null;
  		}
  	}
  
  	/**
  	 * 查询会议室成员名字
  	 * 
  	 * @param muc
  	 */
  	public List<String> findMulitUser(MultiUserChat muc) {
  		List<String> listUser = new ArrayList<String>();
  		Iterator<String> it = muc.getOccupants();
  		//遍历出聊天室人员名称  
  		while (it.hasNext()) {
  			// 聊天室成员名字  
  			String name = StringUtils.parseResource(it.next());
  			listUser.add(name);
  		}
  		return listUser;
  	}
  
  	/**
  	 * 获取服务器上所有会议室
  	 * 
  	 * @return
  	 * @throws XMPPException
  	 */
  	public List<FriendRooms> getConferenceRoom() throws XMPPException {
  		List<FriendRooms> list = new ArrayList<FriendRooms>();
  		new ServiceDiscoveryManager(getConnection());
  		if (!MultiUserChat.getHostedRooms(getConnection(), getConnection().getServiceName()).isEmpty()) {
  
  			for (HostedRoom k : MultiUserChat.getHostedRooms(getConnection(), getConnection().getServiceName())) {
  
  				for (HostedRoom j : MultiUserChat.getHostedRooms(getConnection(), k.getJid())) {
  					RoomInfo info2 = MultiUserChat.getRoomInfo(getConnection(), j.getJid());
  					if (j.getJid().indexOf("@") > 0) {
  
  						FriendRooms friendrooms = new FriendRooms();
  						friendrooms.setName(j.getName());//聊天室的名称  
  						friendrooms.setJid(j.getJid());//聊天室JID  
  						friendrooms.setOccupants(info2.getOccupantsCount());//聊天室中占有者数量  
  						friendrooms.setDescription(info2.getDescription());//聊天室的描述  
  						friendrooms.setSubject(info2.getSubject());//聊天室的主题  
  						list.add(friendrooms);
  					}
  				}
  			}
  		}
  		return list;
  	}
  
  	//	五、监听会议室的消息
  	//	添加会议室消息监听 ：
  	//multiChat.addMessageListener(new multiListener());
  	/**
  	 * 会议室信息监听事件
  	 * 
  	 * @author Administrator
  	 * 
  	 */
  	public class multiListener implements PacketListener {
  		@Override
  		public void processPacket(Packet packet) {
  			Message message = (Message) packet;
  			// 接收来自聊天室的聊天信息  
  			String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
  			MucHistory mh = new MucHistory();
  			//			mh.setUserAccount(account);
  			String from = StringUtils.parseResource(message.getFrom());
  			String fromRoomName = StringUtils.parseName(message.getFrom());
  			mh.setMhRoomName(fromRoomName);
  			mh.setFriendAccount(from);
  			mh.setMhInfo(message.getBody());
  			mh.setMhTime(time);
  			mh.setMhType("left");
  		}
  	}
  
  	//六、发送会议室消息
  	//    multiChat.sendMessage(str);//multiChat 为聊天室对象
  
  	//	七、监听会议室状态（成员的进入、离开等）
  	//	添加监听事件：
  	//    multiChat.addParticipantStatusListener(new ParticipantStatus());
  
  	/**
  	 * 会议室状态监听事件
  	 * 
  	 * @author Administrator
  	 * 
  	 */
  	class ParticipantStatus implements ParticipantStatusListener {
  
  		@Override
  		public void adminGranted(String arg0) {
  			// TODO Auto-generated method stub  
  
  		}
  
  		@Override
  		public void adminRevoked(String arg0) {
  			// TODO Auto-generated method stub  
  
  		}
  
  		@Override
  		public void banned(String arg0, String arg1, String arg2) {
  			// TODO Auto-generated method stub  
  
  		}
  
  		@Override
  		public void joined(String participant) {
  			System.out.println(StringUtils.parseResource(participant) + " has joined the room.");
  		}
  
  		@Override
  		public void kicked(String arg0, String arg1, String arg2) {
  			// TODO Auto-generated method stub  
  
  		}
  
  		@Override
  		public void left(String participant) {
  			// TODO Auto-generated method stub  
  			System.out.println(StringUtils.parseResource(participant) + " has left the room.");
  
  		}
  
  		@Override
  		public void membershipGranted(String arg0) {
  			// TODO Auto-generated method stub  
  
  		}
  
  		@Override
  		public void membershipRevoked(String arg0) {
  			// TODO Auto-generated method stub  
  
  		}
  
  		@Override
  		public void moderatorGranted(String arg0) {
  			// TODO Auto-generated method stub  
  
  		}
  
  		@Override
  		public void moderatorRevoked(String arg0) {
  			// TODO Auto-generated method stub  
  
  		}
  
  		@Override
  		public void nicknameChanged(String participant, String newNickname) {
  			System.out.println(StringUtils.parseResource(participant) + " is now known as " + newNickname + ".");
  		}
  
  		@Override
  		public void ownershipGranted(String arg0) {
  			// TODO Auto-generated method stub  
  
  		}
  
  		@Override
  		public void ownershipRevoked(String arg0) {
  			// TODO Auto-generated method stub  
  
  		}
  
  		@Override
  		public void voiceGranted(String arg0) {
  			// TODO Auto-generated method stub  
  
  		}
  
  		@Override
  		public void voiceRevoked(String arg0) {
  			// TODO Auto-generated method stub  
  
  		}
  	}
  
  	//	一、单人聊天
  	//	1）发送消息：
  	//	首先要获取一个聊天窗口，getConnection()为获取连接connection的方法，调用getFriendChat()获取
  
  	private Map<String, Chat> chatManage = new HashMap<String, Chat>();// 聊天窗口管理map集合
  
  	/**
  	 * 获取或创建聊天窗口
  	 * 
  	 * @param friend 好友名
  	 * @param listenter 聊天監聽器
  	 * @return
  	 */
  	public Chat getFriendChat(String friend, MessageListener listenter) {
  		if (getConnection() == null)
  			return null;
  		/** 判断是否创建聊天窗口 */
  		for (String fristr : chatManage.keySet()) {
  			if (fristr.equals(friend)) {
  				// 存在聊天窗口，则返回对应聊天窗口
  				return chatManage.get(fristr);
  			}
  		}
  		/** 创建聊天窗口 */
  		Chat chat = getConnection().getChatManager().createChat(friend + "@" + getConnection().getServiceName(), listenter);
  		/** 添加聊天窗口到chatManage */
  		chatManage.put(friend, chat);
  		return chat;
  	}
  
  	//	friend为好友名，不是JID；listener 监听器可以传null，利用聊天窗口对象调用sendMessage发送消息
  	//	这里sendMessage我传的是一个JSON字符串，以便更灵活的控制，发送消息完成~
  	//	Chat chat = getFriendChat(friend,null);
  	//	try {
  	//	 	String msgjson = "{\"messageType\":\""+messageType+"\",\"chanId\":\""+chanId+"\",\"chanName\":\""+chanName+"\"}";
  	//		chat.sendMessage(msgjson);
  	//	} catch (XMPPException e) {
  	//		e.printStackTrace();
  	//	}
  
  	//	添加监听，最好是放在登录方法中，在关闭连接方法中，移除监听，原因是为了避免重复添加监听，接受重复消息
  	//	退出程序应该关闭连接，移除监听，该监听可以接受所有好友的消息，很方便吧~
  	//	TaxiChatManagerListener chatManagerListener = new TaxiChatManagerListener();  
  	//	getConnection().getChatManager().addChatListener(chatManagerListener); 
  
  	//	connection.getChatManager().removeChatListener(chatManagerListener);
  
  	//	二、多人聊天（会议室）
  	//	1）、发送消息
  	//	首先要获取会议室对象（MultiUserChat），有两种方法获取
  	//	两个方法前面都有讲到，这里再回顾一下
  	//	1、创建会议室
  	/**
  	 * 创建房间
  	 * 
  	 * @param user
  	 * @param roomName 房间名称
  	 * @param password
  	 * @return
  	 */
  	public MultiUserChat createRoom(String user, String roomName, String password) {
  		if (getConnection() == null)
  			return null;
  
  		MultiUserChat muc = null;
  		try {
  			// 创建一个MultiUserChat
  			muc = new MultiUserChat(getConnection(), roomName + "@conference." + getConnection().getServiceName());
  			// 创建聊天室
  			muc.create(roomName);
  			// 获得聊天室的配置表单
  			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());
  				}
  			}
  			// 设置聊天室的新拥有者
  			List<String> owners = new ArrayList<String>();
  			owners.add(getConnection().getUser());// 用户JID
  			submitForm.setAnswer("muc#roomconfig_roomowners", owners);
  			// 设置聊天室是持久聊天室，即将要被保存下来
  			submitForm.setAnswer("muc#roomconfig_persistentroom", true);
  			// 房间仅对成员开放
  			submitForm.setAnswer("muc#roomconfig_membersonly", false);
  			// 允许占有者邀请其他人
  			submitForm.setAnswer("muc#roomconfig_allowinvites", true);
  			if (!password.equals("")) {
  				// 进入是否需要密码
  				submitForm.setAnswer("muc#roomconfig_passwordprotectedroom", true);
  				// 设置进入密码
  				submitForm.setAnswer("muc#roomconfig_roomsecret", password);
  			}
  			// 能够发现占有者真实 JID 的角色
  			// submitForm.setAnswer("muc#roomconfig_whois", "anyone");
  			// 登录房间对话
  			submitForm.setAnswer("muc#roomconfig_enablelogging", true);
  			// 仅允许注册的昵称登录
  			submitForm.setAnswer("x-muc#roomconfig_reservednick", true);
  			// 允许使用者修改昵称
  			submitForm.setAnswer("x-muc#roomconfig_canchangenick", false);
  			// 允许用户注册房间
  			submitForm.setAnswer("x-muc#roomconfig_registration", false);
  			// 发送已完成的表单（有默认值）到服务器来配置聊天室
  			muc.sendConfigurationForm(submitForm);
  		} catch (XMPPException e) {
  			e.printStackTrace();
  			return null;
  		}
  		return muc;
  	}
  
  	//	/**
  	//	 * 加入会议室
  	//	 * 
  	//	 * @param user 昵称
  	//	 * @param password 会议室密码
  	//	 * @param roomsName 会议室名
  	//	 */
  	//	public MultiUserChat joinMultiUserChat(String user, String roomsName, String password) {
  	//		if (getConnection() == null)
  	//			return null;
  	//		try {
  	//			// 使用XMPPConnection创建一个MultiUserChat窗口
  	//			MultiUserChat muc = new MultiUserChat(getConnection(), roomsName + "@conference." + getConnection().getServiceName());
  	//			// 聊天室服务将会决定要接受的历史记录数量
  	//			DiscussionHistory history = new DiscussionHistory();
  	//			history.setMaxChars(0);
  	//			// history.setSince(new Date());
  	//			// 用户加入聊天室
  	//			muc.join(user, password, history, SmackConfiguration.getPacketReplyTimeout());
  	//			L.i("MultiUserChat", "会议室【" + roomsName + "】加入成功........");
  	//			return muc;
  	//		} catch (XMPPException e) {
  	//			e.printStackTrace();
  	//			L.i("MultiUserChat", "会议室【" + roomsName + "】加入失败........");
  	//			return null;
  	//		}
  	//	}
  
  	//	调用这个两个方法都可以获取到MultiUserChat，根据需求选择一个就可以。
  	//	利用MultiUserChat对象调用sendMessage()方法即可，很容易吧~
  	//	try {  
  	//	    multiUserChat.sendMessage(message);  
  	//	} catch (XMPPException e) {  
  	//	    e.printStackTrace();  
  	//	}
  
  	//	添加监听器，每个会议室聊天对象都要添加一个消息监听器,为了避免重复监听
  	//	应该把会议室聊天对象放在一个集合当中，需要用到的时候取出来用即可。
  	//	multiUserChat.addMessageListener(new TaxiMultiListener());
  
  	//	其次就是给连接设置监听器了，最好放在登录方法里，关闭连接方法里移除监听
  	//	// 添加連接監聽  
  	//	TaxiConnectionListener connectionListener = new TaxiConnectionListener();  
  	//	getConnection().addConnectionListener(connectionListener);  
  
  	//	connection.removeConnectionListener(connectionListener);
  }
  