Android中实现自定义XMPP消息包收发

在Android平台实现XMPP即时通讯主要是使用asmack这个包,asmack是XMPP协议的实现。但是asmack只能帮助我们实现一些基本消息包的收发,如果需要实现特定的自定义消息包收发需要我们自己处理。


一、asmack消息的发送和接收

  • 发送Message消息:

发送一个message结的消息,可以使用sendMessage()发送消息,这个方法有两个重载方法,一种类型的参数是String类型,另一种则是传入Message对象。String类型的方法传入的字符串即为要发送的消息;传入message对象的方需要写一个类继承Message,重写toXML()方法,toXML()方法的返回值即为要发送的消息。例如:


    //1、通过传入String类型的sendMessage()方法发送消息:

    ChatManager chatManager = xmppConnection.getChatManager();
     /**
            * String userJID 对方的JID
         * MessageListener listener 消息监听,当收到消息后会回调processMessage(Chat chat, Message message)方法
         */
    Chat mChat = chatManager.createChat(mToUser, this);
    mChat.sendMessage("your content");
    //2、通过传入Message对象的sendMessage()方法发送消息:

    /**
    *写一个类继承Message重写toXML()方法,方法的返回值即为要发送的消息
    */
    public class MyMessage extends Message {
        
         @Override
        public String toXML() {
            
            return "your content";
        }
    
    }

    ChatManager chatManager = xmppConnection.getChatManager();
     /**
            * String userJID 对方的JID
         * MessageListener listener 消息监听,当收到消息后会回调processMessage(Chat chat, Message message)方法
         */
    Chat mChat = chatManager.createChat(mToUser, this);
    MyMessage myMessage = new MyMessage();
    mChat.sendMessage(myMessage);

  • 接收Message消息:

接收Message类型的消息主要是在processMessage(Chat chat, Message message)方法中,当收到消息后都会回调这个方法,需要实现MessageListener这个接口,然后实现接口中的processMessage(Chat chat, Message message)方法。


二、发送和接收自定义类型的IQ结消息

当发送的iq消息中包含自定义的xml结的时候,asmack提供的解析并不能识别这些自定义的xml结,所以就需要我们自己实现消息包的解析和拼装。

1、发送含自定义xml结的iq消息。
例如发送这样一个iq消息:<iq id='123' type='get' from='client@xmpp/B' to='client2@xmpp/s2'><req var='read'><attr var='temprature'/></req></iq>

    //步骤:
    //1、写一个类继承IQ并重写getChildElementXML()方法,该方法的返回值将作为消息体。
    public class MyIQ extends IQ {
        @Override
        public String getChildElementXML() {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append("<req var='read'>< attr var='temprature'/></req>");
            return stringBuilder.toString();
        }
    }
    //2、发送这个含自定义xml结的iq消息包
    MyIQ packet = new MyIQ();
    packet.setType(IQ.Type.GET);//设置IQ结type
        packet.setFrom("client@xmpp/B");//设置IQ结from
        packet.setTo("client2@xmpp/s2");//设置IQ结to
        xmppConnection.sendPacket(packet);//发送消息包

2、解析服务器返回的iq消息包,消息包中含自定义xml结。
例如解析服务器返回的这样一个iq消息:<iq id='12' type='result' from='client2@xmpp/s2'to='client@xmpp/B'><respxmlns='data'><attr var='temprature'>17</attr></resp></iq>


    //步骤:
    //1、写一个类 implements PacketListener接口并实现其中的processPacket(Packet packet)方法。
    public class MyPacketListener implements PacketListener {
         @Override
        public void processPacket(Packet packet) {
            //当收到消息包就会回调该方法
        }
    }
    //2、添加包监听器
    MyPacketListener mMyPacketListener = new MyPacketListener();
    //该方法有两个参数
    //第一个参数:    PacketListener  包监听器
    //第二个参数:   PacketFilter  包过滤器
    xmppConnection.addPacketListener(mMyPacketListener, null);
    //完成以上两步后,当收到消息包都会回调MyPacketListener中的processPacket(Packet packet)方法。
    //3、写一个类继承IQ并实现getChildElementXML()方法。
    public class GetDataResp extends IQ {
        //例如我们要获取上面iq消息包中的temprature和17两个属性,所以将这两个值声明为成员变量,并生成get和set方法。
        public String var;
        public String value;
        public String getVar() {return var;}
        public void setVar(String var) {this.var = var;}
        public String getValue() {return value;}
        public void setValue(String value) {his.value = value;}
        @Override
        public String getChildElementXML(){
            //拼装消息
            StringBuilder buf = new StringBuilder();
            buf.append("<resp xmlns='get:data'><attr var='");
    ·        buf.append(getVar());
            buf.append("'>");
            buf.append(getValue());
            buf.append("</attr></resp>");
            return buf.toString();
        }
    }
    //4、写一个类implements IQProvider并实现接口中的parseIQ(XmlPullParser parser)方法。
    public class GetDataRespProvider implements IQProvider {
        @Override
        public IQ parseIQ(XmlPullParser parser) throws Exception {
            GetDataResp getDataResp = new GetDataResp();//这个对象是上面第三步中的那个类对象
            boolean done = false;
            while (!done) {
                int eventType = parser.next();
                if (eventType == XmlPullParser.START_TAG) {
                    if (parser.getName().equals("attr")) {
                        String var = parser.getAttributeValue("", "var");//获取var属性的value即:temprature
                        String value = parser.nextText();//获取attr的文本即:17
                        getDataResp.setVar(var);
                        getDataResp.setValue(value);
                    }
                }else if (eventType == XmlPullParser.END_TAG) {
                    if (parser.getName().equals("resp")) {
                        done = true;
                    }
                }
            }
             return getDataResp;
        }
    }
    //5、在配置ConnectionConfiguration时添加IQProvider
    //第一个参数是:String 元素的名称
    //第二个参数是:String  命名空间
    //第三个参数是:Object  需要传入一个prvider对象
    ProviderManager.getInstance().addIQProvider("resp", "data", new GetDataRespProvider());
    //6、在第一步MyPacketListener中的processPacket(Packet packet)方法中获取相应消息包
    public class MyPacketListener implements PacketListener {
         @Override
        public void processPacket(Packet packet) {
            if (packet instanceof GetDataResp) {
                GetDataResp getDataResp = (GetDataResp) packet;
                String from = getDataResp.getFrom();
                String to = getDataResp.getTo();
                String var = getDataResp.getVar();
                String value = getDataResp.getValue();
            }
        }
    }

三、总结

  • 发送message类型的消息中如果带有自定义xml结,需要写一个类继承Message并重写toXML()方法,该方法的返回值便是消息体。
  • 发送的iq类型的消息中如果带有自定义xml结,需要写一个类继承IQ并重写getChildElementXML()方法,该方法的返回值将作为消息体
  • 服务器返回的iq消息类型中如果带有自定义的xml结:
    • 写一个类继承IQ并重写getChildElementXML()方法,将服务器返回的消息中需要的信息做成成员变量,并拼装出消息体,最后作为返回值返回。
    • 写一个类implements IQProvider并实现接口中的parseIQ(XmlPullParser parser)方法,然后在该方法中做出对应的解析过程,最后通过返回值返回上一个步骤中的IQ对象。
    • 服务器返回的iq消息中的消息体必须带有命名空间。
    • 需要通过这个方法ProviderManager.getInstance().addIQProvider("resp", "data", new GetDataRespProvider());添加相应的IQProvider。
  • 如果需还需要实现一些自定义的解析,可以修改asmack源码中的PacketParserUtils这个类中对应的方法。

源码下载地址

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,050评论 25 707
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,497评论 18 139
  • 一、Smack库概述     Smack是一个开源、易用的XMPP/Jabber客户端库,它使用Java语言开发,...
    AndryYu阅读 5,935评论 2 13
  • 关于XMPP最权威的讲解:http://www.jabbercn.org/RFC3920(这个才是最权威的,下面文...
    随风飘荡的小逗逼阅读 1,451评论 1 5
  • 161211 每天早上睁眼的时候,若是看到窗帘的缝隙中透出湛蓝,就会觉得清爽无比。 经过昨晚的纠结,还是决定做一个...
    XxXxXxN阅读 212评论 0 0