一、常见即时通讯实现
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
package com.example.xmppdemo.fengzhuang;
import android.util.Log;
import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.ChatManager;
import org.jivesoftware.smack.ChatManagerListener;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.MessageListener;
import org.jivesoftware.smack.PacketCollector;
import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.RosterEntry;
import org.jivesoftware.smack.SmackConfiguration;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.filter.AndFilter;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.filter.PacketIDFilter;
import org.jivesoftware.smack.filter.PacketTypeFilter;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.packet.Registration;
import org.jivesoftware.smack.provider.PrivacyProvider;
import org.jivesoftware.smack.provider.ProviderManager;
import org.jivesoftware.smackx.Form;
import org.jivesoftware.smackx.GroupChatInvitation;
import org.jivesoftware.smackx.PrivateDataManager;
import org.jivesoftware.smackx.ReportedData;
import org.jivesoftware.smackx.bytestreams.socks5.provider.BytestreamsProvider;
import org.jivesoftware.smackx.packet.ChatStateExtension;
import org.jivesoftware.smackx.packet.LastActivity;
import org.jivesoftware.smackx.packet.OfflineMessageInfo;
import org.jivesoftware.smackx.packet.OfflineMessageRequest;
import org.jivesoftware.smackx.packet.SharedGroupsInfo;
import org.jivesoftware.smackx.packet.VCard;
import org.jivesoftware.smackx.provider.AdHocCommandDataProvider;
import org.jivesoftware.smackx.provider.DataFormProvider;
import org.jivesoftware.smackx.provider.DelayInformationProvider;
import org.jivesoftware.smackx.provider.DiscoverInfoProvider;
import org.jivesoftware.smackx.provider.DiscoverItemsProvider;
import org.jivesoftware.smackx.provider.MUCAdminProvider;
import org.jivesoftware.smackx.provider.MUCOwnerProvider;
import org.jivesoftware.smackx.provider.MUCUserProvider;
import org.jivesoftware.smackx.provider.MessageEventProvider;
import org.jivesoftware.smackx.provider.MultipleAddressesProvider;
import org.jivesoftware.smackx.provider.RosterExchangeProvider;
import org.jivesoftware.smackx.provider.StreamInitiationProvider;
import org.jivesoftware.smackx.provider.VCardProvider;
import org.jivesoftware.smackx.provider.XHTMLExtensionProvider;
import org.jivesoftware.smackx.search.UserSearch;
import org.jivesoftware.smackx.search.UserSearchManager;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
/**
* Created by Kelvin on 2016/12/12.
*/
public class XmppManager {
private static XmppManager xmppManager; //XmppManager的实例
private XmppManager(){} //私有化构造器
public static XmppManager getInstance(){
if (xmppManager == null){
synchronized (XmppManager.class){
if (xmppManager == null){
xmppManager = new XmppManager();
}
}
}
return xmppManager;
}
//XmppConnection 连接对象
private XMPPConnection xmppConnection;
//将其翻译成中文为"花名册",用来表示一个用户的所有好友清单以及申请加好友的用户清单,
// 为了便于管理,Roster中的用户分组进行管理。
private Roster roster;
//用于接收消息的接口
private XmppManagerCallback xmppManagerCallback;
//Debug标签
private final String TAG="XmppManager";
/**
* 打开网络连接
*/
private void openConnection(){
//连接对象为空或者还没有认证的时候(isAuthenticated()方法返回值是boolean类型,意思是是否认证)
if (xmppConnection == null || !xmppConnection.isAuthenticated()){
try {
//配置连接,(参数一:服务器ip地址,参数二:端口号,参数三:服务器名字)
ConnectionConfiguration configuration = new ConnectionConfiguration(Constant.SERVER_HOST,
Constant.SERVER_PORT,Constant.SERVER_NAME);
//Xmpp是否可以自动重连(客户端掉线时是否可以重新连接)
configuration.setReconnectionAllowed(true);
//设置安全模式
configuration.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled);
//特别补充,在设置configuaration的时候对认证的设置,代码如下:
//这个属性默认值是true,设置时得需要与服务器那边统一,如果不一致,就算用户注册成功后,
// 登录时也会返回 server-unavailable(503)错误,我们用的是ejabberd服务器,默认设置SASL认证开启,
// 所以开始我设置为false,怎么都无法登录,最后注释这句代码,成功登录:)
//相当于一个权限
configuration.setSASLAuthenticationEnabled(false);
// 状态设为离线,为了取离线消息
configuration.setSendPresence(true);
// 配置各种Provider,如果不配置,则会无法解析数据
configureConnection(ProviderManager.getInstance());
xmppConnection = new XMPPConnection(configuration);
//打开连接
xmppConnection.connect();
} catch (XMPPException e) {
e.printStackTrace();
}
}
}
/**
* 配置连接
* @param pm
*/
public void configureConnection(ProviderManager pm) {
// Private Data Storage
pm.addIQProvider("query", "jabber:iq:private", new PrivateDataManager.PrivateDataIQProvider());
// Time
try {
pm.addIQProvider("query", "jabber:iq:time", Class.forName("org.jivesoftware.smackx.packet.Time"));
} catch (ClassNotFoundException e) {
Log.w("TestClient", "Can't load class for org.jivesoftware.smackx.packet.Time");
}
// Roster Exchange
pm.addExtensionProvider("x", "jabber:x:roster", new RosterExchangeProvider());
// Message Events
pm.addExtensionProvider("x", "jabber:x:event", new MessageEventProvider());
// Chat State
pm.addExtensionProvider("active", "http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider());
pm.addExtensionProvider("composing", "http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider());
pm.addExtensionProvider("paused", "http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider());
pm.addExtensionProvider("inactive", "http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider());
pm.addExtensionProvider("gone", "http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider());
// XHTML
pm.addExtensionProvider("html", "http://jabber.org/protocol/xhtml-im", new XHTMLExtensionProvider());
// Group Chat Invitations
pm.addExtensionProvider("x", "jabber:x:conference", new GroupChatInvitation.Provider());
// Service Discovery # Items
pm.addIQProvider("query", "http://jabber.org/protocol/disco#items", new DiscoverItemsProvider());
// Service Discovery # Info
pm.addIQProvider("query", "http://jabber.org/protocol/disco#info", new DiscoverInfoProvider());
// Data Forms
pm.addExtensionProvider("x", "jabber:x:data", new DataFormProvider());
// MUC User
pm.addExtensionProvider("x", "http://jabber.org/protocol/muc#user", new MUCUserProvider());
// MUC Admin
pm.addIQProvider("query", "http://jabber.org/protocol/muc#admin", new MUCAdminProvider());
// MUC Owner
pm.addIQProvider("query", "http://jabber.org/protocol/muc#owner", new MUCOwnerProvider());
// Delayed Delivery
pm.addExtensionProvider("x", "jabber:x:delay", new DelayInformationProvider());
// Version
try {
pm.addIQProvider("query", "jabber:iq:version", Class.forName("org.jivesoftware.smackx.packet.Version"));
} catch (ClassNotFoundException e) {
// Not sure what's happening here.
}
// VCard
pm.addIQProvider("vCard", "vcard-temp", new VCardProvider());
// Offline Message Requests
pm.addIQProvider("offline", "http://jabber.org/protocol/offline", new OfflineMessageRequest.Provider());
// Offline Message Indicator
pm.addExtensionProvider("offline", "http://jabber.org/protocol/offline", new OfflineMessageInfo.Provider());
// Last Activity
pm.addIQProvider("query", "jabber:iq:last", new LastActivity.Provider());
// User Search
pm.addIQProvider("query", "jabber:iq:search", new UserSearch.Provider());
// SharedGroupsInfo
pm.addIQProvider("sharedgroup", "http://www.jivesoftware.org/protocol/sharedgroup",
new SharedGroupsInfo.Provider());
// JEP-33: Extended Stanza Addressing
pm.addExtensionProvider("addresses", "http://jabber.org/protocol/address", new MultipleAddressesProvider());
// FileTransfer
pm.addIQProvider("si", "http://jabber.org/protocol/si", new StreamInitiationProvider());
pm.addIQProvider("query", "http://jabber.org/protocol/bytestreams", new BytestreamsProvider());
// Privacy
pm.addIQProvider("query", "jabber:iq:privacy", new PrivacyProvider());
pm.addIQProvider("command", "http://jabber.org/protocol/commands", new AdHocCommandDataProvider());
pm.addExtensionProvider("malformed-action", "http://jabber.org/protocol/commands",
new AdHocCommandDataProvider.MalformedActionError());
pm.addExtensionProvider("bad-locale", "http://jabber.org/protocol/commands",
new AdHocCommandDataProvider.BadLocaleError());
pm.addExtensionProvider("bad-payload", "http://jabber.org/protocol/commands",
new AdHocCommandDataProvider.BadPayloadError());
pm.addExtensionProvider("bad-sessionid", "http://jabber.org/protocol/commands",
new AdHocCommandDataProvider.BadSessionIDError());
pm.addExtensionProvider("session-expired", "http://jabber.org/protocol/commands",
new AdHocCommandDataProvider.SessionExpiredError());
}
/**
* 获取链接
* @return
*/
public XMPPConnection getConnection(){
if (xmppConnection == null){
openConnection();
}
return xmppConnection;
}
/**
* 关闭链接
*/
public void colseConnection(){
if (xmppConnection != null && xmppConnection.isConnected()){
xmppConnection.disconnect();
xmppConnection = null;
}
}
/**
* 登陆的方法
* @param account 账号
* @param psw 密码
* @return
*/
public boolean login(String account,String psw){
//判断连接是否存在
if (getConnection() == null){
return false;
}
if (!getConnection().isAuthenticated() && getConnection().isConnected()){
try {
//登陆
getConnection().login(account,psw);
//登陆之后更改用户状态
Presence presence = new Presence(Presence.Type.available);
//设置用户在线
presence.setMode(Presence.Mode.available);
//向服务器发送状态
getConnection().sendPacket(presence);
//接收消息监听
ChatManager chatManager = getConnection().getChatManager();
chatManager.addChatListener(chatManagerListener);
return true;
} catch (XMPPException e) {
e.printStackTrace();
return false;
}
}
return false;
}
/**
* 聊天管理监听器
*/
private ChatManagerListener chatManagerListener = new ChatManagerListener(){
@Override
public void chatCreated(Chat chat, boolean b) {
chat.addMessageListener(new MessageListener() {
@Override
public void processMessage(Chat chat, Message message) {
//当消息内容为空时,直接反悔
if (TVUtil.isEmpty(message.getBody())){
return;
}
//当消息内容不可空时,通过接口回调的把消息内容传出去
if (xmppManagerCallback != null){
xmppManagerCallback.receiveMsg(message);
}
}
});
}
};
/**
* 注册用户
* 表示的是Info/Query(信息与查询),它为XMPP通信提供请求与响应机制。它与HTTP
* 协议的基本工作原理非常相似,允许获取和设置查询,与HTTP 的GET 和POST 动作类似。
* @return
*/
public IQ registered(String account, String psw){
if (getConnection() == null){
return null;
}
//设置注册所需要的信息
Registration registration = new Registration();
registration.setType(IQ.Type.SET);
registration.setTo(getConnection().getServiceName());
registration.setUsername(account);
registration.setPassword(psw);
//PacketFilter:包过滤类,过滤一些不用的包
PacketFilter filter = new AndFilter(new PacketIDFilter(registration.getPacketID()), new PacketTypeFilter(IQ.class));
PacketCollector collector = getConnection().createPacketCollector(filter);
// 向服务器端,发送注册Packet包,注意其中Registration是Packet的子类
getConnection().sendPacket(registration);
IQ result = (IQ) collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
collector.cancel(); //停止请求result
return result;
}
/**
* 退出登陆
*/
public void outLogin(){
if (getConnection() == null){
return;
}
//设置退出状态
Presence presence = new Presence(Presence.Type.unavailable);
//发送请求
getConnection().sendPacket(presence);
//关闭连接
colseConnection();
}
/**
* 获取用户信息
* @param user
* @return
*/
public VCard getUserInfo(String user){
VCard vCard = null;
try {
vCard = new VCard();
// 加入这句代码,解决No VCard for
ProviderManager.getInstance().addIQProvider("vCard", "vcard-temp", new VCardProvider());
if (user == null){
vCard.load(getConnection());
}else{
vCard.load(getConnection(), user + "@" + Constant.SERVER_NAME);
}
} catch (XMPPException e) {
e.printStackTrace();
}
return vCard;
}
/**
* 获取xmpp好友列表
* 注意:这里的User是在Xmpp包下的User
*/
public List<User> getFriendList() {
// Roster:花名册
if (roster == null) {
roster = getConnection().getRoster();
}
List<User> userList = new ArrayList<User>();
Collection<RosterEntry> entries = roster.getEntries();
for(RosterEntry entry : entries){
userList.add(new User(getUsername(entry.getUser()),entry.getType()));
}
Collections.sort(userList,new PingyinComparator());
return userList;
}
/**
* 通过jid获得username
* @param fullUsername
* @return
*/
public static String getUsername(String fullUsername){
return fullUsername.split("@")[0];
}
/**
* 搜索用户
* @param userName
* @return
* @throws XMPPException
*/
public List<String> searchUser(String userName) {
if (getConnection() == null){
return null;
}
List<String> userList = new ArrayList<>();
try {
UserSearchManager search = new UserSearchManager(getConnection());
Form searchForm = search.getSearchForm("search."+ getConnection().getServiceName());
Form answerForm = searchForm.createAnswerForm();
answerForm.setAnswer("Username", true);
answerForm.setAnswer("search", userName.trim());
ReportedData data = search.getSearchResults(answerForm,"search." + xmppConnection.getServiceName());
Iterator<ReportedData.Row> it = data.getRows();
ReportedData.Row row = null;
while (it.hasNext()) {
row = it.next();
userList.add(row.getValues("Username").next().toString());
}
} catch (XMPPException e) {
e.printStackTrace();
}
return userList;
}
/**
* 添加好友(无分组)
* @param userName
* @return
*/
public boolean addFriend(String userName) {
if (getConnection() == null)
return false;
try {
getConnection().getRoster().createEntry(getFullUsername(userName), getFullUsername(userName), null);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 通过username获得jid
* @param username
* @return
*/
public static String getFullUsername(String username){
return username + "@" + Constant.SERVER_NAME;
}
/**
* 创建聊天
* @param toUser
* @return
*/
public Chat createChat(String toUser){
ChatManager chatManager = getConnection().getChatManager();
Chat newchat = chatManager.createChat(toUser + "@"+ Constant.SERVER_NAME, null);
return newchat;
}
/**
* 发送文本消息
* @param message
*/
public void sendMsg(Chat chat, String message) {
try {
chat.sendMessage(message);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 接口回调
*/
public interface XmppManagerCallback {
//接收消息回调函数
void receiveMsg(Message message);
}
/**
* 设置接口的方法
* @param xmppManagerCallback 接口对象
*/
public void setXmppManagerCallback(XmppManagerCallback xmppManagerCallback) {
this.xmppManagerCallback = xmppManagerCallback;
}
}
这里面封装了所有的方法
ChatMsg.java
package com.example.xmppdemo.fengzhuang;
import android.os.Parcel;
import android.os.Parcelable;
/**
*
* 描述(请用一句话描述这个内容)
*/
public class ChatMsg implements Parcelable {
private String sender; // 发送者
private String body; // 发送的消息
public String getSender() {
return sender;
}
public void setSender(String sender) {
this.sender = sender;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public static final Creator<ChatMsg> CREATOR = new Creator<ChatMsg>() {
@Override
public ChatMsg createFromParcel(Parcel in) {
ChatMsg chatMsg = new ChatMsg();
chatMsg.sender = in.readString();
chatMsg.body = in.readString();
return chatMsg;
}
@Override
public ChatMsg[] newArray(int size) {
return null;
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeString(sender);
parcel.writeString(body);
}
}
还有一个
ChatService.java
package com.example.xmppdemo.service;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.support.annotation.Nullable;
import com.example.xmppdemo.ChatActivity;
import com.example.xmppdemo.R;
import com.example.xmppdemo.fengzhuang.ChatMsg;
import com.example.xmppdemo.fengzhuang.Constant;
import com.example.xmppdemo.fengzhuang.XmppManager;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smackx.OfflineMessageManager;
import java.util.ArrayList;
import java.util.Iterator;
/**
31 * 描述(请用一句话描述这个内容)
*/
public class ChatService extends Service implements XmppManager.XmppManagerCallback {
//接收到的消息集合,包括两种消息: 1,不在对话框界面的消息 2,离线消息
private ArrayList<ChatMsg> messageList = new ArrayList<>();
private MesageBroadcastReceiver mesageReceiver;
@Override
public void onCreate() {
XmppManager.getInstance().setXmppManagerCallback(this);
//注册消息接收广播
IntentFilter filter = new IntentFilter(Constant.INTENT_ACTION_MESSAGE_RECEIVE);
mesageReceiver = new MesageBroadcastReceiver();
registerReceiver(mesageReceiver, filter);
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void receiveMsg(Message message) {
ChatMsg chatMsg = new ChatMsg();
chatMsg.setSender(message.getFrom());
chatMsg.setBody(message.getBody());
sendReceiverMsgBroadCast(chatMsg);
}
/**
* 发送广播的方法
* @param
*/
private void sendReceiverMsgBroadCast(ChatMsg chatMsg){
Intent intent = new Intent();
intent.setAction(Constant.INTENT_ACTION_MESSAGE_RECEIVE);
intent.putExtra("message", chatMsg);
/**
* MesageBroadcastReceiver指定为最后的接受者,Activity.RESULT_CANCELED指定初始的结果码,
* 如果ChatActivity中的广播接收者处理了这条广播,则结果码会在ChatActivity中被更改为Activity.RESULT_OK,
* 反之,ChatActivity中的广播接收者没有处理,则结果码仍然为Activity.RESULT_CANCELED
*/
sendOrderedBroadcast(intent,null,mesageReceiver,null, Activity.RESULT_CANCELED,null,null);
}
/**
* 消息广播
*/
private class MesageBroadcastReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
ChatMsg chatMsg = intent.getParcelableExtra("message");
int resultCode = getResultCode();
if (isOrderedBroadcast()){ //判断是否有下一个广播,true为是 false为无
if (resultCode != Activity.RESULT_OK){
showMsgNotice(chatMsg);
}
}
}
}
/**
* 显示消息通知
* @param chatMsg 消息类
*/
private void showMsgNotice(ChatMsg chatMsg){
messageList.add(chatMsg); //把消息实体加入到集合中
//获取通知服务
NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
//取消所有
nm.cancelAll();
//创建消息
/* Notification notification = new Notification(R.drawable.ic_launcher
,"您有"+messageList.size()+"条新消息", System.currentTimeMillis());
notification.flags = Notification.FLAG_AUTO_CANCEL;
notification.sound= Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.ms);
Intent intent = new Intent(this, ChatActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("from", "notification");
intent.putParcelableArrayListExtra("messageList", messageList);
PendingIntent contentIntent = PendingIntent.getActivity(this, R.string.app_name, intent, PendingIntent.FLAG_UPDATE_CURRENT);
notification.setLatestEventInfo(this, chatMsg.getSender().split("@")[0], chatMsg.getBody(), contentIntent);
nm.notify(0, notification);*/
Notification.Builder builder = new Notification.Builder(this);
builder.setContentText("微信通知"); //设置通知的标题
builder.setSmallIcon(R.drawable.search_icon); //设置通知的小图标
builder.setContentText("您有"+messageList.size()+"条新消息"); //写入通知内容
// builder.setSound(Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.ms));
Intent intent = new Intent(this, ChatActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("from", "notification");
intent.putParcelableArrayListExtra("messageList", messageList);
PendingIntent contentIntent = PendingIntent.getActivity(this, R.string.app_name, intent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(contentIntent);
//获得通知
Notification notification = builder.getNotification();
nm.notify(0, notification);
}
/**
* 获取离线消息
*/
public void getOfflineMessage() {
OfflineMessageManager offlineMessageManager = new OfflineMessageManager(XmppManager.getInstance().getConnection());
try {
Iterator<Message> it = offlineMessageManager.getMessages();
while (it.hasNext()) {
Message message = it.next();
ChatMsg chatMsg = new ChatMsg();
chatMsg.setSender(message.getFrom());
chatMsg.setBody(message.getBody());
sendReceiverMsgBroadCast(chatMsg);
}
offlineMessageManager.deleteMessages();
} catch (XMPPException e) {
e.printStackTrace();
}
}
@Override
public void onDestroy() {
super.onDestroy();
XmppManager.getInstance().colseConnection();
unregisterReceiver(mesageReceiver);
}
}
基本重要的就这么多,代码附上,
链接:http://pan.baidu.com/s/1hs1Dg3M 密码:s57b
可能说的不是很清楚,但是代码里面都有
能看到的代码不是自己的,自己写出来的才是自己的