package com.yyquan.jzh.xmpp; import android.content.Context; import android.util.Log; import android.widget.ImageView; import com.yyquan.jzh.R; import com.yyquan.jzh.entity.User; import com.yyquan.jzh.entity.XmppUser; import com.yyquan.jzh.util.SLog; import com.yyquan.jzh.util.SaveUserUtil; import com.yyquan.jzh.util.SharedPreferencesUtil; import org.jivesoftware.smack.AccountManager; import org.jivesoftware.smack.Connection; import org.jivesoftware.smack.ConnectionConfiguration; import org.jivesoftware.smack.ConnectionListener; import org.jivesoftware.smack.PacketCollector; 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.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.PrivacyProvider; import org.jivesoftware.smack.provider.ProviderManager; import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smackx.Form; import org.jivesoftware.smackx.GroupChatInvitation; import org.jivesoftware.smackx.OfflineMessageManager; import org.jivesoftware.smackx.PrivateDataManager; import org.jivesoftware.smackx.ReportedData; import org.jivesoftware.smackx.bytestreams.ibb.provider.CloseIQProvider; import org.jivesoftware.smackx.bytestreams.ibb.provider.DataPacketProvider; import org.jivesoftware.smackx.bytestreams.ibb.provider.OpenIQProvider; import org.jivesoftware.smackx.bytestreams.socks5.provider.BytestreamsProvider; import org.jivesoftware.smackx.packet.ChatStateExtension; import org.jivesoftware.smackx.packet.LastActivity; import org.jivesoftware.smackx.packet.OfflineMessageInfo; import org.jivesoftware.smackx.packet.OfflineMessageRequest; import org.jivesoftware.smackx.packet.SharedGroupsInfo; import org.jivesoftware.smackx.packet.VCard; import org.jivesoftware.smackx.provider.AdHocCommandDataProvider; import org.jivesoftware.smackx.provider.DataFormProvider; import org.jivesoftware.smackx.provider.DelayInformationProvider; import org.jivesoftware.smackx.provider.DiscoverInfoProvider; import org.jivesoftware.smackx.provider.DiscoverItemsProvider; import org.jivesoftware.smackx.provider.MUCAdminProvider; import org.jivesoftware.smackx.provider.MUCOwnerProvider; import org.jivesoftware.smackx.provider.MUCUserProvider; import org.jivesoftware.smackx.provider.MessageEventProvider; import org.jivesoftware.smackx.provider.MultipleAddressesProvider; import org.jivesoftware.smackx.provider.RosterExchangeProvider; import org.jivesoftware.smackx.provider.StreamInitiationProvider; import org.jivesoftware.smackx.provider.VCardProvider; import org.jivesoftware.smackx.provider.XHTMLExtensionProvider; import org.jivesoftware.smackx.search.UserSearch; import org.jivesoftware.smackx.search.UserSearchManager; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; public class XmppTool { private String tag = "XmppTool"; private static XmppTool instance; public static final String HOST = "123.207.145.194"; // public static final String HOST = "192.168.1.188"; public static final int PORT = 5222; private static XMPPConnection con; Context context; public static XmppTool getInstance() { if (null == instance) instance = new XmppTool(); return instance; } private XmppTool() { configure(ProviderManager.getInstance()); ConnectionConfiguration connConfig = new ConnectionConfiguration(HOST, PORT); connConfig.setSASLAuthenticationEnabled(false); connConfig.setReconnectionAllowed(true); connConfig.setSendPresence(false); // connConfig.setSecurityMode(ConnectionConfiguration.SecurityMode.enabled); // connConfig.setSendPresence(true); con = new XMPPConnection(connConfig); con.DEBUG_ENABLED = true; Roster.setDefaultSubscriptionMode(Roster.SubscriptionMode.manual); try { if (con.isConnected()) {// 首先判断是否还连接着服务器,需要先断开 try { con.disconnect(); } catch (Exception e) { SLog.i(tag, "conn.disconnect() failed: " + e); } } SmackConfiguration.setPacketReplyTimeout(30000);// 设置超时时间 SmackConfiguration.setKeepAliveInterval(-1); SmackConfiguration.setDefaultPingInterval(0); con.connect(); con.addConnectionListener(new ConnectionListener() { @Override public void reconnectionSuccessful() { // TODO Auto-generated method stub SLog.i(tag, "重连成功"); } @Override public void reconnectionFailed(Exception arg0) { // TODO Auto-generated method stub SLog.i(tag, "重连失败"); // User user = SaveUserUtil.loadAccount(context); // login(user.getUser(), user.getPassword()); } @Override public void reconnectingIn(int arg0) { // TODO Auto-generated method stub SLog.i(tag, "重连中"); } @Override public void connectionClosedOnError(Exception e) { // TODO Auto-generated method stub SLog.i(tag, "连接出错"); if (e.getMessage().contains("conflict")) { SLog.i(tag, "被挤掉了"); disConnectServer(); } // User user = SaveUserUtil.loadAccount(context); // login(user.getUser(), user.getPassword()); } @Override public void connectionClosed() { // TODO Auto-generated method stub SLog.i(tag, "连接关闭"); } }); } catch (XMPPException e) { SLog.e(tag, Log.getStackTraceString(e)); } } public XMPPConnection getCon() { return con; } /** * 是否与服务器连接上 * * @return */ public boolean isConnection() { if (con != null) { return (con.isConnected() && con.isAuthenticated()); } return false; } /** * 登录 * * @param name * @param pwd * @return */ public boolean login(String name, String pwd, Context context) { try { this.context = context; // SASLAuthentication.supportSASLMechanism("PLAIN", 0); con.login(name.toLowerCase(), pwd); // getMessage();//获取离线消息 int status = SharedPreferencesUtil.getInt(context, "status", name + "status"); setPresence(status);//设置状态,默认为在线状态 return true; } catch (XMPPException e) { SLog.e(tag, Log.getStackTraceString(e)); } return false; } public boolean login(String name, String pwd) { try { // SASLAuthentication.supportSASLMechanism("PLAIN", 0); con.login(name.toLowerCase(), pwd); // getMessage();//获取离线消息 int status = SharedPreferencesUtil.getInt(context, "status", name + "status"); setPresence(status);//设置状态,默认为在线状态 return true; } catch (XMPPException e) { SLog.e(tag, Log.getStackTraceString(e)); } return false; } /** * 修改密码 * * @param pwd * @return */ public boolean changePassword(String pwd) { try { con.getAccountManager().changePassword(pwd); return true; } catch (XMPPException e) { SLog.e(tag, Log.getStackTraceString(e)); } return false; } /** * 设置状态 * * @param state */ public void setPresence(int state) { Presence presence; switch (state) { //0.在线 1.Q我吧 2.忙碌 3.勿扰 4.离开 5.隐身 6.离线 case 0: presence = new Presence(Presence.Type.available); con.sendPacket(presence); SLog.e(tag, "设置在线"); break; case 1: presence = new Presence(Presence.Type.available); presence.setMode(Presence.Mode.chat); con.sendPacket(presence); SLog.e(tag, "Q我吧"); SLog.e(tag, presence.toXML()); break; case 2: presence = new Presence(Presence.Type.available); presence.setMode(Presence.Mode.dnd); con.sendPacket(presence); SLog.e(tag, "忙碌"); SLog.e(tag, presence.toXML()); break; case 3: presence = new Presence(Presence.Type.available); presence.setMode(Presence.Mode.xa); con.sendPacket(presence); SLog.e(tag, "勿扰"); SLog.e(tag, presence.toXML()); break; case 4: presence = new Presence(Presence.Type.available); presence.setMode(Presence.Mode.away); con.sendPacket(presence); SLog.e(tag, "离开"); SLog.e(tag, presence.toXML()); break; case 5: Roster roster = con.getRoster(); Collection<RosterEntry> entries = roster.getEntries(); for (RosterEntry entity : entries) { presence = new Presence(Presence.Type.unavailable); presence.setPacketID(Packet.ID_NOT_AVAILABLE); presence.setFrom(con.getUser()); presence.setTo(entity.getUser()); con.sendPacket(presence); SLog.e(tag, presence.toXML()); } SLog.e(tag, "告知其他用户-隐身"); break; // case 6: // presence = new Presence(Presence.Type.unavailable); // con.sendPacket(presence); // SLog.e(tag, "离线"); // SLog.e(tag, presence.toXML()); // break; // default: // break; } } public void setPresence(ImageView iv, ImageView iv_me, Context context, String name) { int status = SharedPreferencesUtil.getInt(context, "status", name + "status"); switch (status) { //0.在线 1.Q我吧 2.忙碌 3.勿扰 4.离开 5.隐身 6.离线 case 0: iv.setImageResource(R.mipmap.status_online); iv_me.setImageResource(R.mipmap.status_online); break; case 1: iv.setImageResource(R.mipmap.status_qme); iv_me.setImageResource(R.mipmap.status_qme); break; case 2: iv.setImageResource(R.mipmap.status_busy); iv_me.setImageResource(R.mipmap.status_busy); break; case 3: iv.setImageResource(R.mipmap.status_shield); iv_me.setImageResource(R.mipmap.status_shield); break; case 4: iv.setImageResource(R.mipmap.status_leave); iv_me.setImageResource(R.mipmap.status_leave); break; case 5: iv.setImageResource(R.mipmap.status_invisible); iv_me.setImageResource(R.mipmap.status_invisible); break; } } /** * 获取离线消息 */ private void getMessage() { OfflineMessageManager offlineManager = new OfflineMessageManager(getCon()); try { Iterator<org.jivesoftware.smack.packet.Message> it = offlineManager .getMessages(); Log.i("service", offlineManager.supportsFlexibleRetrieval() + ""); Log.i("service", "离线消息数量: " + offlineManager.getMessageCount()); Map<String, ArrayList<Message>> offlineMsgs = new HashMap<String, ArrayList<Message>>(); while (it.hasNext()) { org.jivesoftware.smack.packet.Message message = it.next(); Log.i("service", "收到离线消息, Received from 【" + message.getFrom() + "】 message: " + message.getBody()); String fromUser = message.getFrom().split("/")[0]; if (offlineMsgs.containsKey(fromUser)) { offlineMsgs.get(fromUser).add(message); } else { ArrayList<Message> temp = new ArrayList<Message>(); temp.add(message); offlineMsgs.put(fromUser, temp); } } //在这里进行处理离线消息集合...... Set<String> keys = offlineMsgs.keySet(); Iterator<String> offIt = keys.iterator(); while (offIt.hasNext()) { String key = offIt.next(); ArrayList<Message> ms = offlineMsgs.get(key); for (int i = 0; i < ms.size(); i++) { Log.i("serviceeeeeeeeeeeee", "收到离线消息, Received from 【" + ms.get(i).getFrom() + "】 message: " + ms.get(i).getBody()); } } offlineManager.deleteMessages(); } catch (Exception e) { e.printStackTrace(); } } /** * 查找用户 * * @param * @param userName * @return */ public List<XmppUser> searchUsers(String userName) { List<XmppUser> list = new ArrayList<XmppUser>(); UserSearchManager userSearchManager = new UserSearchManager(con); try { Form searchForm = userSearchManager.getSearchForm("search." + con.getServiceName()); Form answerForm = searchForm.createAnswerForm(); answerForm.setAnswer("Username", true); answerForm.setAnswer("Name", true); answerForm.setAnswer("search", userName); ReportedData data = userSearchManager.getSearchResults(answerForm, "search." + con.getServiceName()); Iterator<ReportedData.Row> rows = data.getRows(); while (rows.hasNext()) { XmppUser user = new XmppUser(null, null); ReportedData.Row row = rows.next(); user.setUserName(row.getValues("Username").next().toString()); user.setName(row.getValues("Name").next().toString()); list.add(user); } } catch (XMPPException e) { SLog.e(tag, Log.getStackTraceString(e)); } return list; } /** * 添加好友 * * @param * @param userName * @param name * @param groupName 是否有分组 * @return */ public boolean addUser(String userName, String name, String groupName) { Roster roster = con.getRoster(); try { roster.createEntry(userName, name, null == groupName ? null : new String[]{groupName}); return true; } catch (XMPPException e) { SLog.e(tag, Log.getStackTraceString(e)); } return false; } /** * 删除好友 * * @param userName * @return */ public boolean removeUser(String userName) { Roster roster = con.getRoster(); try { RosterEntry entry = roster.getEntry(userName); if (null != entry) { roster.removeEntry(entry); } return true; } catch (XMPPException e) { SLog.e(tag, Log.getStackTraceString(e)); } return false; } /** * 添加到分组 * * @param * @param userName * @param groupName */ public void addUserToGroup(String userName, String groupName) { Roster roster = con.getRoster(); RosterGroup group = roster.getGroup(groupName); if (null == group) { group = roster.createGroup(groupName); } RosterEntry entry = roster.getEntry(userName); if (entry != null) { try { group.addEntry(entry); } catch (XMPPException e) { SLog.e(tag, Log.getStackTraceString(e)); } } } /** * 获取所有分组 * * @param * @return */ public List<RosterGroup> getGroups() { Roster roster = getCon().getRoster(); List<RosterGroup> list = new ArrayList<RosterGroup>(); list.addAll(roster.getGroups()); return list; } /** * 获取某一个分组的成员 * * @param * @param groupName * @return */ public List<RosterEntry> getEntrysByGroup(String groupName) { Roster roster = getCon().getRoster(); List<RosterEntry> list = new ArrayList<RosterEntry>(); RosterGroup group = roster.getGroup(groupName); Collection<RosterEntry> rosterEntiry = group.getEntries(); Iterator<RosterEntry> iter = rosterEntiry.iterator(); while (iter.hasNext()) { RosterEntry entry = iter.next(); SLog.i("xmpptool", entry.getUser() + "\t" + entry.getName() + entry.getType().toString()); if (entry.getType().toString().equals("both")) { list.add(entry); } } return list; } /** * 判断是否是好友 * * @param * @param user * @return */ public boolean isFriendly(String user) { Roster roster = getCon().getRoster(); List<RosterEntry> list = new ArrayList<RosterEntry>(); list.addAll(roster.getEntries()); for (int i = 0; i < list.size(); i++) { Log.i("xmppttttttttt", list.get(i).getUser().toUpperCase() + "\t" + user); if (list.get(i).getUser().contains(user.toLowerCase())) { if (list.get(i).getType().toString().equals("both")) { return true; } else { return false; } } } return false; } // /** // * 注册 // * // * @return 0 服务端无响应 1成功 2已存在 3 失败 // */ // public int regist(User user) { // // Registration reg = new Registration(); // reg.setType(IQ.Type.SET); // reg.setTo(con.getServiceName()); // reg.setUsername(user.getUser()); // reg.setPassword(user.getPassword()); // reg.addAttribute("Android", "createUser"); // reg.addAttribute("name", user.getNickname()); // PacketFilter filter = new AndFilter(new PacketIDFilter(reg.getPacketID())); // PacketCollector col = con.createPacketCollector(filter); // con.sendPacket(reg); // IQ result = (IQ) col.nextResult(SmackConfiguration.getPacketReplyTimeout()); // col.cancel(); // if (null == result) { // SLog.e(tag, "no response from server"); // return 0; // } else if (result.getType() == IQ.Type.RESULT) { // SLog.e(tag, result.toString()); // // return 1; // } else if (result.getType() == IQ.Type.ERROR) { // SLog.e(tag, result.toString()); // if (result.getError().toString().equalsIgnoreCase("conflict(409)")) { // return 2; // } else { // return 3; // } // } // return 3; // } // /** // * 添加分组 // * // * @param // * @param groupName // * @return // */ // public boolean addGroup(String groupName) { // try { // Roster roster = getCon().getRoster(); // roster.createGroup(groupName); // return true; // } catch (Exception e) { // SLog.e(tag, Log.getStackTraceString(e)); // } // return false; // } /** * 断开连接 */ public static void disConnectServer() { if (null != con && con.isConnected()) { new Thread() { public void run() { con.disconnect(); } }.start(); } } public void configure(ProviderManager pm) { try { Class.forName("org.jivesoftware.smack.ReconnectionManager"); } catch (Exception e) { e.printStackTrace(); } // 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) { Log.w("TestClient", "Can't load class for org.jivesoftware.smackx.packet.Time"); } // 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()); // XHTML pm.addExtensionProvider("html", "http://jabber.org/protocol/xhtml-im", new XHTMLExtensionProvider()); // 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) { // Not sure what's happening here. } // 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()); // 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 OpenIQProvider()); pm.addIQProvider("close", "http://jabber.org/protocol/ibb", new CloseIQProvider()); pm.addExtensionProvider("data", "http://jabber.org/protocol/ibb", new DataPacketProvider()); // Privacy pm.addIQProvider("query", "jabber:iq:privacy", new PrivacyProvider()); pm.addIQProvider("command", "http://jabber.org/protocol/commands", new AdHocCommandDataProvider()); pm.addExtensionProvider("malformed-action", "http://jabber.org/protocol/commands", new AdHocCommandDataProvider.MalformedActionError()); pm.addExtensionProvider("bad-locale", "http://jabber.org/protocol/commands", new AdHocCommandDataProvider.BadLocaleError()); pm.addExtensionProvider("bad-payload", "http://jabber.org/protocol/commands", new AdHocCommandDataProvider.BadPayloadError()); pm.addExtensionProvider("bad-sessionid", "http://jabber.org/protocol/commands", new AdHocCommandDataProvider.BadSessionIDError()); pm.addExtensionProvider("session-expired", "http://jabber.org/protocol/commands", new AdHocCommandDataProvider.SessionExpiredError()); } }