Android学习笔记--基于XMPP的即时通讯

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

基本重要的就这么多,代码附上,
链接:http://pan.baidu.com/s/1hs1Dg3M 密码:s57b
可能说的不是很清楚,但是代码里面都有
 

    推荐阅读