首页 > 代码库 > Android学习笔记--基于XMPP的即时通讯
Android学习笔记--基于XMPP的即时通讯
一、常见即时通讯实现
socket
openfire+asmack
环信
信鸽
融云
二、XMPP优势
1. 开放性
XMPP协议是自由、开放、公开的,并且易于了解。而且在客户端、服务器、组件、源码库等方面,都已经各自有多种实现。
2.跨平台
客户端只要基于XMPP协议,不管是什么平台(包括不同的移动终端)都可以互联互通。
三、XMPP协议简介
The Extensible Messaging and Presence Protocol (可扩展通讯和表示协议) XMPP 以 Jabber 协议为基础,而 Jabber 是即时通讯中常用的开放式协议。
数据格式
XML是XMPP系统架构的核心。它能表述几乎任何一种结构化数据。特别是XMPP利用XML数据流进行客户端一服务器端、服务器端一服务器端的通信。XML数据流一般是由客户端发起至服务端,XML数据流的有效时间直接与用户的在线会话有效时间相关联。
XMPP 的特点是将复杂性从客户端转移到服务器端。这使得客户端编写变得非常容易,更新系统功能也同样变得容易。
XMPP中定义了三个角色:XMPP客户端、XMPP服务器、网关。
客户端:通过 TCP 套接字与XMPP 服务器进行通信
服务器:同时承担了客户端信息记录、连接管理和信息的路由功能
网关:承担着与异构即时通信系统的互联互通(异构系统可以包括SMS(短信),MSN,ICQ等)
五、XMPP协议的地址格式(标志)
每个客户端需要拥有一个地址标识用于定位,XMPP 中称之为 JID (Jabber ID)。地址标识的格式如下
[ node "@" ] domain [ "/" resource ]
例如:
charley@gmail.com/spark
格式与 Email 地址格式类似,但增添了 resource 项(非必需的)。上述例子可以解释为:在 gmail.com 服务器注册的 charley用户,且使用 spark客户端软件登录。资源(resource )只用来识别属于用户的位置或设备等,一个用户可以同时以多种资源与同一个XMPP服务器连接(说白了就是用于支持同一账号的多客户端登录)。
六、协议消息格式
XMPP协议包括3个顶层XML元素:Message、Presence和IQ。
Message用来表示传输的消息,当用户发送一条消息时。就会在流的上下文中插入一个Message元素,中间有用户发送的相关信息;
Presence用来表示用户的状态。当用户改变自己的状态时。就会在数据流的上下文中插入一个Presence元素,用来表示用户现在的状态;
IQ用来表示一种请求,响应机制,从一个实体发送请求,另外一个实体接受请求并响应。
XMPP特点
1.客户端通过TCP/IP协议连接到服务器,然后通过XML传输数据。
2.XMPP的核心部分就是一个在网络上分片断发送XML的流协议。这个流协议是XMPP的即时通讯指令的传递基础,也是一个非常重要的可以被进一步利用的网络基础协议。所以可以说,XMPP用TCP传的是XML流。
理论一大堆。。。。接下来贴代码
XmppManager.java
1 package com.example.xmppdemo.fengzhuang; 2 3 import android.util.Log; 4 5 6 7 import org.jivesoftware.smack.Chat; 8 import org.jivesoftware.smack.ChatManager; 9 import org.jivesoftware.smack.ChatManagerListener; 10 import org.jivesoftware.smack.ConnectionConfiguration; 11 import org.jivesoftware.smack.MessageListener; 12 import org.jivesoftware.smack.PacketCollector; 13 import org.jivesoftware.smack.Roster; 14 import org.jivesoftware.smack.RosterEntry; 15 import org.jivesoftware.smack.SmackConfiguration; 16 import org.jivesoftware.smack.XMPPConnection; 17 import org.jivesoftware.smack.XMPPException; 18 import org.jivesoftware.smack.filter.AndFilter; 19 import org.jivesoftware.smack.filter.PacketFilter; 20 import org.jivesoftware.smack.filter.PacketIDFilter; 21 import org.jivesoftware.smack.filter.PacketTypeFilter; 22 import org.jivesoftware.smack.packet.IQ; 23 import org.jivesoftware.smack.packet.Message; 24 import org.jivesoftware.smack.packet.Presence; 25 import org.jivesoftware.smack.packet.Registration; 26 import org.jivesoftware.smack.provider.PrivacyProvider; 27 import org.jivesoftware.smack.provider.ProviderManager; 28 import org.jivesoftware.smackx.Form; 29 import org.jivesoftware.smackx.GroupChatInvitation; 30 import org.jivesoftware.smackx.PrivateDataManager; 31 import org.jivesoftware.smackx.ReportedData; 32 import org.jivesoftware.smackx.bytestreams.socks5.provider.BytestreamsProvider; 33 import org.jivesoftware.smackx.packet.ChatStateExtension; 34 import org.jivesoftware.smackx.packet.LastActivity; 35 import org.jivesoftware.smackx.packet.OfflineMessageInfo; 36 import org.jivesoftware.smackx.packet.OfflineMessageRequest; 37 import org.jivesoftware.smackx.packet.SharedGroupsInfo; 38 import org.jivesoftware.smackx.packet.VCard; 39 import org.jivesoftware.smackx.provider.AdHocCommandDataProvider; 40 import org.jivesoftware.smackx.provider.DataFormProvider; 41 import org.jivesoftware.smackx.provider.DelayInformationProvider; 42 import org.jivesoftware.smackx.provider.DiscoverInfoProvider; 43 import org.jivesoftware.smackx.provider.DiscoverItemsProvider; 44 import org.jivesoftware.smackx.provider.MUCAdminProvider; 45 import org.jivesoftware.smackx.provider.MUCOwnerProvider; 46 import org.jivesoftware.smackx.provider.MUCUserProvider; 47 import org.jivesoftware.smackx.provider.MessageEventProvider; 48 import org.jivesoftware.smackx.provider.MultipleAddressesProvider; 49 import org.jivesoftware.smackx.provider.RosterExchangeProvider; 50 import org.jivesoftware.smackx.provider.StreamInitiationProvider; 51 import org.jivesoftware.smackx.provider.VCardProvider; 52 import org.jivesoftware.smackx.provider.XHTMLExtensionProvider; 53 import org.jivesoftware.smackx.search.UserSearch; 54 import org.jivesoftware.smackx.search.UserSearchManager; 55 56 import java.util.ArrayList; 57 import java.util.Collection; 58 import java.util.Collections; 59 import java.util.Iterator; 60 import java.util.List; 61 62 /** 63 * Created by Kelvin on 2016/12/12. 64 */ 65 66 public class XmppManager { 67 68 private static XmppManager xmppManager; //XmppManager的实例 69 70 private XmppManager(){} //私有化构造器 71 72 public static XmppManager getInstance(){ 73 if (xmppManager == null){ 74 synchronized (XmppManager.class){ 75 if (xmppManager == null){ 76 xmppManager = new XmppManager(); 77 } 78 } 79 } 80 return xmppManager; 81 } 82 83 //XmppConnection 连接对象 84 private XMPPConnection xmppConnection; 85 86 //将其翻译成中文为"花名册",用来表示一个用户的所有好友清单以及申请加好友的用户清单, 87 // 为了便于管理,Roster中的用户分组进行管理。 88 private Roster roster; 89 90 //用于接收消息的接口 91 private XmppManagerCallback xmppManagerCallback; 92 93 //Debug标签 94 private final String TAG="XmppManager"; 95 96 /** 97 * 打开网络连接 98 */ 99 private void openConnection(){ 100 101 //连接对象为空或者还没有认证的时候(isAuthenticated()方法返回值是boolean类型,意思是是否认证) 102 if (xmppConnection == null || !xmppConnection.isAuthenticated()){ 103 try { 104 //配置连接,(参数一:服务器ip地址,参数二:端口号,参数三:服务器名字) 105 ConnectionConfiguration configuration = new ConnectionConfiguration(Constant.SERVER_HOST, 106 Constant.SERVER_PORT,Constant.SERVER_NAME); 107 108 //Xmpp是否可以自动重连(客户端掉线时是否可以重新连接) 109 configuration.setReconnectionAllowed(true); 110 111 //设置安全模式 112 configuration.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled); 113 //特别补充,在设置configuaration的时候对认证的设置,代码如下: 114 //这个属性默认值是true,设置时得需要与服务器那边统一,如果不一致,就算用户注册成功后, 115 // 登录时也会返回 server-unavailable(503)错误,我们用的是ejabberd服务器,默认设置SASL认证开启, 116 // 所以开始我设置为false,怎么都无法登录,最后注释这句代码,成功登录:) 117 //相当于一个权限 118 configuration.setSASLAuthenticationEnabled(false); 119 // 状态设为离线,为了取离线消息 120 configuration.setSendPresence(true); 121 // 配置各种Provider,如果不配置,则会无法解析数据 122 configureConnection(ProviderManager.getInstance()); 123 xmppConnection = new XMPPConnection(configuration); 124 //打开连接 125 xmppConnection.connect(); 126 } catch (XMPPException e) { 127 e.printStackTrace(); 128 } 129 } 130 } 131 132 /** 133 * 配置连接 134 * @param pm 135 */ 136 public void configureConnection(ProviderManager pm) { 137 // Private Data Storage 138 pm.addIQProvider("query", "jabber:iq:private", new PrivateDataManager.PrivateDataIQProvider()); 139 // Time 140 try { 141 pm.addIQProvider("query", "jabber:iq:time", Class.forName("org.jivesoftware.smackx.packet.Time")); 142 } catch (ClassNotFoundException e) { 143 Log.w("TestClient", "Can‘t load class for org.jivesoftware.smackx.packet.Time"); 144 } 145 146 // Roster Exchange 147 pm.addExtensionProvider("x", "jabber:x:roster", new RosterExchangeProvider()); 148 // Message Events 149 pm.addExtensionProvider("x", "jabber:x:event", new MessageEventProvider()); 150 // Chat State 151 pm.addExtensionProvider("active", "http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider()); 152 pm.addExtensionProvider("composing", "http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider()); 153 pm.addExtensionProvider("paused", "http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider()); 154 pm.addExtensionProvider("inactive", "http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider()); 155 pm.addExtensionProvider("gone", "http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider()); 156 // XHTML 157 pm.addExtensionProvider("html", "http://jabber.org/protocol/xhtml-im", new XHTMLExtensionProvider()); 158 // Group Chat Invitations 159 pm.addExtensionProvider("x", "jabber:x:conference", new GroupChatInvitation.Provider()); 160 // Service Discovery # Items 161 pm.addIQProvider("query", "http://jabber.org/protocol/disco#items", new DiscoverItemsProvider()); 162 // Service Discovery # Info 163 pm.addIQProvider("query", "http://jabber.org/protocol/disco#info", new DiscoverInfoProvider()); 164 // Data Forms 165 pm.addExtensionProvider("x", "jabber:x:data", new DataFormProvider()); 166 // MUC User 167 pm.addExtensionProvider("x", "http://jabber.org/protocol/muc#user", new MUCUserProvider()); 168 // MUC Admin 169 pm.addIQProvider("query", "http://jabber.org/protocol/muc#admin", new MUCAdminProvider()); 170 // MUC Owner 171 pm.addIQProvider("query", "http://jabber.org/protocol/muc#owner", new MUCOwnerProvider()); 172 // Delayed Delivery 173 pm.addExtensionProvider("x", "jabber:x:delay", new DelayInformationProvider()); 174 // Version 175 try { 176 pm.addIQProvider("query", "jabber:iq:version", Class.forName("org.jivesoftware.smackx.packet.Version")); 177 } catch (ClassNotFoundException e) { 178 // Not sure what‘s happening here. 179 } 180 // VCard 181 pm.addIQProvider("vCard", "vcard-temp", new VCardProvider()); 182 // Offline Message Requests 183 pm.addIQProvider("offline", "http://jabber.org/protocol/offline", new OfflineMessageRequest.Provider()); 184 // Offline Message Indicator 185 pm.addExtensionProvider("offline", "http://jabber.org/protocol/offline", new OfflineMessageInfo.Provider()); 186 // Last Activity 187 pm.addIQProvider("query", "jabber:iq:last", new LastActivity.Provider()); 188 // User Search 189 pm.addIQProvider("query", "jabber:iq:search", new UserSearch.Provider()); 190 // SharedGroupsInfo 191 pm.addIQProvider("sharedgroup", "http://www.jivesoftware.org/protocol/sharedgroup", 192 new SharedGroupsInfo.Provider()); 193 // JEP-33: Extended Stanza Addressing 194 pm.addExtensionProvider("addresses", "http://jabber.org/protocol/address", new MultipleAddressesProvider()); 195 // FileTransfer 196 pm.addIQProvider("si", "http://jabber.org/protocol/si", new StreamInitiationProvider()); 197 pm.addIQProvider("query", "http://jabber.org/protocol/bytestreams", new BytestreamsProvider()); 198 // Privacy 199 pm.addIQProvider("query", "jabber:iq:privacy", new PrivacyProvider()); 200 pm.addIQProvider("command", "http://jabber.org/protocol/commands", new AdHocCommandDataProvider()); 201 pm.addExtensionProvider("malformed-action", "http://jabber.org/protocol/commands", 202 new AdHocCommandDataProvider.MalformedActionError()); 203 pm.addExtensionProvider("bad-locale", "http://jabber.org/protocol/commands", 204 new AdHocCommandDataProvider.BadLocaleError()); 205 pm.addExtensionProvider("bad-payload", "http://jabber.org/protocol/commands", 206 new AdHocCommandDataProvider.BadPayloadError()); 207 pm.addExtensionProvider("bad-sessionid", "http://jabber.org/protocol/commands", 208 new AdHocCommandDataProvider.BadSessionIDError()); 209 pm.addExtensionProvider("session-expired", "http://jabber.org/protocol/commands", 210 new AdHocCommandDataProvider.SessionExpiredError()); 211 } 212 213 /** 214 * 获取链接 215 * @return 216 */ 217 public XMPPConnection getConnection(){ 218 if (xmppConnection == null){ 219 openConnection(); 220 } 221 return xmppConnection; 222 } 223 224 /** 225 * 关闭链接 226 */ 227 public void colseConnection(){ 228 if (xmppConnection != null && xmppConnection.isConnected()){ 229 xmppConnection.disconnect(); 230 xmppConnection = null; 231 } 232 } 233 234 /** 235 * 登陆的方法 236 * @param account 账号 237 * @param psw 密码 238 * @return 239 */ 240 public boolean login(String account,String psw){ 241 242 //判断连接是否存在 243 if (getConnection() == null){ 244 return false; 245 } 246 247 if (!getConnection().isAuthenticated() && getConnection().isConnected()){ 248 try { 249 //登陆 250 getConnection().login(account,psw); 251 //登陆之后更改用户状态 252 Presence presence = new Presence(Presence.Type.available); 253 //设置用户在线 254 presence.setMode(Presence.Mode.available); 255 //向服务器发送状态 256 getConnection().sendPacket(presence); 257 //接收消息监听 258 ChatManager chatManager = getConnection().getChatManager(); 259 chatManager.addChatListener(chatManagerListener); 260 return true; 261 } catch (XMPPException e) { 262 e.printStackTrace(); 263 return false; 264 } 265 } 266 return false; 267 } 268 269 /** 270 * 聊天管理监听器 271 */ 272 private ChatManagerListener chatManagerListener = new ChatManagerListener(){ 273 274 @Override 275 public void chatCreated(Chat chat, boolean b) { 276 chat.addMessageListener(new MessageListener() { 277 @Override 278 public void processMessage(Chat chat, Message message) { 279 //当消息内容为空时,直接反悔 280 if (TVUtil.isEmpty(message.getBody())){ 281 return; 282 } 283 //当消息内容不可空时,通过接口回调的把消息内容传出去 284 if (xmppManagerCallback != null){ 285 xmppManagerCallback.receiveMsg(message); 286 } 287 } 288 }); 289 } 290 }; 291 292 /** 293 * 注册用户 294 * 表示的是Info/Query(信息与查询),它为XMPP通信提供请求与响应机制。它与HTTP 295 * 协议的基本工作原理非常相似,允许获取和设置查询,与HTTP 的GET 和POST 动作类似。 296 * @return 297 */ 298 public IQ registered(String account, String psw){ 299 300 if (getConnection() == null){ 301 return null; 302 } 303 304 //设置注册所需要的信息 305 Registration registration = new Registration(); 306 registration.setType(IQ.Type.SET); 307 registration.setTo(getConnection().getServiceName()); 308 registration.setUsername(account); 309 registration.setPassword(psw); 310 311 //PacketFilter:包过滤类,过滤一些不用的包 312 PacketFilter filter = new AndFilter(new PacketIDFilter(registration.getPacketID()), new PacketTypeFilter(IQ.class)); 313 PacketCollector collector = getConnection().createPacketCollector(filter); 314 // 向服务器端,发送注册Packet包,注意其中Registration是Packet的子类 315 getConnection().sendPacket(registration); 316 IQ result = (IQ) collector.nextResult(SmackConfiguration.getPacketReplyTimeout()); 317 collector.cancel(); //停止请求result 318 return result; 319 } 320 321 /** 322 * 退出登陆 323 */ 324 public void outLogin(){ 325 if (getConnection() == null){ 326 return; 327 } 328 329 //设置退出状态 330 Presence presence = new Presence(Presence.Type.unavailable); 331 //发送请求 332 getConnection().sendPacket(presence); 333 //关闭连接 334 colseConnection(); 335 } 336 337 /** 338 * 获取用户信息 339 * @param user 340 * @return 341 */ 342 public VCard getUserInfo(String user){ 343 VCard vCard = null; 344 try { 345 vCard = new VCard(); 346 // 加入这句代码,解决No VCard for 347 ProviderManager.getInstance().addIQProvider("vCard", "vcard-temp", new VCardProvider()); 348 if (user == null){ 349 vCard.load(getConnection()); 350 }else{ 351 vCard.load(getConnection(), user + "@" + Constant.SERVER_NAME); 352 } 353 } catch (XMPPException e) { 354 e.printStackTrace(); 355 } 356 return vCard; 357 } 358 359 /** 360 * 获取xmpp好友列表 361 * 注意:这里的User是在Xmpp包下的User 362 */ 363 public List<User> getFriendList() { 364 // Roster:花名册 365 if (roster == null) { 366 roster = getConnection().getRoster(); 367 } 368 List<User> userList = new ArrayList<User>(); 369 Collection<RosterEntry> entries = roster.getEntries(); 370 for(RosterEntry entry : entries){ 371 userList.add(new User(getUsername(entry.getUser()),entry.getType())); 372 } 373 Collections.sort(userList,new PingyinComparator()); 374 return userList; 375 } 376 377 /** 378 * 通过jid获得username 379 * @param fullUsername 380 * @return 381 */ 382 public static String getUsername(String fullUsername){ 383 return fullUsername.split("@")[0]; 384 } 385 386 /** 387 * 搜索用户 388 * @param userName 389 * @return 390 * @throws XMPPException 391 */ 392 public List<String> searchUser(String userName) { 393 if (getConnection() == null){ 394 return null; 395 } 396 List<String> userList = new ArrayList<>(); 397 try { 398 UserSearchManager search = new UserSearchManager(getConnection()); 399 Form searchForm = search.getSearchForm("search."+ getConnection().getServiceName()); 400 Form answerForm = searchForm.createAnswerForm(); 401 answerForm.setAnswer("Username", true); 402 answerForm.setAnswer("search", userName.trim()); 403 ReportedData data = http://www.mamicode.com/search.getSearchResults(answerForm,"search." + xmppConnection.getServiceName()); 404 Iterator<ReportedData.Row> it = data.getRows(); 405 ReportedData.Row row = null; 406 while (it.hasNext()) { 407 row = it.next(); 408 userList.add(row.getValues("Username").next().toString()); 409 } 410 } catch (XMPPException e) { 411 e.printStackTrace(); 412 } 413 return userList; 414 } 415 416 /** 417 * 添加好友(无分组) 418 * @param userName 419 * @return 420 */ 421 public boolean addFriend(String userName) { 422 if (getConnection() == null) 423 return false; 424 try { 425 getConnection().getRoster().createEntry(getFullUsername(userName), getFullUsername(userName), null); 426 return true; 427 } catch (Exception e) { 428 e.printStackTrace(); 429 return false; 430 } 431 } 432 433 /** 434 * 通过username获得jid 435 * @param username 436 * @return 437 */ 438 public static String getFullUsername(String username){ 439 return username + "@" + Constant.SERVER_NAME; 440 } 441 442 /** 443 * 创建聊天 444 * @param toUser 445 * @return 446 */ 447 public Chat createChat(String toUser){ 448 ChatManager chatManager = getConnection().getChatManager(); 449 Chat newchat = chatManager.createChat(toUser + "@"+ Constant.SERVER_NAME, null); 450 return newchat; 451 } 452 453 /** 454 * 发送文本消息 455 * @param message 456 */ 457 public void sendMsg(Chat chat, String message) { 458 try { 459 chat.sendMessage(message); 460 } catch (Exception e) { 461 e.printStackTrace(); 462 } 463 } 464 465 /** 466 * 接口回调 467 */ 468 public interface XmppManagerCallback { 469 //接收消息回调函数 470 void receiveMsg(Message message); 471 } 472 473 /** 474 * 设置接口的方法 475 * @param xmppManagerCallback 接口对象 476 */ 477 public void setXmppManagerCallback(XmppManagerCallback xmppManagerCallback) { 478 this.xmppManagerCallback = xmppManagerCallback; 479 } 480 }
这里面封装了所有的方法
ChatMsg.java
1 package com.example.xmppdemo.fengzhuang; 2 import android.os.Parcel; 3 import android.os.Parcelable; 4 5 /** 6 * 7 * 描述(请用一句话描述这个内容) 8 */ 9 10 public class ChatMsg implements Parcelable { 11 12 private String sender; // 发送者 13 private String body; // 发送的消息 14 15 public String getSender() { 16 return sender; 17 } 18 19 public void setSender(String sender) { 20 this.sender = sender; 21 } 22 23 public String getBody() { 24 return body; 25 } 26 27 public void setBody(String body) { 28 this.body = body; 29 } 30 31 public static final Creator<ChatMsg> CREATOR = new Creator<ChatMsg>() { 32 @Override 33 public ChatMsg createFromParcel(Parcel in) { 34 ChatMsg chatMsg = new ChatMsg(); 35 chatMsg.sender = in.readString(); 36 chatMsg.body = in.readString(); 37 return chatMsg; 38 } 39 40 @Override 41 public ChatMsg[] newArray(int size) { 42 return null; 43 } 44 }; 45 46 @Override 47 public int describeContents() { 48 return 0; 49 } 50 51 @Override 52 public void writeToParcel(Parcel parcel, int i) { 53 parcel.writeString(sender); 54 parcel.writeString(body); 55 } 56 }
还有一个
ChatService.java
1 package com.example.xmppdemo.service; 2 3 import android.app.Activity; 4 import android.app.Notification; 5 import android.app.NotificationManager; 6 import android.app.PendingIntent; 7 import android.app.Service; 8 import android.content.BroadcastReceiver; 9 import android.content.Context; 10 import android.content.Intent; 11 import android.content.IntentFilter; 12 import android.os.IBinder; 13 import android.support.annotation.Nullable; 14 15 16 import com.example.xmppdemo.ChatActivity; 17 import com.example.xmppdemo.R; 18 import com.example.xmppdemo.fengzhuang.ChatMsg; 19 import com.example.xmppdemo.fengzhuang.Constant; 20 import com.example.xmppdemo.fengzhuang.XmppManager; 21 22 import org.jivesoftware.smack.XMPPException; 23 import org.jivesoftware.smack.packet.Message; 24 import org.jivesoftware.smackx.OfflineMessageManager; 25 26 import java.util.ArrayList; 27 import java.util.Iterator; 28 29 /** 30 31 * 描述(请用一句话描述这个内容) 32 */ 33 public class ChatService extends Service implements XmppManager.XmppManagerCallback { 34 35 //接收到的消息集合,包括两种消息: 1,不在对话框界面的消息 2,离线消息 36 private ArrayList<ChatMsg> messageList = new ArrayList<>(); 37 private MesageBroadcastReceiver mesageReceiver; 38 39 @Override 40 public void onCreate() { 41 XmppManager.getInstance().setXmppManagerCallback(this); 42 //注册消息接收广播 43 IntentFilter filter = new IntentFilter(Constant.INTENT_ACTION_MESSAGE_RECEIVE); 44 mesageReceiver = new MesageBroadcastReceiver(); 45 registerReceiver(mesageReceiver, filter); 46 } 47 48 @Nullable 49 @Override 50 public IBinder onBind(Intent intent) { 51 return null; 52 } 53 54 @Override 55 public void receiveMsg(Message message) { 56 ChatMsg chatMsg = new ChatMsg(); 57 58 chatMsg.setSender(message.getFrom()); 59 chatMsg.setBody(message.getBody()); 60 sendReceiverMsgBroadCast(chatMsg); 61 } 62 /** 63 * 发送广播的方法 64 * @param 65 */ 66 private void sendReceiverMsgBroadCast(ChatMsg chatMsg){ 67 Intent intent = new Intent(); 68 intent.setAction(Constant.INTENT_ACTION_MESSAGE_RECEIVE); 69 intent.putExtra("message", chatMsg); 70 /** 71 * MesageBroadcastReceiver指定为最后的接受者,Activity.RESULT_CANCELED指定初始的结果码, 72 * 如果ChatActivity中的广播接收者处理了这条广播,则结果码会在ChatActivity中被更改为Activity.RESULT_OK, 73 * 反之,ChatActivity中的广播接收者没有处理,则结果码仍然为Activity.RESULT_CANCELED 74 */ 75 sendOrderedBroadcast(intent,null,mesageReceiver,null, Activity.RESULT_CANCELED,null,null); 76 } 77 /** 78 * 消息广播 79 */ 80 private class MesageBroadcastReceiver extends BroadcastReceiver{ 81 82 @Override 83 public void onReceive(Context context, Intent intent) { 84 ChatMsg chatMsg = intent.getParcelableExtra("message"); 85 int resultCode = getResultCode(); 86 if (isOrderedBroadcast()){ //判断是否有下一个广播,true为是 false为无 87 88 if (resultCode != Activity.RESULT_OK){ 89 showMsgNotice(chatMsg); 90 } 91 } 92 } 93 } 94 95 /** 96 * 显示消息通知 97 * @param chatMsg 消息类 98 */ 99 private void showMsgNotice(ChatMsg chatMsg){ 100 messageList.add(chatMsg); //把消息实体加入到集合中 101 //获取通知服务 102 NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 103 //取消所有 104 nm.cancelAll(); 105 //创建消息 106 /* Notification notification = new Notification(R.drawable.ic_launcher 107 ,"您有"+messageList.size()+"条新消息", System.currentTimeMillis()); 108 notification.flags = Notification.FLAG_AUTO_CANCEL; 109 notification.sound= Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.ms); 110 Intent intent = new Intent(this, ChatActivity.class); 111 intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); 112 intent.putExtra("from", "notification"); 113 intent.putParcelableArrayListExtra("messageList", messageList); 114 PendingIntent contentIntent = PendingIntent.getActivity(this, R.string.app_name, intent, PendingIntent.FLAG_UPDATE_CURRENT); 115 notification.setLatestEventInfo(this, chatMsg.getSender().split("@")[0], chatMsg.getBody(), contentIntent); 116 nm.notify(0, notification);*/ 117 118 Notification.Builder builder = new Notification.Builder(this); 119 builder.setContentText("微信通知"); //设置通知的标题 120 builder.setSmallIcon(R.drawable.search_icon); //设置通知的小图标 121 builder.setContentText("您有"+messageList.size()+"条新消息"); //写入通知内容 122 // builder.setSound(Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.ms)); 123 Intent intent = new Intent(this, ChatActivity.class); 124 intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); 125 intent.putExtra("from", "notification"); 126 intent.putParcelableArrayListExtra("messageList", messageList); 127 PendingIntent contentIntent = PendingIntent.getActivity(this, R.string.app_name, intent, PendingIntent.FLAG_UPDATE_CURRENT); 128 builder.setContentIntent(contentIntent); 129 //获得通知 130 Notification notification = builder.getNotification(); 131 nm.notify(0, notification); 132 } 133 134 /** 135 * 获取离线消息 136 */ 137 public void getOfflineMessage() { 138 OfflineMessageManager offlineMessageManager = new OfflineMessageManager(XmppManager.getInstance().getConnection()); 139 try { 140 Iterator<Message> it = offlineMessageManager.getMessages(); 141 while (it.hasNext()) { 142 Message message = it.next(); 143 ChatMsg chatMsg = new ChatMsg(); 144 chatMsg.setSender(message.getFrom()); 145 chatMsg.setBody(message.getBody()); 146 sendReceiverMsgBroadCast(chatMsg); 147 } 148 offlineMessageManager.deleteMessages(); 149 } catch (XMPPException e) { 150 e.printStackTrace(); 151 } 152 } 153 154 @Override 155 public void onDestroy() { 156 super.onDestroy(); 157 XmppManager.getInstance().colseConnection(); 158 unregisterReceiver(mesageReceiver); 159 } 160 }
基本重要的就这么多,代码附上,
链接:http://pan.baidu.com/s/1hs1Dg3M 密码:s57b
可能说的不是很清楚,但是代码里面都有
Android学习笔记--基于XMPP的即时通讯