/** * XMPP服务器连接工具类. * * @author chen.lin * */ public class XmppManager { private static final String TAG = "XmppManager"; private XMPPConnection connection; private static ConnectionConfiguration connectionConfig; private static XmppManager xmppManager; private Context mContext; private SharedPreferences sp; private final String CONFERENCE = "@conference."; //private IMConnectionListener connectionListener; // ----------------------------------------------------------- private MultiUserChat muc; public MultiUserChat getMuc() { return muc; } public void setMuc(MultiUserChat muc) { this.muc = muc; } // ----------------------------------------------------------- private XmppManager(Context context) { mContext = context; sp = mContext.getSharedPreferences(Constant.CONFIG, Context.MODE_PRIVATE); connection = init(getLoginConfig()); //connectionListener = new IMConnectionListener(); } public static XmppManager getInstance(Context context) { if (xmppManager == null) { xmppManager = new XmppManager(context); } return xmppManager; } public void saveLoginConfig(IMLoginConfig loginConfig) { Editor edit = sp.edit(); edit.putString(Constant.XMPP_HOST, loginConfig.getXmppHost()); edit.putInt(Constant.XMPP_PORT, loginConfig.getXmppPort()); edit.putString(Constant.XMPP_SEIVICE_NAME, loginConfig.getXmppServiceName()); edit.putString(Constant.USERNAME, loginConfig.getUsername()); edit.putString(Constant.PASSWORD, loginConfig.getPassword()); edit.commit(); } public IMLoginConfig getLoginConfig() { IMLoginConfig loginConfig = new IMLoginConfig(); loginConfig.setXmppHost(sp.getString(Constant.XMPP_HOST, Constant.VALUE_HOST_LOCAL)); loginConfig.setXmppPort(sp.getInt(Constant.XMPP_PORT, Constant.VALUE_XMPP_PORT)); loginConfig.setUsername(sp.getString(Constant.USERNAME, null)); loginConfig.setPassword(sp.getString(Constant.PASSWORD, null)); loginConfig.setXmppServiceName(sp.getString(Constant.XMPP_SEIVICE_NAME, Constant.VALUE_XMPP_SERVICE_NAME)); return loginConfig; } // 初始化连接数据 public XMPPConnection init(IMLoginConfig loginConfig) { Connection.DEBUG_ENABLED = false; ProviderManager pm = ProviderManager.getInstance(); configure(pm); connectionConfig = new ConnectionConfiguration(loginConfig.getXmppHost(), loginConfig.getXmppPort(), loginConfig.getXmppServiceName()); connectionConfig.setSASLAuthenticationEnabled(false);// 不使用SASL验证,设置为false connectionConfig.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled); // 允许自动连接 connectionConfig.setReconnectionAllowed(false); // 允许登陆成功后更新在线状态 connectionConfig.setSendPresence(true); // 收到好友邀请后manual表示需要经过同意,accept_all表示不经同意自动为好友 Roster.setDefaultSubscriptionMode(Roster.SubscriptionMode.accept_all); try { Class.forName("org.jivesoftware.smackx.ServiceDiscoveryManager", true, XmppManager.class.getClassLoader()); } catch (ClassNotFoundException e) { e.printStackTrace(); } connection = new XMPPConnection(connectionConfig); return connection; } /** * * 返回一个有效的xmpp连接,如果无效则返回空. * * @return */ public XMPPConnection getConnection() { if (connection == null) { throw new RuntimeException("请先初始化XMPPConnection连接"); } return connection; } /** * * 销毁xmpp连接. */ public void disconnect() { new Thread() { public void run() { if (connection != null && connection.isConnected()) { connection.disconnect(); connection = null; /* * if (connectionListener != null) { * connection.removeConnectionListener(connectionListener); * } */ } } }.start(); } /** * 登陆到服务器 * * @param username * @param password * @return */ public boolean login(String username, String password) { Roster roster; boolean flag = true; try { connection.login(username, password); // if (connectionListener != null) { // connection.addConnectionListener(connectionListener); // } roster = connection.getRoster(); roster.addRosterListener(new RosterListener() {// 监听Roster @Override public void entriesAdded(Collection<String> collection) {// 添加好友的时候触发 String jid = ""; Iterator<String> it = collection.iterator(); if (it.hasNext()) { jid = it.next() + connection.getServiceName(); } // 订阅好友的Presence Presence presence = new Presence(Presence.Type.subscribe); presence.setTo(jid); // presence.setMode(Presence.Mode.available); connection.sendPacket(presence); } @Override public void entriesDeleted(Collection<String> arg0) { } @Override public void entriesUpdated(Collection<String> arg0) { } @Override public void presenceChanged(Presence p) { // 当订阅的好友presence改变的时候调用 } }); } catch (Exception e) { flag = false; } return flag; } /** * 注册 * * @param account * 注册帐号 * @param password * 注册密码 * @return 1、注册成功 0、服务器没有返回结果2、这个账号已经存在3、注册失败 */ public String regist(String account, String password) { Log.i(TAG, "开始注册------------>"); String str = null; if (connection == null) str = "0"; Registration reg = new Registration(); reg.setType(IQ.Type.SET); reg.setTo(connection.getServiceName()); reg.setUsername(account);// 注意这里createAccount注册时,参数是username,不是jid,是“@”前面的部分。 reg.setPassword(password); reg.addAttribute("android", "geolo_createUser_android");// 这边addAttribute不能为空,否则出错。所以做个标志是android手机创建的吧!!!!! PacketFilter filter = new AndFilter(new PacketIDFilter(reg.getPacketID()), new PacketTypeFilter(IQ.class)); PacketCollector collector = connection.createPacketCollector(filter); connection.sendPacket(reg); Log.i(TAG, "注册结束------------>"); IQ result = (IQ) collector.nextResult(SmackConfiguration.getPacketReplyTimeout()); collector.cancel();// 停止请求results(是否成功的结果) if (result == null) { Log.e(TAG, "无响应."); str = "0"; } else if (result.getType() == IQ.Type.ERROR) { if (result.getError().toString().equalsIgnoreCase("conflict(409)")) { Log.e(TAG, "这个账号已经存在"); str = "2"; } else { Log.e(TAG, "注册失败"); str = "3"; } } else if (result.getType() == IQ.Type.RESULT) { Log.e(TAG, "恭喜你注册成功"); str = "1"; } return str; } /** * 用户加入时向服务器发送的报文 ,就是XMPPCONNECTION来发送 * * @用法:connnection.sendPacket(leaveXml()); * @return */ public IQ joinXml(String jid) { IQ iq = new IQ() { public String getChildElementXML() { StringBuilder buf = new StringBuilder(); buf.append("<query xmlns="jabber:iq:private">"); buf.append("<storage xmlns="storage:bookmarks">"); buf.append("<").append("conference").append(" name="ccc"").append(" autojoin="false"").append(""); buf.append("</storage>"); buf.append("</query>"); return buf.toString(); } }; iq.setType(IQ.Type.SET); // 方法如名,这里是设置这份报文来至那个JID,后边的/smack是这段信息来至哪个端,如spark端就是/spark,android就是/Smack iq.setFrom(jid + "/Smack"); return iq; } /** * 获取用户的vcard信息 . * * @return * */ public VCard getUserVCard(String jid) { VCard vcard = new VCard(); try { if (connection.isConnected() && connection.isAuthenticated()) { vcard.load(connection, jid); } } catch (XMPPException e) { e.printStackTrace(); } return vcard; } /** * * 保存用户的vcard信息. 注:修改vcard时,头像会丢失,此处为asmack.jar的bug,目前还无法修复 * * @param vCard * @return * */ public VCard saveUserVCard(VCard vCard) { try { vCard.save(connection); return getUserVCard(vCard.getJabberId()); } catch (XMPPException e) { e.printStackTrace(); } return null; } /** * * 获取用户头像信息 . * * @param connection * @param jid * @return */ public InputStream getUserImage(String jid) { InputStream ic = null; try { VCard vcard = new VCard(); vcard.load(connection, jid); if (vcard == null || vcard.getAvatar() == null) { return null; } ByteArrayInputStream bais = new ByteArrayInputStream(vcard.getAvatar()); return bais; } catch (Exception e) { e.printStackTrace(); } return ic; } /** * 从服务器上查询用户 * * @param username * @param connection * @return */ public List<IMUser> findUsers(String username) { List<IMUser> results = new ArrayList<IMUser>(); try { UserSearchManager usm = new UserSearchManager(connection); String serverDomain = "search." + connection.getServiceName(); Form searchForm = usm.getSearchForm(serverDomain); Form answerForm = searchForm.createAnswerForm(); answerForm.setAnswer("Username", true); answerForm.setAnswer("search", username); ReportedData data = usm.getSearchResults(answerForm, serverDomain); Iterator<Row> it = data.getRows(); Row row = null; IMUser user = null; while (it.hasNext()) { user = new IMUser(); row = it.next(); String jid = row.getValues("Jid").next().toString(); String name = row.getValues("Username").next().toString(); String email = row.getValues("Email").next().toString(); user.setJID(jid); user.setName(name); user.setEmail(email); results.add(user); } return results; } catch (XMPPException e) { e.printStackTrace(); } return results; } /** * 查找用户 * * @param serverDomain * @param userName * @return */ public List<IMUser> searchUsers(String serverDomain, String userName) { List<IMUser> list = new ArrayList<IMUser>(); UserSearchManager userSearchManager = new UserSearchManager(connection); try { Form searchForm = userSearchManager.getSearchForm("search." + serverDomain); Form answerForm = searchForm.createAnswerForm(); answerForm.setAnswer("Username", true); answerForm.setAnswer("Name", true); answerForm.setAnswer("search", userName); ReportedData data = userSearchManager.getSearchResults(answerForm, "search." + serverDomain); Iterator<Row> rows = data.getRows(); while (rows.hasNext()) { IMUser user = new IMUser(); Row row = rows.next(); user.setName(row.getValues("Username").next().toString()); user.setNickName(row.getValues("Name").next().toString()); Logger.i(TAG, user.toString()); list.add(user); } } catch (XMPPException e) { Logger.i(TAG, Log.getStackTraceString(e)); } return list; } /** * 发送文件 * * @param recvUser * @param filePath */ public void sendFile(String recvUser, String filePath) { FileTransferManager fileTransferManager = new FileTransferManager(connection); try { final OutgoingFileTransfer outgoingFileTransfer = fileTransferManager.createOutgoingFileTransfer(recvUser); outgoingFileTransfer.sendFile(new File(filePath), "outgoingFileTransfer ^_^"); new App().execRunnable(new Runnable() { @Override public void run() { while (!outgoingFileTransfer.isDone()) { try { Thread.sleep(100); } catch (InterruptedException e) { } } if (outgoingFileTransfer.getStatus().equals(Status.complete)) Logger.i(TAG, "上送完毕"); else if (outgoingFileTransfer.getStatus().equals(Status.error)) Logger.i(TAG, "上送出错"); } }); } catch (XMPPException e) { Logger.i(TAG, "上送文件异常"); Logger.i(TAG, Log.getStackTraceString(e)); } } /** * 注册文件接收器 */ public void registRecvFileListener() { FileTransferManager fileTransferManager = new FileTransferManager(connection); fileTransferManager.addFileTransferListener(new FileTransferListener() { public void fileTransferRequest(final FileTransferRequest request) { final IncomingFileTransfer transfer = request.accept(); try { Logger.i(TAG, "接受文件:" + transfer.getFileName()); transfer.recieveFile(new File(Environment.getExternalStorageDirectory() + "/" + request.getFileName())); new App().execRunnable(new Runnable() { @Override public void run() { while (!transfer.isDone()) { Logger.i(TAG, "进度:" + transfer.getProgress()); try { Thread.sleep(100); } catch (InterruptedException e) { Logger.i(TAG, Log.getStackTraceString(e)); } } Logger.i(TAG, "接受状态" + transfer.getStatus()); if (transfer.getStatus().equals(Status.complete)) Logger.i(TAG, "接受完毕"); else if (transfer.getStatus().equals(Status.error)) { transfer.cancel(); Logger.i(TAG, "接受出错"); } } }); } catch (Exception e) { Logger.i(TAG, Log.getStackTraceString(e)); Logger.i(TAG, "文件接收出错"); transfer.cancel(); } } }); } /** * 返回群组所有组信息 <RosterGroup> * * @return List(RosterGroup) */ public List<RosterGroup> getGroups(Roster roster) { List<RosterGroup> groupsList = new ArrayList<RosterGroup>(); Collection<RosterGroup> rosterGroup = roster.getGroups(); Iterator<RosterGroup> i = rosterGroup.iterator(); while (i.hasNext()) { groupsList.add(i.next()); } return groupsList; } /** * 创建群组 * * @param roster * @param groupName * @return */ public boolean createGroup(Roster roster, String groupName) { RosterEntry entry = roster.getEntries().iterator().next(); try { roster.createGroup(groupName).addEntry(entry); return true; } catch (XMPPException e) { e.printStackTrace(); return false; } } /** * 返回相应(groupName)组里的所有用户<RosterEntry> * * @return List(RosterEntry) */ public List<RosterEntry> getEntriesByGroup(Roster roster, String groupName) { List<RosterEntry> EntriesList = new ArrayList<RosterEntry>(); RosterGroup rosterGroup = roster.getGroup(groupName); Collection<RosterEntry> rosterEntry = rosterGroup.getEntries(); Iterator<RosterEntry> it = rosterEntry.iterator(); while (it.hasNext()) EntriesList.add(it.next()); return EntriesList; } /** * 获得某个群组中的所有成员 * * @param roster * @param groupName * @return */ public List<RosterEntry> getEntrysByGroup(Roster roster, String groupName) { List<RosterEntry> list = new ArrayList<RosterEntry>(); RosterGroup group = roster.getGroup(groupName); list.addAll(group.getEntries()); return list; } /** * 返回所有用户信息 <RosterEntry> * * @return List(RosterEntry) */ public List<RosterEntry> getAllEntries(Roster roster) { List<RosterEntry> EntriesList = new ArrayList<RosterEntry>(); Collection<RosterEntry> rosterEntry = roster.getEntries(); Iterator<RosterEntry> i = rosterEntry.iterator(); while (i.hasNext()) EntriesList.add(i.next()); return EntriesList; } /** * 获得所有的好友 * * @param roster * @return */ public List<RosterEntry> getAllEntrys(Roster roster) { List<RosterEntry> list = new ArrayList<RosterEntry>(); list.addAll(roster.getEntries()); return list; } /** * 添加一个组 */ public boolean addGroup(Roster roster, String groupName) { try { roster.createGroup(groupName); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 删除一个组 */ public boolean removeGroup(Roster roster, String groupName) { // roster.removeEntry(groupName); return false; } /** * 添加一个好友 无分组 */ public boolean addUser(Roster roster, String userName, String nickName) { try { roster.createEntry(userName, nickName, null); return true; } catch (Exception 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, null == groupName ? null : new String[] { groupName }); return true; } catch (XMPPException e) { Log.e(TAG, Log.getStackTraceString(e)); } 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); if (null != entry) roster.removeEntry(entry); return true; } catch (XMPPException e) { Log.e(TAG, Log.getStackTraceString(e)); } return false; } /** * 添加用户到群组 * * @param roster * @param userName * @param groupName */ public void addUserToGroup(Roster roster, String userName, String groupName) { RosterGroup group = roster.getGroup(groupName); if (null == group) { group = roster.createGroup(groupName); } RosterEntry entry = roster.getEntry(userName); try { group.addEntry(entry); } catch (XMPPException e) { Log.e(TAG, Log.getStackTraceString(e)); } } /** * 修改心情 * * @param connection * @param status */ public void changeStateMessage(String status) { Presence presence = new Presence(Presence.Type.available); presence.setStatus(status); connection.sendPacket(presence); } /** * 更改用户头像 * * @param file * @param jid * @throws XMPPException * @throws IOException */ public void changeImage(File file, String jid) throws XMPPException, IOException { VCard vcard = new VCard(); vcard.load(connection, jid); byte[] bytes; bytes = getFileBytes(file); String encodedImage = StringUtils.encodeBase64(bytes); vcard.setAvatar(bytes, encodedImage); vcard.setEncodedImage(encodedImage); vcard.save(connection); } 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 pm */ public MultiUserChat createRoom(String roomName, String roomPwd, String subject) { if (getConnection() == null) return null; // 使用XMPPConnection创建一个MultiUserChat MultiUserChat multiUserChat = new MultiUserChat(connection, roomName + CONFERENCE + connection.getServiceName()); try { // 创建聊天室 multiUserChat.create(roomName); // 获得聊天室的配置表单 Form configForm = multiUserChat.getConfigurationForm(); // 根据原始表单创建一个要提交的新表单。 Form submitForm = configForm.createAnswerForm(); // 向要提交的表单添加默认答复 for (Iterator<FormField> fields = configForm.getFields(); fields.hasNext();) { FormField formField = fields.next(); if (!formField.getType().equals(FormField.TYPE_HIDDEN) && formField.getVariable() != null) { // 设置默认值作为答复 submitForm.setDefaultAnswer(formField.getVariable()); } } List<String> owners = new ArrayList<String>(); owners.add(connection.getUser()); // 设置聊天室的新拥有者 // List owners = new ArrayList(); // owners.add("liaonaibo2\40slook.cc"); // owners.add("liaonaibo1\40slook.cc"); // submitForm.setAnswer("muc#roomconfig_roomowners", owners); submitForm.setAnswer("muc#roomconfig_passwordprotectedroom", true); // 设置聊天室是持久聊天室,即将要被保存下来 submitForm.setAnswer("muc#roomconfig_persistentroom", true); // 房间仅对成员开放 submitForm.setAnswer("muc#roomconfig_membersonly", false); // 允许占有者邀请其他人 submitForm.setAnswer("muc#roomconfig_allowinvites", true); // 能够发现占有者真实 JID 的角色 // submitForm.setAnswer("muc#roomconfig_whois", "anyone"); submitForm.setAnswer("muc#roomconfig_maxusers", Arrays.asList("500")); // 登录房间对话 submitForm.setAnswer("muc#roomconfig_enablelogging", true); // 仅允许注册的昵称登录 submitForm.setAnswer("x-muc#roomconfig_reservednick", true); // 允许使用者修改昵称 submitForm.setAnswer("x-muc#roomconfig_canchangenick", true); // 允许用户注册房间 submitForm.setAnswer("x-muc#roomconfig_registration", true); submitForm.setAnswer("muc#roomconfig_roomsecret", roomPwd); submitForm.setAnswer("muc#roomconfig_roomdesc", subject); // 发送已完成的表单(有默认值)到服务器来配置聊天室 multiUserChat.sendConfigurationForm(submitForm); // 通知主界面已创建了新的房间, 主界面需要刷新显示 Uri uri = Uri.parse(Constant.IM_ROOM_CONTENT_PATH); mContext.getContentResolver().notifyChange(uri, null); } catch (XMPPException e) { e.getStackTrace(); return null; } return multiUserChat; } /** * 初始化房间列表 */ public void initChatRoom(String jid) { List<DiscoverItems.Item> listDiscoverItems = new ArrayList<DiscoverItems.Item>(); // 获得与XMPPConnection相关的ServiceDiscoveryManager ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(connection); // 获得指定XMPP实体的项目 // 这个例子获得与在线目录服务相关的项目 DiscoverItems discoItems; try { discoItems = discoManager.discoverItems(jid); // 获得被查询的XMPP实体的要查看的项目 @SuppressWarnings("rawtypes") Iterator it = discoItems.getItems(); // 显示远端XMPP实体的项目 while (it.hasNext()) { DiscoverItems.Item item = (DiscoverItems.Item) it.next(); listDiscoverItems.add(item); } } catch (XMPPException e) { e.printStackTrace(); } } /** * 加入聊天室 * * @param user * @param pwd * 会议室密码 * @param roomName * @return */ public MultiUserChat joinRoom(String user, String pwd, String roomName) { MultiUserChat muc = new MultiUserChat(connection, roomName.contains(CONFERENCE) ? roomName : roomName + CONFERENCE + connection.getServiceName()); DiscussionHistory history = new DiscussionHistory(); history.setMaxStanzas(100); // history.setSince(new Date(2014, 01, 01)); // history.setSince(new Date()); try { muc.join(user, pwd, history, SmackConfiguration.getPacketReplyTimeout()); } catch (XMPPException e) { e.printStackTrace(); return null; } return muc; } /** * 查询会议室成员名字 * * @param muc */ public List<String> findMulitUser(MultiUserChat muc) { if (getConnection() == null) return null; 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 */ public List<IMMucRoom> getJoinedRooms() { List<IMMucRoom> rooms = new ArrayList<IMMucRoom>(); Iterator<String> it = MultiUserChat.getJoinedRooms(connection, connection.getUser()); while (it.hasNext()) { IMMucRoom room = new IMMucRoom(); room.name = it.next(); rooms.add(room); } return rooms; } /** * 创建私聊 * * @param participant * @param listener * @return */ public Chat createPrivateChat(String participant, MessageListener listener) { return muc.createPrivateChat(participant, listener); } /** * 离开聊天室 */ public void leaveRoom() { if (null != muc) muc.leave(); muc = null; } /** * 获取服务器上所有会议室 * * @return * @throws XMPPException */ public List<IMMucRoom> getAllRooms() throws XMPPException { List<IMMucRoom> list = new ArrayList<IMMucRoom>(); new ServiceDiscoveryManager(connection); if (!MultiUserChat.getHostedRooms(connection, connection.getServiceName()).isEmpty()) { Collection<HostedRoom> rooms = MultiUserChat.getHostedRooms(connection, "conference." + connection.getServiceName());// 获取服务器上面存在的所有聊天室 // 查询服务器上的聊天室 // Collection<HostedRoom> rooms = // MultiUserChat.getHostedRooms(connection, // connection.getServiceName()); for (HostedRoom room : rooms) { // 查看Room消息 IMMucRoom friendrooms = new IMMucRoom(); friendrooms.setName(room.getName());// 聊天室的名称 friendrooms.setJid(room.getJid());// 聊天室JID RoomInfo roomInfo = MultiUserChat.getRoomInfo(connection, room.getJid()); if (roomInfo != null) { friendrooms.setOccupants(roomInfo.getOccupantsCount());// 聊天室中占有者数量 friendrooms.setDescription(roomInfo.getDescription());// 聊天室的描述 friendrooms.setSubject(roomInfo.getSubject());// 聊天室的主题 } list.add(friendrooms); } } return list; } /** * 初始化会议室列表 */ public List<HostedRoom> getHostRooms() { if (getConnection() == null) return null; Collection<HostedRoom> hostrooms = null; List<HostedRoom> roominfos = new ArrayList<HostedRoom>(); try { new ServiceDiscoveryManager(getConnection()); hostrooms = MultiUserChat.getHostedRooms(getConnection(), getConnection().getServiceName()); for (HostedRoom entry : hostrooms) { roominfos.add(entry); Logger.i("room", "名字:" + entry.getName() + " - ID:" + entry.getJid()); } Logger.i("room", "服务会议数量:" + roominfos.size()); } catch (XMPPException e) { e.printStackTrace(); } return roominfos; } /** * 用户是否支持的聊天室 * * @param user * @return */ public boolean isUserSupportMUC(String user) { return MultiUserChat.isServiceEnabled(connection, user); } /** * 得到所有离线消息 * * @return */ public List<Message> getOffLineMessages() { List<Message> msgs = new ArrayList<Message>(); OfflineMessageManager offLineMessageManager = new OfflineMessageManager(connection); try { Iterator<Message> it = offLineMessageManager.getMessages(); while (it.hasNext()) { Message msg = it.next(); msgs.add(msg); } offLineMessageManager.deleteMessages(); } catch (XMPPException e) { e.printStackTrace(); } return msgs; } /** * 获取离线消息 * * @return */ public Map<String, List<HashMap<String, String>>> getHisMessage() { if (getConnection() == null) return null; Map<String, List<HashMap<String, String>>> offlineMsgs = null; try { OfflineMessageManager offlineManager = new OfflineMessageManager(getConnection()); Iterator<Message> it = offlineManager.getMessages(); int count = offlineManager.getMessageCount(); if (count <= 0) return null; offlineMsgs = new HashMap<String, List<HashMap<String, String>>>(); while (it.hasNext()) { Message message = it.next(); String fromUser = StringUtils.parseName(message.getFrom()); HashMap<String, String> histrory = new HashMap<String, String>(); histrory.put("useraccount", StringUtils.parseName(getConnection().getUser())); histrory.put("friendaccount", fromUser); histrory.put("info", message.getBody()); histrory.put("type", "left"); if (offlineMsgs.containsKey(fromUser)) { offlineMsgs.get(fromUser).add(histrory); } else { List<HashMap<String, String>> temp = new ArrayList<HashMap<String, String>>(); temp.add(histrory); offlineMsgs.put(fromUser, temp); } } offlineManager.deleteMessages(); } catch (Exception e) { e.printStackTrace(); } return offlineMsgs; } /** * 判断OpenFire用户的状态 strUrl : url格式 - * http://my.openfire.com:9090/plugins/presence * /status?jid=user1@SERVER_NAME&type=xml 返回值 : 0 - 用户不存在; 1 - 用户在线; 2 - * 用户离线 说明 :必须要求 OpenFire加载 presence 插件,同时设置任何人都可以访问 */ public int IsUserOnLine(String user, String host) { String url = "http://" + host + ":9090/plugins/presence/status?" + "jid=" + user + "@" + connection.getServiceName() + "&type=xml"; int shOnLineState = 0; // 不存在 try { URL oUrl = new URL(url); URLConnection oConn = oUrl.openConnection(); if (oConn != null) { BufferedReader oIn = new BufferedReader(new InputStreamReader(oConn.getInputStream())); if (null != oIn) { String strFlag = oIn.readLine(); oIn.close(); if (strFlag.indexOf("type="unavailable"") >= 0) { shOnLineState = 2; } if (strFlag.indexOf("type="error"") >= 0) { shOnLineState = 0; } else if (strFlag.indexOf("priority") >= 0 || strFlag.indexOf("id="") >= 0) { shOnLineState = 1; } } } } catch (Exception e) { e.printStackTrace(); } return shOnLineState; } /** * 设置状态 表示XMPP状态的packet。每个presence packet都有一个状态。 用枚举类型Presence.Type的值表示: * * @available -- (默认)用户空闲状态 * @unavailable -- 用户没空看消息 * @subscribe -- 请求订阅别人,即请求加对方为好友 * @subscribed -- 统一被别人订阅,也就是确认被对方加为好友 * @unsubscribe -- 他取消订阅别人,请求删除某好友 * @subscribed -- 拒绝被别人订阅,即拒绝对放的添加请求 * @error -- 当前状态packet有错误 * @param state */ public void setPresence(int state) { Presence presence; switch (state) { case 0: presence = new Presence(Presence.Type.available);// (默认)用户空闲状态 connection.sendPacket(presence); Log.e(TAG, "设置在线"); break; case 1: presence = new Presence(Presence.Type.available); presence.setMode(Presence.Mode.chat);// /presence.setMode(Presence.Mode.dnd); connection.sendPacket(presence); Log.e(TAG, "Q我吧"); Log.e(TAG, presence.toXML()); break; case 2: presence = new Presence(Presence.Type.available); presence.setMode(Presence.Mode.dnd); connection.sendPacket(presence); Log.e(TAG, "忙碌"); Log.e(TAG, presence.toXML()); break; case 3: presence = new Presence(Presence.Type.available); presence.setMode(Presence.Mode.away); connection.sendPacket(presence); Log.e(TAG, "离开"); Log.e(TAG, presence.toXML()); break; case 4: Roster roster = connection.getRoster(); Collection<RosterEntry> entries = roster.getEntries(); for (RosterEntry entity : entries) { presence = new Presence(Presence.Type.unavailable);// 用户没空看消息 presence.setPacketID(Packet.ID_NOT_AVAILABLE); presence.setFrom(connection.getUser()); presence.setTo(entity.getUser()); connection.sendPacket(presence); Log.e(TAG, presence.toXML()); } Log.e(TAG, "告知其他用户-隐身"); // 向同一用户的其他客户端发送隐身状态 presence = new Presence(Presence.Type.unavailable); presence.setPacketID(Packet.ID_NOT_AVAILABLE); presence.setFrom(connection.getUser()); presence.setTo(StringUtils.parseBareAddress(connection.getUser())); connection.sendPacket(presence); Log.e(TAG, "告知本用户的其他客户端-隐身"); Log.e(TAG, presence.toXML()); break; case 5: presence = new Presence(Presence.Type.unavailable); connection.sendPacket(presence); Log.e(TAG, "离线"); Log.e(TAG, presence.toXML()); break; default: break; } } /** * 删除账号 * * @return */ public boolean deleteCount() { try { connection.getAccountManager().deleteAccount(); return true; } catch (XMPPException e) { Log.e(TAG, Log.getStackTraceString(e)); } return false; } /** * 开启服务 */ public void startService() { // 好友联系人服务 Intent server = new Intent(mContext, IMContactService.class); mContext.startService(server); // 聊天服务 Intent chatServer = new Intent(mContext, IMChatService.class); mContext.startService(chatServer); // 自动恢复连接服务 Intent reConnectService = new Intent(mContext, IMReConnectService.class); mContext.startService(reConnectService); // 系统消息连接服务 Intent imSystemMsgService = new Intent(mContext, IMSystemMsgService.class); mContext.startService(imSystemMsgService); } /** * * 销毁服务. */ public void stopService() { // 好友联系人服务 Intent server = new Intent(mContext, IMContactService.class); boolean isRunning = ServiceUtils.isServiceRunning(mContext, "com.ymerp.android.service.IMContactService"); if (isRunning) { mContext.stopService(server); } // 聊天服务 Intent chatServer = new Intent(mContext, IMChatService.class); isRunning = ServiceUtils.isServiceRunning(mContext, "com.ymerp.android.service.IMChatService"); if (isRunning) { mContext.stopService(chatServer); } // 自动恢复连接服务 Intent reConnectService = new Intent(mContext, IMReConnectService.class); isRunning = ServiceUtils.isServiceRunning(mContext, "com.ymerp.android.service.IMReConnectService"); if (isRunning) { mContext.stopService(reConnectService); } // 系统消息连接服务 Intent imSystemMsgService = new Intent(mContext, IMSystemMsgService.class); isRunning = ServiceUtils.isServiceRunning(mContext, "com.ymerp.android.service.IMSystemMsgService"); if (isRunning) { mContext.stopService(imSystemMsgService); } } /** * * 处理离线消息. * * @param connection */ public void dealOfflineMsg() { OfflineMessageManager offlineManager = new OfflineMessageManager(connection); try { Iterator<org.jivesoftware.smack.packet.Message> it = offlineManager.getMessages(); Logger.i("离线消息数量: ", "" + offlineManager.getMessageCount()); while (it.hasNext()) { org.jivesoftware.smack.packet.Message message = it.next(); Logger.i("收到离线消息", "Received from 【" + message.getFrom() + "】 message: " + message.getBody()); if (message != null && message.getBody() != null && !message.getBody().equals("null")) { IMMessage msg = new IMMessage(); String time = (String) message.getProperty(IMMessage.KEY_TIME); msg.setTime(time == null ? DateUtil.getCurDateStr() : time); msg.setContent(message.getBody()); if (Message.Type.error == message.getType()) { msg.setType(IMMessage.ERROR); } else { msg.setType(IMMessage.SUCCESS); } String from = message.getFrom().split("/")[0]; msg.setFromSubJid(from); // 生成通知 IMNoticeManager noticeManager = IMNoticeManager.getInstance(mContext); IMNotice notice = new IMNotice(); notice.setTitle("会话信息"); notice.setNoticeType(IMNotice.CHAT_MSG); notice.setContent(message.getBody()); notice.setFrom(from); notice.setStatus(IMNotice.UNREAD); notice.setNoticeTime(time == null ? DateUtil.getCurDateStr() : time); // 历史记录 IMMessage newMessage = new IMMessage(); newMessage.setMsgType(0); newMessage.setFromSubJid(from); newMessage.setContent(message.getBody()); newMessage.setTime(time == null ? DateUtil.getCurDateStr() : time); IMMessageManager.getInstance(mContext).saveIMMessage(newMessage); long noticeId = noticeManager.saveNotice(notice); if (noticeId != -1) { Intent intent = new Intent(Constant.NEW_MESSAGE_ACTION); intent.putExtra(IMMessage.IMMESSAGE_KEY, msg); intent.putExtra("noticeId", noticeId); mContext.sendBroadcast(intent); IMUtils.setNotiType(mContext, R.drawable.im_head, mContext.getResources().getString(R.string.new_message), notice.getContent(), IMChatActivity.class, from); } } } offlineManager.deleteMessages(); } catch (Exception e) { e.printStackTrace(); } } /** * 连接监听类 * */ class IMConnectionListener implements ConnectionListener { private Timer timer; private String username; private String password; private int logintime = 2000; @Override public void connectionClosed() { Log.i(TAG, "连接关闭"); // 关闭连接 disconnect(); // 重连服务器 timer = new Timer(); timer.schedule(new timetask(), logintime); } @Override public void connectionClosedOnError(Exception e) { Log.i(TAG, "连接关闭异常"); // 判斷為帳號已被登錄 boolean error = e.getMessage().equals("stream:error (conflict)"); if (!error) { // 关闭连接 disconnect(); // 重连服务器 timer = new Timer(); timer.schedule(new timetask(), logintime); } } class timetask extends TimerTask { @Override public void run() { username = sp.getString(Constant.USERNAME, null); password = sp.getString(Constant.PASSWORD, null); if (username != null && password != null) { Logger.i(TAG, "尝试登陆"); // 连接服务器 if (login(username, password)) { Logger.i(TAG, "登陆成功"); } else { Logger.i(TAG, "重新登陆"); timer.schedule(new timetask(), logintime); } } } } @Override public void reconnectingIn(int arg0) { } @Override public void reconnectionFailed(Exception arg0) { } @Override public void reconnectionSuccessful() { } } public void configure(ProviderManager pm) { // Private Data Storage pm.addIQProvider("query", "jabber:iq:private", new PrivateDataManager.PrivateDataIQProvider()); // Time try { pm.addIQProvider("query", "jabber:iq:time", Class.forName("org.jivesoftware.smackx.packet.Time")); } catch (ClassNotFoundException e) { } // XHTML pm.addExtensionProvider("html", "http://jabber.org/protocol/xhtml-im", new XHTMLExtensionProvider()); // Roster Exchange pm.addExtensionProvider("x", "jabber:x:roster", new RosterExchangeProvider()); // Message Events pm.addExtensionProvider("x", "jabber:x:event", new MessageEventProvider()); // Chat State pm.addExtensionProvider("active", "http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider()); pm.addExtensionProvider("composing", "http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider()); pm.addExtensionProvider("paused", "http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider()); pm.addExtensionProvider("inactive", "http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider()); pm.addExtensionProvider("gone", "http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider()); // FileTransfer pm.addIQProvider("si", "http://jabber.org/protocol/si", new StreamInitiationProvider()); // Group Chat Invitations pm.addExtensionProvider("x", "jabber:x:conference", new GroupChatInvitation.Provider()); // 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()); // Data Forms pm.addExtensionProvider("x", "jabber:x:data", new DataFormProvider()); // MUC User pm.addExtensionProvider("x", "http://jabber.org/protocol/muc#user", new MUCUserProvider()); // MUC Admin pm.addIQProvider("query", "http://jabber.org/protocol/muc#admin", new MUCAdminProvider()); // MUC Owner pm.addIQProvider("query", "http://jabber.org/protocol/muc#owner", new MUCOwnerProvider()); // Delayed Delivery pm.addExtensionProvider("x", "jabber:x:delay", new DelayInformationProvider()); // Version try { pm.addIQProvider("query", "jabber:iq:version", Class.forName("org.jivesoftware.smackx.packet.Version")); } catch (ClassNotFoundException e) { } // VCard pm.addIQProvider("vCard", "vcard-temp", new VCardProvider()); // 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()); // Last Activity pm.addIQProvider("query", "jabber:iq:last", new LastActivity.Provider()); // User Search pm.addIQProvider("query", "jabber:iq:search", new UserSearch.Provider()); // SharedGroupsInfo pm.addIQProvider("sharedgroup", "http://www.jivesoftware.org/protocol/sharedgroup", new SharedGroupsInfo.Provider()); // JEP-33: Extended Stanza Addressing pm.addExtensionProvider("addresses", "http://jabber.org/protocol/address", new MultipleAddressesProvider()); } }