一、常见即时通讯实现
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服务器、网关。
客户端:通过
服务器:同时承担了客户端信息记录、连接管理和信息的路由功能
网关:承担着与异构即时通信系统的互联互通(异构系统可以包括SMS(短信),MSN,ICQ等)
五、XMPP协议的地址格式(标志)
每个客户端需要拥有一个地址标识用于定位,XMPP 中称之为 JID (Jabber ID)。地址标识的格式如下
[ node "@" ] domain [ "/" resource ]
例如:
charley@gmail.com/spark
格式与
六、协议消息格式
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 = 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
可能说的不是很清楚,但是代码里面都有
能看到的代码不是自己的,自己写出来的才是自己的