zoukankan      html  css  js  c++  java
  • 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 = 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

    可能说的不是很清楚,但是代码里面都有

  • 相关阅读:
    UVA-1623 Enter The Dragon (贪心)
    UVA-1619 Feel Good (单调队列)
    UVA-11536 Smallest Sub-Array
    UVA-1617 Laptop (贪心)
    UVA-10570 Meeting with Aliens (枚举+贪心)
    UVA-1153 Keep the Customer Satisfied (贪心)
    UVA-1614 Hell on the Markets(贪心+推理) (有待补充)
    UVA-1613 K-Graph Oddity (着色问题)
    UVA-1612 Guess (贪心)
    todo:open和fopen的区别
  • 原文地址:https://www.cnblogs.com/langfei8818/p/6180724.html
Copyright © 2011-2022 走看看