功能实现:注册,登录,单聊表情,文本,图片,语音的发送接收,添加好友,删除好友,查找好友,修改密码,消息提醒设置,获取离线消息等功能
1.前期准备
1.下载opnefire软件:https://www.igniterealtime.org/downloads/index.jsp
2.下载一款数据库软件:mysql
4.在AS中添加smack相关依赖包:
compile 'org.igniterealtime.smack:smack-android-extensions:4.1.4' compile 'org.igniterealtime.smack:smack-tcp:4.1.4' compile 'org.igniterealtime.smack:smack-im:4.1.4' compile 'org.igniterealtime.smack:smack-extensions:4.1.4' compile 'com.rockerhieu.emojicon:library:1.3.3'
5.核心代码块:
XmppConnection 工具类
1 import android.content.Context; 2 import android.database.Cursor; 3 import android.os.Environment; 4 import android.text.TextUtils; 5 import android.util.Log; 6 7 import org.jivesoftware.smack.AbstractXMPPConnection; 8 import org.jivesoftware.smack.ConnectionConfiguration; 9 import org.jivesoftware.smack.MessageListener; 10 import org.jivesoftware.smack.SmackConfiguration; 11 import org.jivesoftware.smack.SmackException; 12 import org.jivesoftware.smack.XMPPException; 13 import org.jivesoftware.smack.chat.Chat; 14 import org.jivesoftware.smack.chat.ChatManager; 15 import org.jivesoftware.smack.chat.ChatMessageListener; 16 import org.jivesoftware.smack.packet.Message; 17 import org.jivesoftware.smack.packet.Presence; 18 import org.jivesoftware.smack.provider.ProviderManager; 19 import org.jivesoftware.smack.roster.Roster; 20 import org.jivesoftware.smack.roster.RosterEntry; 21 import org.jivesoftware.smack.roster.RosterGroup; 22 import org.jivesoftware.smack.tcp.XMPPTCPConnection; 23 import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration; 24 import org.jivesoftware.smackx.address.provider.MultipleAddressesProvider; 25 import org.jivesoftware.smackx.bytestreams.ibb.provider.CloseIQProvider; 26 import org.jivesoftware.smackx.bytestreams.ibb.provider.OpenIQProvider; 27 import org.jivesoftware.smackx.bytestreams.socks5.provider.BytestreamsProvider; 28 import org.jivesoftware.smackx.chatstates.packet.ChatStateExtension; 29 import org.jivesoftware.smackx.commands.provider.AdHocCommandDataProvider; 30 import org.jivesoftware.smackx.delay.provider.DelayInformationProvider; 31 import org.jivesoftware.smackx.disco.provider.DiscoverInfoProvider; 32 import org.jivesoftware.smackx.disco.provider.DiscoverItemsProvider; 33 import org.jivesoftware.smackx.filetransfer.FileTransferListener; 34 import org.jivesoftware.smackx.filetransfer.FileTransferManager; 35 import org.jivesoftware.smackx.filetransfer.FileTransferRequest; 36 import org.jivesoftware.smackx.filetransfer.IncomingFileTransfer; 37 import org.jivesoftware.smackx.filetransfer.OutgoingFileTransfer; 38 import org.jivesoftware.smackx.iqlast.packet.LastActivity; 39 import org.jivesoftware.smackx.iqprivate.PrivateDataManager; 40 import org.jivesoftware.smackx.iqregister.AccountManager; 41 import org.jivesoftware.smackx.muc.DiscussionHistory; 42 import org.jivesoftware.smackx.muc.HostedRoom; 43 import org.jivesoftware.smackx.muc.MultiUserChat; 44 import org.jivesoftware.smackx.muc.MultiUserChatManager; 45 import org.jivesoftware.smackx.muc.packet.GroupChatInvitation; 46 import org.jivesoftware.smackx.muc.provider.MUCAdminProvider; 47 import org.jivesoftware.smackx.muc.provider.MUCOwnerProvider; 48 import org.jivesoftware.smackx.muc.provider.MUCUserProvider; 49 import org.jivesoftware.smackx.offline.OfflineMessageManager; 50 import org.jivesoftware.smackx.offline.packet.OfflineMessageInfo; 51 import org.jivesoftware.smackx.offline.packet.OfflineMessageRequest; 52 import org.jivesoftware.smackx.privacy.provider.PrivacyProvider; 53 import org.jivesoftware.smackx.search.ReportedData; 54 import org.jivesoftware.smackx.search.UserSearch; 55 import org.jivesoftware.smackx.search.UserSearchManager; 56 import org.jivesoftware.smackx.sharedgroups.packet.SharedGroupsInfo; 57 import org.jivesoftware.smackx.si.provider.StreamInitiationProvider; 58 import org.jivesoftware.smackx.vcardtemp.provider.VCardProvider; 59 import org.jivesoftware.smackx.xdata.Form; 60 import org.jivesoftware.smackx.xdata.FormField; 61 import org.jivesoftware.smackx.xdata.provider.DataFormProvider; 62 import org.jivesoftware.smackx.xhtmlim.provider.XHTMLExtensionProvider; 63 64 import java.io.BufferedInputStream; 65 import java.io.BufferedReader; 66 import java.io.File; 67 import java.io.FileInputStream; 68 import java.io.IOException; 69 import java.io.InputStreamReader; 70 import java.net.URL; 71 import java.net.URLConnection; 72 import java.util.ArrayList; 73 import java.util.Collection; 74 import java.util.Date; 75 import java.util.HashMap; 76 import java.util.Iterator; 77 import java.util.List; 78 import java.util.Map; 79 import java.util.Set; 80 81 import cnpc.fcyt.fcydyy.util.LoggerUtil; 82 import cnpc.fcyt.fcydyy.xmpp.bean.XmppChat; 83 import cnpc.fcyt.fcydyy.xmpp.bean.XmppMessage; 84 import cnpc.fcyt.fcydyy.xmpp.bean.XmppUser; 85 import cnpc.fcyt.fcydyy.xmpp.dao.FriendChatDao; 86 import cnpc.fcyt.fcydyy.xmpp.dao.MessageDao; 87 import cnpc.fcyt.fcydyy.xmpp.util.TimeUtil; 88 import cnpc.fcyt.fcydyy.xmpp.util.UserConstants; 89 90 /** 91 * XmppConnection 工具类 92 */ 93 94 public class XmppConnection { 95 private int SERVER_PORT = 5222; 96 private String SERVER_HOST = "192.168.0.195"; 97 private String SERVER_NAME = "192.168.0.195"; 98 public AbstractXMPPConnection connection = null; 99 private static XmppConnection xmppConnection = new XmppConnection(); 100 private XMConnectionListener connectionListener; 101 102 /** 103 * 单例模式 104 * 105 * @return XmppConnection 106 */ 107 public synchronized static XmppConnection getInstance() { 108 configure(new ProviderManager()); 109 return xmppConnection; 110 } 111 112 /** 113 * 创建连接 114 */ 115 public AbstractXMPPConnection getConnection() { 116 117 if (connection == null) { 118 // 开线程打开连接,避免在主线程里面执行HTTP请求 119 // Caused by: android.os.NetworkOnMainThreadException 120 new Thread(new Runnable() { 121 @Override 122 public void run() { 123 openConnection(); 124 } 125 }).start(); 126 } 127 return connection; 128 } 129 130 public void setConnectionToNull() { 131 connection = null; 132 } 133 134 /** 135 * 判断是否已连接 136 */ 137 public boolean checkConnection() { 138 return null != connection && connection.isConnected(); 139 } 140 141 /** 142 * 打开连接 143 */ 144 public boolean openConnection() { 145 try { 146 if (null == connection || !connection.isAuthenticated()) { 147 SmackConfiguration.DEBUG = true; 148 XMPPTCPConnectionConfiguration.Builder config = XMPPTCPConnectionConfiguration.builder(); 149 //设置openfire主机IP 150 config.setHost(SERVER_HOST); 151 //设置openfire服务器名称 152 config.setServiceName(SERVER_NAME); 153 //设置端口号:默认5222 154 config.setPort(SERVER_PORT); 155 //禁用SSL连接 156 config.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled).setCompressionEnabled(false); 157 //设置Debug 158 config.setDebuggerEnabled(true); 159 //设置离线状态 160 config.setSendPresence(false); 161 //设置开启压缩,可以节省流量 162 config.setCompressionEnabled(true); 163 164 //需要经过同意才可以添加好友 165 Roster.setDefaultSubscriptionMode(Roster.SubscriptionMode.accept_all); 166 167 // 将相应机制隐掉 168 //SASLAuthentication.blacklistSASLMechanism("SCRAM-SHA-1"); 169 //SASLAuthentication.blacklistSASLMechanism("DIGEST-MD5"); 170 171 connection = new XMPPTCPConnection(config.build()); 172 connection.connect();// 连接到服务器 173 174 return true; 175 } 176 } catch (Exception xe) { 177 xe.printStackTrace(); 178 connection = null; 179 } 180 return false; 181 } 182 183 /** 184 * 关闭连接 185 */ 186 public void closeConnection() { 187 if (connection != null) { 188 // 移除连接监听 189 connection.removeConnectionListener(connectionListener); 190 if (connection.isConnected()) 191 connection.disconnect(); 192 connection = null; 193 } 194 195 Log.i("XmppConnection", "关闭连接"); 196 } 197 198 /** 199 * 删除好友 200 * 201 * @param 202 */ 203 public boolean deleteRosterEntry(RosterEntry rosterEntry) { 204 try { 205 Roster.getInstanceFor(connection).removeEntry(rosterEntry); 206 return true; 207 } catch (Exception e) { 208 e.printStackTrace(); 209 return false; 210 } 211 } 212 213 /** 214 * 判断连接是否通过了身份验证 215 * 即是否已登录 216 * 217 * @return 218 */ 219 public boolean isAuthenticated() { 220 return connection != null && connection.isConnected() && connection.isAuthenticated(); 221 } 222 223 /** 224 * 添加好友 无分组 225 * 226 * @param userName userName 227 * @param name name 228 * @return boolean 229 */ 230 public boolean addUser(String userName, String name) { 231 if (getConnection() == null) 232 return false; 233 try { 234 235 Roster.getInstanceFor(connection).createEntry(userName, name, null); 236 237 return true; 238 } catch (Exception e) { 239 e.printStackTrace(); 240 return false; 241 } 242 } 243 244 /** 245 * 获取账号的全部信息 246 */ 247 public void getAccountAttributes() { 248 try { 249 250 Set<String> accountAttributes = AccountManager.getInstance(connection).getAccountAttributes(); 251 Iterator<String> iterator = accountAttributes.iterator(); 252 while (iterator.hasNext()) { 253 String trim = iterator.next().toString().trim(); 254 Log.e("Account", "获取账号信息成功===" + trim); 255 } 256 } catch (SmackException.NoResponseException e) { 257 e.printStackTrace(); 258 Log.e("Account", "连接服务器失败"); 259 } catch (XMPPException.XMPPErrorException e) { 260 e.printStackTrace(); 261 Log.e("Account", "该账户已存在"); 262 } catch (SmackException.NotConnectedException e) { 263 e.printStackTrace(); 264 Log.e("Account", "服务器连接失败"); 265 } 266 } 267 268 /** 269 * 登录 270 * 271 * @param account 登录帐号 272 * @param password 登录密码 273 * @return true登录成功 274 */ 275 public boolean login(String account, String password) { 276 try { 277 if (getConnection() == null) 278 return false; 279 280 getConnection().login(account, password); 281 282 // 更改在线状态 283 // setPresence(0); 284 285 // 添加连接监听 286 connectionListener = new XMConnectionListener(account, password); 287 getConnection().addConnectionListener(connectionListener); 288 receivedFile(); 289 return true; 290 } catch (Exception xe) { 291 xe.printStackTrace(); 292 } 293 return false; 294 } 295 296 297 /** 298 * 获取用户离线在线状态 1 在线 2 离线 299 */ 300 public int getStatus(RosterEntry entry) { 301 Roster roster = Roster.getInstanceFor(connection); 302 Presence presence = roster.getPresence(entry.getUser() + UserConstants.chatDoMain); 303 304 LoggerUtil.systemOut(entry.getUser() + "用户名"); 305 LoggerUtil.systemOut(presence.getType().name() + "获取到的 类型状态"); 306 LoggerUtil.systemOut(presence.getType().toString() + "获取到的 类型状态"); 307 if (presence.getType() == Presence.Type.available) { 308 return 1;//在线 309 } 310 return 2;//离线 311 } 312 313 /** 314 * 更改用户状态 315 */ 316 public void setPresence(int code) { 317 org.jivesoftware.smack.XMPPConnection con = getConnection(); 318 if (con == null) 319 return; 320 Presence presence; 321 try { 322 switch (code) { 323 case 0: 324 presence = new Presence(Presence.Type.available); 325 con.sendStanza(presence); 326 Log.v("state", "设置在线"); 327 break; 328 case 1: 329 presence = new Presence(Presence.Type.available); 330 presence.setMode(Presence.Mode.chat); 331 con.sendStanza(presence); 332 Log.v("state", "设置Q我吧"); 333 break; 334 case 2: 335 presence = new Presence(Presence.Type.available); 336 presence.setMode(Presence.Mode.dnd); 337 con.sendStanza(presence); 338 Log.v("state", "设置忙碌"); 339 break; 340 case 3: 341 presence = new Presence(Presence.Type.available); 342 presence.setMode(Presence.Mode.away); 343 con.sendStanza(presence); 344 Log.v("state", "设置离开"); 345 break; 346 case 4: 347 // Roster roster = con.getRoster(); 348 // Collection<RosterEntry> entries = roster.getEntries(); 349 // for (RosterEntry entry : entries) { 350 // presence = new Presence(Presence.Type.unavailable); 351 // presence.setPacketID(Packet.ID_NOT_AVAILABLE); 352 // presence.setFrom(con.getUser()); 353 // presence.setTo(entry.getUser()); 354 // con.sendPacket(presence); 355 // Log.v("state", presence.toXML()); 356 // } 357 // // 向同一用户的其他客户端发送隐身状态 358 // presence = new Presence(Presence.Type.unavailable); 359 // presence.setPacketID(Packet.ID_NOT_AVAILABLE); 360 // presence.setFrom(con.getUser()); 361 // presence.setTo(StringUtils.parseBareAddress(con.getUser())); 362 // con.sendStanza(presence); 363 // Log.v("state", "设置隐身"); 364 // break; 365 case 5: 366 presence = new Presence(Presence.Type.unavailable); 367 con.sendStanza(presence); 368 Log.v("state", "设置离线"); 369 break; 370 default: 371 break; 372 } 373 } catch (Exception e) { 374 e.printStackTrace(); 375 } 376 } 377 378 /** 379 * 获取所有组 380 * 381 * @return 所有组集合 382 */ 383 public List<RosterGroup> getGroups() { 384 if (getConnection() == null) 385 return null; 386 List<RosterGroup> groupList = new ArrayList<>(); 387 Collection<RosterGroup> rosterGroup = Roster.getInstanceFor(connection).getGroups(); 388 for (RosterGroup aRosterGroup : rosterGroup) { 389 groupList.add(aRosterGroup); 390 } 391 return groupList; 392 } 393 394 /** 395 * 获取某个组里面的所有好友 396 * 397 * @param groupName 组名 398 * @return List<RosterEntry> 399 */ 400 public List<RosterEntry> getEntriesByGroup(String groupName) { 401 if (getConnection() == null) 402 return null; 403 List<RosterEntry> EntriesList = new ArrayList<>(); 404 RosterGroup rosterGroup = Roster.getInstanceFor(connection).getGroup(groupName); 405 Collection<RosterEntry> rosterEntry = rosterGroup.getEntries(); 406 for (RosterEntry aRosterEntry : rosterEntry) { 407 EntriesList.add(aRosterEntry); 408 } 409 return EntriesList; 410 } 411 412 /** 413 * 获取所有好友信息 414 * 415 * @return List<RosterEntry> 416 */ 417 public List<RosterEntry> getAllEntries() { 418 if (getConnection() == null) 419 return null; 420 List<RosterEntry> Enlist = new ArrayList<>(); 421 Collection<RosterEntry> rosterEntry = Roster.getInstanceFor(connection).getEntries(); 422 for (RosterEntry aRosterEntry : rosterEntry) { 423 Enlist.add(aRosterEntry); 424 } 425 return Enlist; 426 } 427 428 429 /** 430 * 添加一个分组 431 * 432 * @param groupName groupName 433 * @return boolean 434 */ 435 public boolean addGroup(String groupName) { 436 if (getConnection() == null) 437 return false; 438 try { 439 Roster.getInstanceFor(connection).createGroup(groupName); 440 Log.v("addGroup", groupName + "創建成功"); 441 return true; 442 } catch (Exception e) { 443 e.printStackTrace(); 444 return false; 445 } 446 } 447 448 /** 449 * 删除分组 450 * 451 * @param groupName groupName 452 * @return boolean 453 */ 454 public boolean removeGroup(String groupName) { 455 return true; 456 } 457 458 459 /** 460 * 文件转字节 461 * 462 * @param file file 463 * @return byte[] 464 * @throws IOException 465 */ 466 private byte[] getFileBytes(File file) throws IOException { 467 BufferedInputStream bis = null; 468 try { 469 bis = new BufferedInputStream(new FileInputStream(file)); 470 int bytes = (int) file.length(); 471 byte[] buffer = new byte[bytes]; 472 int readBytes = bis.read(buffer); 473 if (readBytes != buffer.length) { 474 throw new IOException("Entire file not read"); 475 } 476 return buffer; 477 } finally { 478 if (bis != null) { 479 bis.close(); 480 } 481 } 482 } 483 484 485 /** 486 * 发送群组聊天消息 487 * 488 * @param muc muc 489 * @param message 消息文本 490 */ 491 public void sendGroupMessage(MultiUserChat muc, String message) { 492 try { 493 muc.sendMessage(message); 494 } catch (Exception e) { 495 e.printStackTrace(); 496 } 497 } 498 499 500 /** 501 * 修改密码 502 * 503 * @return true成功 504 */ 505 public boolean changePassword(String pwd) { 506 if (getConnection() == null) 507 return false; 508 try { 509 AccountManager.getInstance(connection).changePassword(pwd); 510 return true; 511 } catch (Exception e) { 512 e.printStackTrace(); 513 return false; 514 } 515 } 516 517 518 519 520 /** 521 * 创建群聊聊天室 522 * 523 * @param roomName 聊天室名字 524 * @param nickName 创建者在聊天室中的昵称 525 * @param password 聊天室密码 526 * @return 527 */ 528 public MultiUserChat createChatRoom(String roomName, String nickName, String password) { 529 MultiUserChat muc; 530 try { 531 // 创建一个MultiUserChat 532 muc = MultiUserChatManager.getInstanceFor(connection).getMultiUserChat(roomName + "@conference.192.168.0.195"); 533 // 创建聊天室 534 boolean isCreated = muc.createOrJoin(nickName); 535 if (isCreated) { 536 // 获得聊天室的配置表单 537 Form form = muc.getConfigurationForm(); 538 // 根据原始表单创建一个要提交的新表单。 539 Form submitForm = form.createAnswerForm(); 540 // 向要提交的表单添加默认答复 541 List<FormField> fields = form.getFields(); 542 for (int i = 0; fields != null && i < fields.size(); i++) { 543 if (FormField.Type.hidden != fields.get(i).getType() && 544 fields.get(i).getVariable() != null) { 545 // 设置默认值作为答复 546 submitForm.setDefaultAnswer(fields.get(i).getVariable()); 547 } 548 } 549 // 设置聊天室的新拥有者 550 List owners = new ArrayList(); 551 owners.add(connection.getUser());// 用户JID 552 submitForm.setAnswer("muc#roomconfig_roomowners", owners); 553 // 设置聊天室是持久聊天室,即将要被保存下来 554 submitForm.setAnswer("muc#roomconfig_persistentroom", true); 555 // 房间仅对成员开放 556 submitForm.setAnswer("muc#roomconfig_membersonly", false); 557 // 允许占有者邀请其他人 558 submitForm.setAnswer("muc#roomconfig_allowinvites", true); 559 if (password != null && password.length() != 0) { 560 // 进入是否需要密码 561 submitForm.setAnswer("muc#roomconfig_passwordprotectedroom", true); 562 // 设置进入密码 563 submitForm.setAnswer("muc#roomconfig_roomsecret", password); 564 } 565 // 能够发现占有者真实 JID 的角色 566 // submitForm.setAnswer("muc#roomconfig_whois", "anyone"); 567 // 登录房间对话 568 submitForm.setAnswer("muc#roomconfig_enablelogging", true); 569 // 仅允许注册的昵称登录 570 submitForm.setAnswer("x-muc#roomconfig_reservednick", true); 571 // 允许使用者修改昵称 572 submitForm.setAnswer("x-muc#roomconfig_canchangenick", false); 573 // 允许用户注册房间 574 submitForm.setAnswer("x-muc#roomconfig_registration", false); 575 // 发送已完成的表单(有默认值)到服务器来配置聊天室 576 muc.sendConfigurationForm(submitForm); 577 578 } else { 579 580 } 581 } catch (XMPPException | SmackException e) { 582 e.printStackTrace(); 583 584 return null; 585 } 586 return muc; 587 } 588 /** 589 * 加入一个群聊聊天室 590 * 591 * @param jid 聊天室ip 格式为>>群组名称@conference.ip 592 * @param nickName 用户在聊天室中的昵称 593 * @param password 聊天室密码 没有密码则传"" 594 * @return 595 */ 596 public MultiUserChat join(String jid, String nickName, String password) { 597 try { 598 // 使用XMPPConnection创建一个MultiUserChat窗口 599 MultiUserChat muc = MultiUserChatManager.getInstanceFor(connection).getMultiUserChat(jid); 600 // 聊天室服务将会决定要接受的历史记录数量 601 DiscussionHistory history = new DiscussionHistory(); 602 history.setMaxChars(0); 603 // 用户加入聊天室 604 muc.join(nickName, password); 605 return muc; 606 } catch (XMPPException | SmackException e) { 607 e.printStackTrace(); 608 if ("XMPPError: not-authorized - auth".equals(e.getMessage())) { 609 //需要密码加入 610 } 611 return null; 612 } 613 } 614 /** 615 * 获取服务器上的聊天室 616 */ 617 public List<HostedRoom> getHostedRoom() { 618 MultiUserChatManager manager = MultiUserChatManager.getInstanceFor(connection); 619 try { 620 //serviceNames->conference.106.14.20.176 621 List<String> serviceNames = manager.getServiceNames(); 622 for (int i = 0; i < serviceNames.size(); i++) { 623 return manager.getHostedRooms(serviceNames.get(i)); 624 } 625 } catch (Exception e) { 626 e.printStackTrace(); 627 } 628 return null; 629 } 630 /** 631 * @param jid 格式为>>群组名称@conference.ip 632 */ 633 private void initRoomListener(String jid) { 634 MultiUserChat multiUserChat = MultiUserChatManager.getInstanceFor(connection).getMultiUserChat(jid); 635 multiUserChat.addMessageListener(new MessageListener() { 636 @Override 637 public void processMessage(final Message message) { 638 //当消息返回为空的时候,表示用户正在聊天窗口编辑信息并未发出消息 639 if (!TextUtils.isEmpty(message.getBody())) { 640 //收到的消息 641 } 642 } 643 }); 644 //发送群聊消息 645 // MultiUserChat multiUserChat = MultiUserChatManager.getInstanceFor(connection).getMultiUserChat(jid); 646 // multiUserChat.sendMessage("Hello World"); 647 648 } 649 650 // /** 651 // * 创建房间 652 // * 653 // * @param roomName 房间名称 654 // */ 655 // public MultiUserChat createRoom(String roomName, String password) { 656 // if (getConnection() == null) 657 // return null; 658 // 659 // MultiUserChat muc = null; 660 // try { 661 // // 创建一个MultiUserChat 662 // muc = MultiUserChatManager.getInstanceFor(connection).getMultiUserChat(roomName+"@conference.192.168.0.195"); 663 // // 创建聊天室 664 // muc.create(roomName); 665 // // 获得聊天室的配置表单 666 // Form form = muc.getConfigurationForm(); 667 // // 根据原始表单创建一个要提交的新表单。 668 // Form submitForm = form.createAnswerForm(); 669 // // 向要提交的表单添加默认答复 670 // for (FormField formField : form.getFields()) { 671 // if (FormField.Type.hidden == formField.getType() 672 // && formField.getVariable() != null) { 673 // // 设置默认值作为答复 674 // submitForm.setDefaultAnswer(formField.getVariable()); 675 // } 676 // } 677 // // 设置聊天室的新拥有者 678 // List<String> owners = new ArrayList<>(); 679 // owners.add(getConnection().getUser());// 用户JID 680 // submitForm.setAnswer("muc#roomconfig_roomowners", owners); 681 // // 设置聊天室是持久聊天室,即将要被保存下来 682 // submitForm.setAnswer("muc#roomconfig_persistentroom", true); 683 // // 房间仅对成员开放 684 // submitForm.setAnswer("muc#roomconfig_membersonly", false); 685 // // 允许占有者邀请其他人 686 // submitForm.setAnswer("muc#roomconfig_allowinvites", true); 687 // if (!password.equals("")) { 688 // // 进入是否需要密码 689 // submitForm.setAnswer("muc#roomconfig_passwordprotectedroom", 690 // true); 691 // // 设置进入密码 692 // submitForm.setAnswer("muc#roomconfig_roomsecret", password); 693 // } 694 // // 能够发现占有者真实 JID 的角色 695 // // submitForm.setAnswer("muc#roomconfig_whois", "anyone"); 696 // // 登录房间对话 697 // submitForm.setAnswer("muc#roomconfig_enablelogging", true); 698 // // 仅允许注册的昵称登录 699 // submitForm.setAnswer("x-muc#roomconfig_reservednick", true); 700 // // 允许使用者修改昵称 701 // submitForm.setAnswer("x-muc#roomconfig_canchangenick", false); 702 // // 允许用户注册房间 703 // submitForm.setAnswer("x-muc#roomconfig_registration", false); 704 // // 发送已完成的表单(有默认值)到服务器来配置聊天室 705 // muc.sendConfigurationForm(submitForm); 706 // } catch (Exception e) { 707 // e.printStackTrace(); 708 // LoggerUtil.systemOut(e.toString()); 709 // return null; 710 // } 711 // return muc; 712 // } 713 714 /** 715 * 加入会议室 716 * 717 * @param user 昵称 718 * @param roomsName 会议室名 719 */ 720 public MultiUserChat joinMultiUserChat(String user, String roomsName) { 721 if (getConnection() == null) 722 return null; 723 try { 724 // 使用XMPPConnection创建一个MultiUserChat窗口 725 MultiUserChat muc = MultiUserChatManager.getInstanceFor(connection).getMultiUserChat(connection.getServiceName()); 726 727 // 用户加入聊天室 728 muc.join(user); 729 730 Log.i("MultiUserChat", "会议室【" + roomsName + "】加入成功........"); 731 return muc; 732 } catch (Exception e) { 733 e.printStackTrace(); 734 Log.i("MultiUserChat", "会议室【" + roomsName + "】加入失败........"); 735 return null; 736 } 737 } 738 739 740 741 742 /** 743 * 判断是否是好友 744 * 745 * @param 746 * @param user 747 * @return 748 */ 749 public boolean isMyFriend(String user) { 750 751 List<RosterEntry> allEntries = XmppConnection.getInstance().getAllEntries(); 752 for (int i = 0; i < allEntries.size(); i++) { 753 LoggerUtil.systemOut("allEntries.get(i).getUser() == " + allEntries.get(i).getUser()); 754 LoggerUtil.systemOut("user == " + user); 755 if (allEntries.get(i).getUser().equals(user)) { 756 LoggerUtil.systemOut(allEntries.get(i).getType().toString() + "type"); 757 if (allEntries.get(i).getType().toString().equals("both")) { 758 return true; 759 } else { 760 return false; 761 } 762 } 763 } 764 return false; 765 766 } 767 /** 768 * 查询会议室成员名字 769 * 770 * @param muc 771 */ 772 public List<String> findMulitUser(MultiUserChat muc) { 773 if (getConnection() == null) 774 return null; 775 List<String> listUser = new ArrayList<>(); 776 List<String> occupants = muc.getOccupants(); 777 // 遍历出聊天室人员名称 778 for (String entityFullJid : occupants) { 779 // 聊天室成员名字 780 String name = entityFullJid; 781 listUser.add(name); 782 } 783 return listUser; 784 } 785 786 787 /** 788 * 判断OpenFire用户的状态 strUrl : 789 * url格式 - http://my.openfire.com:9090/plugins/presence 790 * /status?jid=user1@SERVER_NAME&type=xml 791 * 返回值 : 0 - 用户不存在; 1 - 用户在线; 2 - 用户离线 792 * 说明 :必须要求 OpenFire加载 presence 插件,同时设置任何人都可以访问 793 */ 794 public int IsUserOnLine(String user) { 795 String url = "http://" + SERVER_HOST + ":9090/plugins/presence/status?" + 796 "jid=" + user; 797 int shOnLineState = 0; // 不存在 798 try { 799 URL oUrl = new URL(url); 800 URLConnection oConn = oUrl.openConnection(); 801 if (oConn != null) { 802 BufferedReader oIn = new BufferedReader(new InputStreamReader( 803 oConn.getInputStream())); 804 String strFlag = oIn.readLine(); 805 oIn.close(); 806 System.out.println("strFlag" + strFlag); 807 if (strFlag.contains("type=\"unavailable\"")) { 808 shOnLineState = 2; 809 } 810 if (strFlag.contains("type=\"error\"")) { 811 shOnLineState = 0; 812 } else if (strFlag.contains("priority") || strFlag.contains("id=\"")) { 813 shOnLineState = 1; 814 } 815 } 816 } catch (Exception e) { 817 e.printStackTrace(); 818 } 819 820 return shOnLineState; 821 } 822 823 /** 824 * 创建聊天窗口 825 * 826 * @param JID JID 827 * @return Chat 828 */ 829 public Chat getFriendChat(String JID, ChatMessageListener listener) { 830 try { 831 return ChatManager.getInstanceFor(XmppConnection.getInstance().getConnection()) 832 .createChat(JID, listener); 833 } catch (Exception e) { 834 e.printStackTrace(); 835 } 836 return null; 837 } 838 839 /** 840 * 发送单人聊天消息 841 * 842 * @param chat chat 843 * @param message 消息文本 844 */ 845 public void sendSingleMessage(Chat chat, String message) { 846 try { 847 chat.sendMessage(message); 848 } catch (SmackException.NotConnectedException e) { 849 e.printStackTrace(); 850 } 851 } 852 853 /** 854 * 发消息 855 * 856 * @param chat chat 857 * @param muc muc 858 * @param message message 859 */ 860 public void sendMessage(Chat chat, MultiUserChat muc, String message) { 861 if (chat != null) { 862 sendSingleMessage(chat, message); 863 } else if (muc != null) { 864 sendGroupMessage(muc, message); 865 } 866 } 867 868 869 /** 870 * 获取离线消息 871 * 872 * @return 873 */ 874 int i = 0; 875 876 public void getHisMessage(Context context) { 877 LoggerUtil.systemOut("访问次数 " + (i++)); 878 setPresence(5); 879 if (getConnection() == null) 880 return; 881 882 try { 883 OfflineMessageManager offlineManager = new OfflineMessageManager(getConnection()); 884 List<Message> messageList = offlineManager.getMessages(); 885 int count = offlineManager.getMessageCount(); 886 LoggerUtil.systemOut("离线消息个数" + count); 887 if (count <= 0) { 888 setPresence(0); 889 return; 890 } 891 for (Message message : messageList) { 892 String[] send = message.getFrom().split("@");// 发送方 893 String[] receiver = message.getTo().split("@");// 接收方 894 saveofflineMessage(context, receiver[0], send[0], send[0], message.getBody(), "chat"); 895 saveofflineChatData(context, receiver[0], send[0], send[0], message.getBody()); 896 897 } 898 offlineManager.deleteMessages(); 899 } catch (Exception e) { 900 e.printStackTrace(); 901 } 902 setPresence(0); 903 } 904 905 public boolean saveofflineMessage(Context context, String main, final String users, final String to, final String content, String type) { 906 907 Cursor cursor = MessageDao.getInstance(context).queryIshasResult(context, main, type); 908 909 if (cursor != null) { 910 //更新 911 if (type.equals("add")) { 912 int result = cursor.getInt(cursor.getColumnIndex("result")); 913 if (result == 0) { 914 int id = cursor.getInt(cursor.getColumnIndex("id")); 915 MessageDao.getInstance(context).update(context, id, content, 1); 916 return true; 917 } else { 918 return false; 919 } 920 } else { 921 int id = cursor.getInt(cursor.getColumnIndex("id")); 922 MessageDao.getInstance(context).update(context, id, content, 1); 923 return true; 924 } 925 926 } else { 927 //插入 928 List<XmppUser> list1 = XmppConnection.getInstance().searchUsers(users); 929 XmppMessage xm = new XmppMessage(to, 930 type, 931 new XmppUser(list1.get(0).getUserName(), list1.get(0).getName()), 932 TimeUtil.getDate(), 933 content, 934 1, 935 main 936 ); 937 LoggerUtil.systemOut("to" + to); 938 MessageDao.getInstance(context).inserts(context, xm); 939 940 return true; 941 } 942 943 944 } 945 946 public void saveofflineChatData(Context context, String main, final String users, final String to, final String content) { 947 XmppChat xc = new XmppChat(main, users, "", "", 2, content, to, 1, new Date().getTime()); 948 FriendChatDao.getInstance(context).insert(context, xc); 949 } 950 951 /** 952 * 注册 953 * 954 * @param account 注册帐号 955 * @param password 注册密码 956 * @return 1、注册成功 0、注册失败 957 */ 958 public boolean register(String account, String password, String nickName) { 959 if (getConnection() == null) 960 return false; 961 try { 962 // new 963 Map<String, String> attributes = new HashMap<>(); 964 attributes.put("name", nickName); 965 AccountManager.getInstance(connection).createAccount(account, password, attributes); 966 967 } catch (XMPPException | SmackException e) { 968 e.printStackTrace(); 969 return false; 970 } 971 972 return true; 973 } 974 975 976 /** 977 * 设置昵称 978 * 979 * @param 980 * @param rosterEntry 981 * @return 982 */ 983 public boolean setNickName(RosterEntry rosterEntry, String nickName) { 984 try { 985 rosterEntry.setName(nickName); 986 return true; 987 } catch (SmackException.NotConnectedException e) { 988 e.printStackTrace(); 989 return false; 990 } catch (SmackException.NoResponseException e) { 991 e.printStackTrace(); 992 return false; 993 } catch (XMPPException.XMPPErrorException e) { 994 e.printStackTrace(); 995 return false; 996 } 997 } 998 999 private OutgoingFileTransfer fileTransfer; 1000 1001 // 发送文件 1002 public void sendFile(String user, File file) throws Exception { 1003 1004 FileTransferManager instanceFor = FileTransferManager.getInstanceFor(connection); 1005 1006 fileTransfer = instanceFor.createOutgoingFileTransfer(user); 1007 fileTransfer.sendFile(file, "send file"); 1008 1009 System.out.println("发送成功" + user + file.exists() + "文件路径" + file.getPath()); 1010 } 1011 1012 /* 1013 * 语音接收文件监听接收文件 1014 * 1015 * @author Administrator 1016 * 1017 */ 1018 private FileTransferListener mfiletransfransferlistener;//接受语音文件监听 1019 1020 public void receivedFile() { 1021 1022 // Create the file transfer manager 1023 1024 FileTransferManager manager = FileTransferManager.getInstanceFor(connection); 1025 mfiletransfransferlistener = new FileTransferListener() { 1026 public void fileTransferRequest(FileTransferRequest request) { 1027 // Check to see if the request should be accepted 1028 1029 LoggerUtil.systemOut("有文件接收了" + request.toString()); 1030 // Accept it 1031 IncomingFileTransfer transfer = request.accept(); 1032 try { 1033 1034 File filePath = new File(Environment.getExternalStorageDirectory(), "fcyt"); 1035 1036 if (!filePath.exists()) { 1037 filePath.mkdirs(); 1038 } 1039 // File file = new File( Environment 1040 // .getExternalStorageDirectory()+"/fcyt/" 1041 // +"/"+ request.getFileName()); 1042 1043 1044 String streamID = request.getStreamID(); 1045 1046 LoggerUtil.systemOut("streamID", streamID); 1047 File file = new File(filePath, request.getFileName()); 1048 System.out.println(request.getFileName() + "接收路径" + file.getPath() + "接收语音文件名称" + file.exists()); 1049 1050 transfer.recieveFile(file); 1051 1052 } catch (Exception e) { 1053 e.printStackTrace(); 1054 } 1055 1056 } 1057 }; 1058 1059 1060 manager.addFileTransferListener(mfiletransfransferlistener); 1061 1062 } 1063 1064 /** 1065 * 查找用户 1066 * 1067 * @param 1068 * @param userName 1069 * @return 1070 */ 1071 public List<XmppUser> searchUsers(String userName) { 1072 List<XmppUser> list = new ArrayList<XmppUser>(); 1073 UserSearchManager userSearchManager = new UserSearchManager(connection); 1074 try { 1075 Form searchForm = userSearchManager.getSearchForm("search." 1076 + connection.getServiceName()); 1077 Form answerForm = searchForm.createAnswerForm(); 1078 answerForm.setAnswer("Username", true); 1079 answerForm.setAnswer("Name", true); 1080 answerForm.setAnswer("search", userName); 1081 ReportedData data = userSearchManager.getSearchResults(answerForm, "search." + connection.getServiceName()); 1082 List<ReportedData.Row> rows = data.getRows(); 1083 for (ReportedData.Row row : rows) { 1084 XmppUser user = new XmppUser(null, null); 1085 user.setUserName(row.getValues("Username").toString().replace("]", "").replace("[", "")); 1086 user.setName(row.getValues("Name").toString().replace("]", "").replace("[", "")); 1087 list.add(user); 1088 } 1089 1090 } catch (Exception e) { 1091 1092 } 1093 return list; 1094 } 1095 1096 public static void configure(ProviderManager pm) { 1097 1098 try { 1099 Class.forName("org.jivesoftware.smack.ReconnectionManager"); 1100 } catch (Exception e) { 1101 e.printStackTrace(); 1102 } 1103 1104 // Private Data Storage 1105 pm.addIQProvider("query", "jabber:iq:private", new PrivateDataManager.PrivateDataIQProvider()); 1106 1107 // Time 1108 try { 1109 pm.addIQProvider("query", "jabber:iq:time", Class.forName("org.jivesoftware.smackx.packet.Time")); 1110 } catch (ClassNotFoundException e) { 1111 Log.w("TestClient", "Can't load class for org.jivesoftware.smackx.packet.Time"); 1112 } 1113 1114 // // Roster Exchange 1115 // pm.addExtensionProvider("x", "jabber:x:roster", new RosterLoadedListener() { 1116 // }); 1117 // 1118 // // Message Events 1119 // pm.addExtensionProvider("x", "jabber:x:event", new MessageEventProvider()); 1120 1121 // Chat State 1122 pm.addExtensionProvider("active", "http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider()); 1123 pm.addExtensionProvider("composing", "http://jabber.org/protocol/chatstates", 1124 new ChatStateExtension.Provider()); 1125 pm.addExtensionProvider("paused", "http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider()); 1126 pm.addExtensionProvider("inactive", "http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider()); 1127 pm.addExtensionProvider("gone", "http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider()); 1128 1129 // XHTML 1130 pm.addExtensionProvider("html", "http://jabber.org/protocol/xhtml-im", new XHTMLExtensionProvider()); 1131 1132 // Group Chat Invitations 1133 pm.addExtensionProvider("x", "jabber:x:conference", new GroupChatInvitation.Provider()); 1134 1135 // Service Discovery # Items 1136 pm.addIQProvider("query", "http://jabber.org/protocol/disco#items", new DiscoverItemsProvider()); 1137 1138 // Service Discovery # Info 1139 pm.addIQProvider("query", "http://jabber.org/protocol/disco#info", new DiscoverInfoProvider()); 1140 1141 // Data Forms 1142 pm.addExtensionProvider("x", "jabber:x:data", new DataFormProvider()); 1143 1144 // MUC User 1145 pm.addExtensionProvider("x", "http://jabber.org/protocol/muc#user", new MUCUserProvider()); 1146 1147 // MUC Admin 1148 pm.addIQProvider("query", "http://jabber.org/protocol/muc#admin", new MUCAdminProvider()); 1149 1150 // MUC Owner 1151 pm.addIQProvider("query", "http://jabber.org/protocol/muc#owner", new MUCOwnerProvider()); 1152 1153 // Delayed Delivery 1154 pm.addExtensionProvider("x", "jabber:x:delay", new DelayInformationProvider()); 1155 1156 // Version 1157 try { 1158 pm.addIQProvider("query", "jabber:iq:version", Class.forName("org.jivesoftware.smackx.packet.Version")); 1159 } catch (ClassNotFoundException e) { 1160 // Not sure what's happening here. 1161 } 1162 1163 // VCard 1164 pm.addIQProvider("vCard", "vcard-temp", new VCardProvider()); 1165 1166 // Offline Message Requests 1167 pm.addIQProvider("offline", "http://jabber.org/protocol/offline", new OfflineMessageRequest.Provider()); 1168 1169 // Offline Message Indicator 1170 pm.addExtensionProvider("offline", "http://jabber.org/protocol/offline", new OfflineMessageInfo.Provider()); 1171 1172 // Last Activity 1173 pm.addIQProvider("query", "jabber:iq:last", new LastActivity.Provider()); 1174 1175 // User Search 1176 pm.addIQProvider("query", "jabber:iq:search", new UserSearch.Provider()); 1177 1178 // SharedGroupsInfo 1179 pm.addIQProvider("sharedgroup", "http://www.jivesoftware.org/protocol/sharedgroup", 1180 new SharedGroupsInfo.Provider()); 1181 1182 // JEP-33: Extended Stanza Addressing 1183 pm.addExtensionProvider("addresses", "http://jabber.org/protocol/address", new MultipleAddressesProvider()); 1184 1185 // FileTransfer 1186 pm.addIQProvider("si", "http://jabber.org/protocol/si", new StreamInitiationProvider()); 1187 pm.addIQProvider("query", "http://jabber.org/protocol/bytestreams", new BytestreamsProvider()); 1188 pm.addIQProvider("open", "http://jabber.org/protocol/ibb", new OpenIQProvider()); 1189 pm.addIQProvider("close", "http://jabber.org/protocol/ibb", new CloseIQProvider()); 1190 // pm.addExtensionProvider("data", "http://jabber.org/protocol/ibb", new DataPacketProvider()); 1191 1192 // Privacy 1193 pm.addIQProvider("query", "jabber:iq:privacy", new PrivacyProvider()); 1194 pm.addIQProvider("command", "http://jabber.org/protocol/commands", new AdHocCommandDataProvider()); 1195 pm.addExtensionProvider("malformed-action", "http://jabber.org/protocol/commands", 1196 new AdHocCommandDataProvider.MalformedActionError()); 1197 pm.addExtensionProvider("bad-locale", "http://jabber.org/protocol/commands", 1198 new AdHocCommandDataProvider.BadLocaleError()); 1199 pm.addExtensionProvider("bad-payload", "http://jabber.org/protocol/commands", 1200 new AdHocCommandDataProvider.BadPayloadError()); 1201 pm.addExtensionProvider("bad-sessionid", "http://jabber.org/protocol/commands", 1202 new AdHocCommandDataProvider.BadSessionIDError()); 1203 pm.addExtensionProvider("session-expired", "http://jabber.org/protocol/commands", 1204 new AdHocCommandDataProvider.SessionExpiredError()); 1205 } 1206 1207 1208 }
XmppService后台监听接收消息
import android.app.Service; import android.content.ContentResolver; import android.content.Intent; import android.database.Cursor; import android.media.AudioManager; import android.media.SoundPool; import android.os.Handler; import android.os.IBinder; import android.os.Vibrator; import android.util.Log; import org.greenrobot.eventbus.EventBus; import org.jivesoftware.smack.AbstractXMPPConnection; import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.StanzaListener; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Presence; import org.jivesoftware.smack.packet.Stanza; import java.util.Date; import java.util.HashMap; import java.util.List; import cnpc.fcyt.fcydyy.R; import cnpc.fcyt.fcydyy.constant.ConfigConstants; import cnpc.fcyt.fcydyy.event.LogoutEvent; import cnpc.fcyt.fcydyy.event.RefreshChatMessageEvent; import cnpc.fcyt.fcydyy.event.RefreshRedDotEvent; import cnpc.fcyt.fcydyy.util.LoggerUtil; import cnpc.fcyt.fcydyy.xmpp.bean.XmppChat; import cnpc.fcyt.fcydyy.xmpp.bean.XmppMessage; import cnpc.fcyt.fcydyy.xmpp.bean.XmppUser; import cnpc.fcyt.fcydyy.xmpp.dao.FriendChatDao; import cnpc.fcyt.fcydyy.xmpp.dao.MessageDao; import cnpc.fcyt.fcydyy.xmpp.util.SaveUserUtil; import cnpc.fcyt.fcydyy.xmpp.util.TimeUtil; import cnpc.fcyt.fcydyy.xmpp.util.UserConstants; public class XmppService extends Service { private XMPPConnection con; public static ContentResolver resolver; public static HashMap<String, Object> map; String send[];//发送方 String receiver[];//接收方 public static String user; public static SoundPool pool; public static Vibrator vibrator; Handler handler = new Handler() { @Override public void handleMessage(android.os.Message msg) { super.handleMessage(msg); if (msg.what == 1) { boolean authenticated = XmppConnection.getInstance().isAuthenticated(); AbstractXMPPConnection connection = XmppConnection.getInstance().getConnection(); if (connection!=null){ boolean connected = connection.isConnected(); if (!connected){ LoggerUtil.systemOut("IM服务器无法连接"); XmppConnection.getInstance().setConnectionToNull(); EventBus.getDefault().post(new LogoutEvent()); }else { if (!authenticated) { LoggerUtil.systemOut("掉线了"); EventBus.getDefault().post(new LogoutEvent()); }else { LoggerUtil.systemOut("连接ing"); } } } handler.sendEmptyMessageDelayed(1, 3000); } } }; @Override public void onCreate() { // TODO Auto-generated method stub super.onCreate(); resolver = getContentResolver(); map = new HashMap<>(); con = XmppConnection.getInstance().getConnection(); user = SaveUserUtil.loadAccount(XmppService.this).getUser(); pool = new SoundPool(10, AudioManager.STREAM_SYSTEM, 5); pool.load(this, R.raw.tishi, 1); vibrator = (Vibrator) getSystemService(Service.VIBRATOR_SERVICE); LoggerUtil.systemOut("启动服务......"); handler.sendEmptyMessageDelayed(1, 3000); } @Override public IBinder onBind(Intent intent) { return null; } String messageID = ""; @Override public int onStartCommand(Intent intent, int flags, int startId) {//'zS4Xw-62 if (null != con && con.isConnected()) { con.addAsyncStanzaListener(new StanzaListener() { @Override public void processPacket(Stanza packet) throws SmackException.NotConnectedException { String stanzaId = packet.getStanzaId(); LoggerUtil.systemOut(stanzaId + "消息ID"); LoggerUtil.systemOut("messageID" + messageID); if (messageID.equals(stanzaId) || stanzaId == null) { } else { if (stanzaId != null) { messageID = stanzaId; } LoggerUtil.systemOut(packet.toString() + "通知来了"); if (packet instanceof Presence) { Presence presence = (Presence) packet; send = presence.getFrom().split("@");// 发送方 receiver = presence.getTo().split("@");// 接收方 // Presence.Type有7中状态 LoggerUtil.systemOut(presence.getType() + "信息类型"); if (presence.getType().equals(Presence.Type.subscribe)) {// 好友申请 LoggerUtil.systemOut(send[0] + "\t好友申请加为好友\t type=" + presence.getType().toString()); sendBroad("add"); } else if (presence.getType().equals(Presence.Type.subscribed)) {// 同意添加好友 LoggerUtil.systemOut(send[0] + "\t同意添加好友\t type=" + presence.getType().toString()); sendBroad("tongyi"); } else if (presence.getType().equals(Presence.Type.unsubscribe)) {// 删除好友 LoggerUtil.systemOut(send[0] + "\t删除好友\t type=" + presence.getType().toString()); } else if (presence.getType().equals(Presence.Type.unsubscribed)) {// 拒绝对放的添加请求 LoggerUtil.systemOut(send[0] + "\t拒绝添加好友\t type=" + presence.getType().toString()); sendBroad("jujue"); } else if (presence.getType().equals(Presence.Type.unavailable)) {// 好友下线 Log.i("service", send[0] + "\t 下线了"); LoggerUtil.systemOut(send[0] + "\t下线了\t type=" + presence.getType().toString()); sendBroad("status", 6); } else if (presence.getType().equals(Presence.Type.available)) {// 好友上线 //0.在线 1.Q我吧 2.忙碌 3.勿扰 4.离开 5.隐身 6.离线 if (presence.getMode() == Presence.Mode.chat) {//Q我吧 Log.i("service", send[0] + "\t 的状态改为了 Q我吧"); sendBroad("status", 1); } else if (presence.getMode() == Presence.Mode.dnd) {//忙碌 Log.i("service", send[0] + "\t 的状态改为了 忙碌了"); sendBroad("status", 2); } else if (presence.getMode() == Presence.Mode.xa) {//忙碌 Log.i("service", send[0] + "\t 的状态改为了 勿扰了"); sendBroad("status", 3); } else if (presence.getMode() == Presence.Mode.away) {//离开 Log.i("service", send[0] + "\t 的状态改为了 离开了"); sendBroad("status", 4); } else { Log.i("service", send[0] + "\t 的状态改为了 上线了"); sendBroad("status", 0); } } } else if (packet instanceof Message) { Message msg = (Message) packet; EventBus.getDefault().post(new RefreshRedDotEvent()); int viewType; if (msg.getBody() != null) { if (msg.getBody().length() > 3 && msg.getBody().toString().substring(0, 4).equals("http")) { viewType = 2; } else { viewType = 1; } XmppChat xc = new XmppChat(UserConstants.loginuser, packet.getFrom().replace(UserConstants.chatDoMain, ""), "", "", 2,
msg.getBody().toString(), packet.getFrom().replace(UserConstants.chatDoMain, ""), viewType, new Date().getTime()); FriendChatDao.getInstance(XmppService.this).insert(XmppService.this, xc); sendBroad("chat", xc); } } } } }, null); } return super.onStartCommand(intent, flags, startId); } private void sendBroad(String type, XmppChat xc) { Intent intent; intent = new Intent("xmpp_receiver"); intent.putExtra("type", type); intent.putExtra("chat", xc); sendBroadcast(intent); } private void sendBroad(String type, int status) { map.put(send[0], status); Intent intent; intent = new Intent("xmpp_receiver"); intent.putExtra("type", type); sendBroadcast(intent); } private void sendBroad(String type) { String str_content = ""; String str_type = ""; switch (type) { case "add": str_content = "请求加为好友"; str_type = "add"; break; case "tongyi": str_content = "同意添加好友"; str_type = "tongyi"; break; case "jujue": str_content = "拒绝添加好友"; str_type = "jujue"; break; } LoggerUtil.systemOut(send[0] + "发送人"); LoggerUtil.systemOut(receiver[0] + "接收人"); if (msgDatas(receiver[0], send[0], send[0], str_content, str_type)) { if (pool != null && ConfigConstants.getSound(this)) { pool.play(1, 1, 1, 0, 0, 1); } if (vibrator != null && ConfigConstants.getShake(this)) { vibrator.vibrate(500); } Intent intent; intent = new Intent("xmpp_receiver"); intent.putExtra("type", type); sendBroadcast(intent); } } public boolean msgDatas(final String main, final String users, final String to, final String content, String type) { Cursor cursor = MessageDao.getInstance(this).queryIshasResult(this, main, type); if (cursor != null) { //更新 if (type.equals("add")) { int result = cursor.getInt(cursor.getColumnIndex("result")); if (result == 0) { int id = cursor.getInt(cursor.getColumnIndex("id")); MessageDao.getInstance(this).update(this, id, content, 1); //刷新聊天页面 EventBus.getDefault().post(new RefreshChatMessageEvent()); return true; } else { return false; } } else { int id = cursor.getInt(cursor.getColumnIndex("id")); MessageDao.getInstance(this).update(this, id, content, 1); //刷新聊天页面 EventBus.getDefault().post(new RefreshChatMessageEvent()); return true; } } else { //插入 List<XmppUser> list1 = XmppConnection.getInstance().searchUsers(users); XmppMessage xm = new XmppMessage(to, type, new XmppUser(list1.get(0).getUserName(), list1.get(0).getName()), TimeUtil.getDate(), content, 1, main ); LoggerUtil.systemOut("to" + to); MessageDao.getInstance(this).inserts(this, xm); //刷新聊天页面 EventBus.getDefault().post(new RefreshChatMessageEvent()); return true; } } }
XmppReceiver消息广播处理消息
import android.annotation.TargetApi; import android.app.ActivityManager; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.os.Build; import android.support.v4.app.NotificationCompat; import org.greenrobot.eventbus.EventBus; import java.util.List; import cnpc.fcyt.fcydyy.R; import cnpc.fcyt.fcydyy.constant.ConfigConstants; import cnpc.fcyt.fcydyy.event.RefreshChatMessageEvent; import cnpc.fcyt.fcydyy.util.LoggerUtil; import cnpc.fcyt.fcydyy.xmpp.bean.XmppChat; import cnpc.fcyt.fcydyy.xmpp.bean.XmppMessage; import cnpc.fcyt.fcydyy.xmpp.bean.XmppUser; import cnpc.fcyt.fcydyy.xmpp.dao.MessageDao; import cnpc.fcyt.fcydyy.xmpp.util.TimeUtil; public class XmppReceiver extends BroadcastReceiver { updateActivity ua = null; public NotificationManager manager = null; Context context; public XmppReceiver(updateActivity ua) { this.ua = ua; } @TargetApi(Build.VERSION_CODES.JELLY_BEAN) @Override public void onReceive(Context context, Intent intent) { this.context = context; String type = intent.getStringExtra("type"); if (type.equals("chat")) { LoggerUtil.systemOut("有新的接收消息"); XmppChat xc = (XmppChat) intent.getSerializableExtra("chat"); if (ChatActivity.ca != null) { LoggerUtil.systemOut(ChatActivity.ca.user + "当前聊天用户"); LoggerUtil.systemOut(xc.getUser() + "新信息的用户"); LoggerUtil.systemOut(xc.getToo() + "当前聊天用户too"); if ((ChatActivity.ca.user).equals(xc.getToo())) { ua.update(xc); } chatDatas(xc.getMain(), xc.getUser(), xc.getToo(), xc.getContent()); } else { int num = chatData(xc.getMain(), xc.getUser(), xc.getToo(), xc.getContent()); if (XmppService.vibrator != null && ConfigConstants.getShake(context)) { XmppService.vibrator.vibrate(500); } if (!isAppOnForeground(context)) { //在message界面更新信息 if (manager == null) { manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); } Intent intent1 = new Intent(context, ChatActivity.class); intent1.putExtra("user", xc.getUser()); PendingIntent pi = PendingIntent.getActivity(context, 0, intent1, PendingIntent.FLAG_UPDATE_CURRENT); List<XmppUser> xmppUsers = XmppConnection.getInstance().searchUsers(xc.getUser()); Notification notify = new Notification.Builder(context) .setAutoCancel(true) .setTicker("有新消息") .setSmallIcon(R.mipmap.ic_launcher) .setContentTitle("来自" + xmppUsers.get(0).getName() + "的消息") .setContentText(xc.getContent()) .setDefaults(NotificationCompat.FLAG_ONLY_ALERT_ONCE) .setWhen(System.currentTimeMillis()) .setNumber(num) .setContentIntent(pi).build(); manager.notify(0, notify); } else { if (XmppService.pool != null && ConfigConstants.getSound(context)) { XmppService.pool.play(1, 1, 1, 0, 0, 1); } } } } ua.update(type); } public interface updateActivity { public void update(String type); public void update(XmppChat xc); } public int chatData(final String main, final String users, final String to, final String content) { Cursor cursor = MessageDao.getInstance(context).queryIshasResult(context, main, "chat"); if (cursor != null) { //更新 int id = cursor.getInt(cursor.getColumnIndex("id")); int result = cursor.getInt(cursor.getColumnIndex("result")); MessageDao.getInstance(context).update(context, id, content, result + 1); //刷新聊天页面 EventBus.getDefault().post(new RefreshChatMessageEvent()); return (result + 1); } else { //插入 List<XmppUser> list1 = XmppConnection.getInstance().searchUsers(users); XmppMessage xm = new XmppMessage(to, "chat", new XmppUser(list1.get(0).getUserName(), list1.get(0).getName()), TimeUtil.getDate(), content, 1, main ); LoggerUtil.systemOut("to3" + to); MessageDao.getInstance(context).inserts(context, xm); //刷新聊天页面 EventBus.getDefault().post(new RefreshChatMessageEvent()); return 1; } } public void chatDatas(final String main, final String users, final String to, final String content) { int id = MessageDao.getInstance(context).queryIshas(context, main, "chat"); if (id != -1) { //更新 MessageDao.getInstance(context).update(context, id, content, 0); } else { //插入 List<XmppUser> list1 = XmppConnection.getInstance().searchUsers(users); XmppMessage xm = new XmppMessage(to, "chat", new XmppUser(list1.get(0).getUserName(), list1.get(0).getName()), TimeUtil.getDate(), content, 0, main ); LoggerUtil.systemOut("to1" + to); MessageDao.getInstance(context).inserts(context, xm); } //刷新聊天页面 EventBus.getDefault().post(new RefreshChatMessageEvent()); } public boolean isAppOnForeground(Context context) { // Returns a list of application processes that are running on the // device ActivityManager activityManager = (ActivityManager) context.getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE); String packageName = context.getApplicationContext().getPackageName(); List<ActivityManager.RunningAppProcessInfo> appProcesses = activityManager .getRunningAppProcesses(); if (appProcesses == null) return false; for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) { // The name of the process that this object is associated with. if (appProcess.processName.equals(packageName) && appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) { return true; } } return false; } }
本地数据库建立,用于储存历史消息记录等
import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import java.util.ArrayList; import cnpc.fcyt.fcydyy.util.LoggerUtil; import cnpc.fcyt.fcydyy.xmpp.bean.XmppChat; public class FriendChatDao { private static FriendChatDao mInstance; public Context context; private FriendChatDao(Context ctx) { this.context = ctx; } public static FriendChatDao getInstance(Context ctx) { //懒汉: 考虑线程安全问题, 两种方式: 1. 给方法加同步锁 synchronized, 效率低; 2. 给创建对象的代码块加同步锁 //读数据不会出现线程安全问题, 写数据会出现线程安全问题 //a, B, C if (mInstance == null) { //B, C synchronized (FriendChatDao.class) { //a if (mInstance == null) { mInstance = new FriendChatDao(ctx); } } } return mInstance; } public boolean insert(Context context, XmppChat xc) { boolean isSucceed = false; // 1. 在内存中创建数据库帮助类的对象 FriendChatOpenHelper helper = new FriendChatOpenHelper(context); // 2. 在磁盘上创建数据库文件 SQLiteDatabase db = helper.getWritableDatabase(); /** * table :表名 * nullColumnHack: */ ContentValues values = new ContentValues(); values.put("main", xc.getMain()); values.put("user", xc.getUser()); values.put("nickname", xc.getNickname()); values.put("icon", xc.getIcon()); values.put("type", xc.getType()); values.put("content", xc.getContent()); values.put("too", xc.getToo()); values.put("viewtype", xc.getViewType()); values.put("time", xc.getTime()); long id = db.insert("chat", null, values); if (id == -1) { LoggerUtil.systemOut("插入失败"); isSucceed = false; } else { LoggerUtil.systemOut("插入成功"); isSucceed = true; } // 释放资源 db.close(); return isSucceed; } public ArrayList<XmppChat> query(Context context, String main, String too) { // 1. 在内存中创建数据库帮助类的对象 FriendChatOpenHelper helper = new FriendChatOpenHelper(context); // 2. 在磁盘上创建数据库文件 SQLiteDatabase database = helper.getWritableDatabase(); Cursor cursor = database.query("chat", null, "too=?", new String[]{too}, null, null, null); ArrayList<XmppChat> list = new ArrayList<>(); if (cursor != null) { LoggerUtil.systemOut("查询个数 " + cursor.getCount()); while (cursor.moveToNext()) { String user = cursor.getString(cursor.getColumnIndex("user")); String nickname = cursor.getString(cursor.getColumnIndex("nickname")); String icon = cursor.getString(cursor.getColumnIndex("icon")); int type = cursor.getInt(cursor.getColumnIndex("type")); String content = cursor.getString(cursor.getColumnIndex("content")); String times = cursor.getString(cursor.getColumnIndex("time")); long time = Long.parseLong(times); int viewType = cursor.getInt(cursor.getColumnIndex("viewtype")); XmppChat xmppChat = new XmppChat(main, user, nickname, icon, type, content, too, viewType, time); list.add(xmppChat); } cursor.close(); } database.close(); return list; } public boolean delete(Context context, String too) { boolean isDelete = false; // 1. 在内存中创建数据库帮助类的对象 FriendChatOpenHelper helper = new FriendChatOpenHelper(context); // 2. 在磁盘上创建数据库文件 SQLiteDatabase database = helper.getWritableDatabase(); int d = database.delete("chat", "too = ?", new String[]{too + ""}); if (d == 0) { LoggerUtil.systemOut("删除失败"); isDelete = false; } else { LoggerUtil.systemOut("删除失败" + too); isDelete = true; } // 释放资源 database.close(); return isDelete; } }
import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; public class FriendChatOpenHelper extends SQLiteOpenHelper { private Context context; public FriendChatOpenHelper(Context context) { super(context, "XMPPChat.db",null,1); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL("create table chat(id integer primary key autoincrement,main text,user text,nickname text,icon text,type integer,content text,too text,viewtype integer,time text)"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } }
import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import java.util.ArrayList; import java.util.List; import cnpc.fcyt.fcydyy.util.LoggerUtil; import cnpc.fcyt.fcydyy.xmpp.bean.XmppUser; import cnpc.fcyt.fcydyy.xmpp.bean.XmppMessage; import cnpc.fcyt.fcydyy.xmpp.util.TimeUtil; public class MessageDao { public Context context; private static MessageDao mInstance; private MessageDao(Context ctx) { this.context = ctx; } public static MessageDao getInstance(Context ctx) { //懒汉: 考虑线程安全问题, 两种方式: 1. 给方法加同步锁 synchronized, 效率低; 2. 给创建对象的代码块加同步锁 //读数据不会出现线程安全问题, 写数据会出现线程安全问题 //a, B, C if (mInstance == null) { //B, C synchronized (MessageDao.class) { //a if (mInstance == null) { mInstance = new MessageDao(ctx); } } } return mInstance; } public List<XmppMessage> queryMessage(Context context,String main ) { // 1. 在内存中创建数据库帮助类的对象 MessageOpenHelper helper = new MessageOpenHelper(context); // 2. 在磁盘上创建数据库文件 SQLiteDatabase database = helper.getReadableDatabase(); Cursor cursor = database.query("message", null, "main = ?", new String[]{main}, null, null, null); ArrayList<XmppMessage> list = new ArrayList<>(); while (cursor.moveToNext()) { String type = cursor.getString(cursor.getColumnIndex("type")); int id = cursor.getInt(cursor.getColumnIndex("id")); String to = cursor.getString(cursor.getColumnIndex("too")); String username = cursor.getString(cursor.getColumnIndex("username")); String name = cursor.getString(cursor.getColumnIndex("name")); XmppUser user = new XmppUser(username, name); String time = cursor.getString(cursor.getColumnIndex("time")); String content = cursor.getString(cursor.getColumnIndex("content")); int result = cursor.getInt(cursor.getColumnIndex("result")); XmppMessage xm = new XmppMessage(id, to, type, user, time, content, result, main); list.add(xm); } return list; } public int queryIshas(Context context, String main, String type) { // 1. 在内存中创建数据库帮助类的对象 MessageOpenHelper helper = new MessageOpenHelper(context); // 2. 在磁盘上创建数据库文件 SQLiteDatabase database = helper.getReadableDatabase(); Cursor cursor = database.query("message", null, "main=? and type=?", new String[]{main, type}, null, null, null); if (cursor != null) { if (!cursor.moveToFirst()) { //插入 LoggerUtil.systemOut("没有查询到"); return -1; } else { //更新 LoggerUtil.systemOut("查询到了"); int id = cursor.getInt(cursor.getColumnIndex("id")); return id; } } else { LoggerUtil.systemOut("cursor为空"); return -1; } } public int queryhasMsg(Context context, String too, String type) { // 1. 在内存中创建数据库帮助类的对象 MessageOpenHelper helper = new MessageOpenHelper(context); // 2. 在磁盘上创建数据库文件 SQLiteDatabase database = helper.getReadableDatabase(); Cursor cursor = database.query("message", null, "too=? and type=?", new String[]{too, type}, null, null, null); if (cursor != null) { if (!cursor.moveToFirst()) { //插入 LoggerUtil.systemOut("没有查询到"); return -1; } else { //更新 LoggerUtil.systemOut("查询到了"); int id = cursor.getInt(cursor.getColumnIndex("id")); return id; } } else { LoggerUtil.systemOut("cursor为空"); return -1; } } public Cursor queryIshasResult(Context context, String main, String type) { // 1. 在内存中创建数据库帮助类的对象 MessageOpenHelper helper = new MessageOpenHelper(context); // 2. 在磁盘上创建数据库文件 SQLiteDatabase database = helper.getReadableDatabase(); Cursor cursor = database.query("message", null, "main=? and type=?", new String[]{main, type}, null, null, null); if (cursor != null) { if (!cursor.moveToFirst()) { //插入 LoggerUtil.systemOut("没有查询到"); return null; } else { //更新 LoggerUtil.systemOut("查询到了"); int result = cursor.getInt(cursor.getColumnIndex("result")); return cursor; } } else { LoggerUtil.systemOut("cursor为空"); return null; } } public boolean inserts(Context context, XmppMessage xm) { boolean isSucceed = false; // 1. 在内存中创建数据库帮助类的对象 MessageOpenHelper helper = new MessageOpenHelper(context); // 2. 在磁盘上创建数据库文件 SQLiteDatabase database = helper.getWritableDatabase(); /** * table :表名 * nullColumnHack: */ ContentValues values = new ContentValues(); values.put("main", xm.getMain()); values.put("name", xm.getUser().getName()); values.put("username", xm.getUser().getUserName()); values.put("too", xm.getTo()); values.put("type", xm.getType()); values.put("content", xm.getContent()); values.put("time", xm.getTime()); values.put("result", xm.getResult()); long id = database.insert("message", null, values); if (id == -1) { LoggerUtil.systemOut("插入失败"); isSucceed = false; } else { LoggerUtil.systemOut("插入成功"); isSucceed = true; } // 释放资源 database.close(); return isSucceed; } public boolean update(Context context, int id, String content, int result) { // 1. 在内存中创建数据库帮助类的对象 MessageOpenHelper helper = new MessageOpenHelper(context); // 2. 在磁盘上创建数据库文件 SQLiteDatabase database = helper.getWritableDatabase(); /** * table :表名 * nullColumnHack: */ ContentValues values = new ContentValues(); values.put("content", content); values.put("time", TimeUtil.getDate()); values.put("result", result); //返回更新的行数 int update = database.update("message", values, "id=?", new String[]{id + ""}); database.close(); return update > 0; } public boolean updateResult(Context context, String too,String type ,String content) { // 1. 在内存中创建数据库帮助类的对象 MessageOpenHelper helper = new MessageOpenHelper(context); // 2. 在磁盘上创建数据库文件 SQLiteDatabase database = helper.getWritableDatabase(); /** * table :表名 * nullColumnHack: */ ContentValues values = new ContentValues(); values.put("result", 0); if (!content.isEmpty()){ values.put("content", content); } values.put("time", TimeUtil.getDate()); //返回更新的行数 int update = database.update("message", values, "too=? and type = ? ", new String[]{too,type}); database.close(); return update > 0; } public boolean delete(Context context, int id) { boolean isDelete = false; // 1. 在内存中创建数据库帮助类的对象 MessageOpenHelper helper = new MessageOpenHelper(context); // 2. 在磁盘上创建数据库文件 SQLiteDatabase database = helper.getWritableDatabase(); int d = database.delete("message", "id = ?", new String[]{id + ""}); if (d == 0) { LoggerUtil.systemOut("删除失败"); isDelete = false; } else { LoggerUtil.systemOut("删除失败" + id); isDelete = true; } // 释放资源 database.close(); return isDelete; } }
import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; public class MessageOpenHelper extends SQLiteOpenHelper { private Context context; public MessageOpenHelper(Context context) { super(context, "XMPPMessage.db",null,1); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL("create table message(id integer primary key autoincrement,main text,too text,name varchar(20),username text,type text,content text,time text,result integer)"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } }
6.开发过程中,注意注册的用户名和聊天等相关JID的区别,聊天发送的JID需要后缀标识,建群同理,无法与注册用户的JID对应,这点比较无语....