关键词:
在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=‘[email protected]/B‘ to=‘[email protected]/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("[email protected]/B");//设置IQ结from
packet.setTo("[email protected]/s2");//设置IQ结to
xmppConnection.sendPacket(packet);//发送消息包
2、解析服务器返回的iq消息包,消息包中含自定义xml结。
例如解析服务器返回的这样一个iq消息:
<iq id=‘12‘ type=‘result‘ from=‘[email protected]/s2‘ to=‘[email protected]/B‘><resp xmlns=‘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。
- 写一个类继承IQ并重写
- 如果需还需要实现一些自定义的解析,可以修改asmack源码中的
PacketParserUtils
这个类中对应的方法。
下面是源码地址:
点击:下载地址
在 Android 中实现自定义 ListView
】在Android中实现自定义ListView【英文标题】:ImplementacustomListViewinAndroid【发布时间】:2016-10-2802:16:18【问题描述】:我在我的MainActivity中创建了一个listView,并为行布局创建了另一个布局文件,如下所示:问题是,我该如何实现... 查看详情
android中实现自定义的拍照应用
可以参考:http://www.android-doc.com/guide/topics/media/camera.html一、添加相应的权限<uses-permissionandroid:name="android.permission.CAMERA"/><uses-featureandroid:name="android.hardware.camera"/><!- 查看详情
如何在android中实现自定义可折叠工具栏?
】如何在android中实现自定义可折叠工具栏?【英文标题】:HowtoimplementCustomCollapsableToolbarinandroid?【发布时间】:2015-11-2212:08:36【问题描述】:使用thistutorial实现灵活空间模式(带有折叠工具栏的模式)。我正在尝试实现与Lollipop... 查看详情
在spring boot中实现自定义错误
】在springboot中实现自定义错误【英文标题】:Implementthecustomerrorinspringboot【发布时间】:2019-04-0702:58:26【问题描述】:我想页面。在应用程序中,id是主键,所以当没有给出id时,它会将请求传输到页面,但我希望应用程序在索... 查看详情
在 Gradle Android 中实现自定义库时未解析类
】在GradleAndroid中实现自定义库时未解析类【英文标题】:ClassnotresolvedwhenimplementingcustomlibraryinGradleAndroid【发布时间】:2022-01-0201:32:22【问题描述】:我创建了一个android库并在Jitpack中发布。目前,我的构建在Jitpack中取得了成功... 查看详情
在 MembershipProvider 中实现自定义“ValidateUser”
】在MembershipProvider中实现自定义“ValidateUser”【英文标题】:Implementcustom"ValidateUser"inMembershipProvider【发布时间】:2011-03-2510:32:38【问题描述】:我正在实现一个自定义MembershipProvider,我正在尝试使用ValidateUser方法来验证... 查看详情
如何在 keras 中实现自定义指标?
】如何在keras中实现自定义指标?【英文标题】:howtoimplementcustommetricinkeras?【发布时间】:2016-10-0601:13:54【问题描述】:我得到这个错误:sum()得到了一个意外的关键字参数\'out\'当我运行这段代码时:importpandasaspd,numpyasnpimportkera... 查看详情
如何在 iPhone 中实现自定义相机功能? [关闭]
】如何在iPhone中实现自定义相机功能?[关闭]【英文标题】:HowtoimplementcustomcamerafunctionalityiniPhone?[closed]【发布时间】:2011-08-1605:07:13【问题描述】:我想开发一种功能,以便在iPhone应用程序中实现自定义相机功能,所以请给我... 查看详情
在具有条件的 keras 中实现自定义损失函数
】在具有条件的keras中实现自定义损失函数【英文标题】:Implementingcustomlossfunctioninkeraswithcondition【发布时间】:2018-12-0813:49:59【问题描述】:我需要一些有关keras损失函数的帮助。我一直在使用Tensorflow后端在keras上实现自定义损... 查看详情
在 Freemarker 中实现自定义 Escaper
】在Freemarker中实现自定义Escaper【英文标题】:ImplementaCustomEscaperinFreemarker【发布时间】:2010-11-0920:21:59【问题描述】:Freemarker可以使用以下方式进行文本转义:<#escapexasx?html>Foo:$someValBar:$someOtherVal</#escape>xml、xhtml和html... 查看详情
为啥不推荐使用 JScript 在 WiX 中实现自定义操作?
】为啥不推荐使用JScript在WiX中实现自定义操作?【英文标题】:WhyisusingJScriptforimplementingcustomactionsinWiXnotrecommended?为什么不推荐使用JScript在WiX中实现自定义操作?【发布时间】:2013-07-1008:19:33【问题描述】:在浏览有关WiX的文... 查看详情
如何在canvas中实现自定义路径动画(代码片段)
在最近的项目中笔者需要做一个新需求:在canvas中实现自定义的路径动画。这里所谓的自定义路径不单单包括一条直线,也许是多条直线的运动组合,甚至还包含了贝塞尔曲线,因此,这个动画也许是下面这个样子的:那么如何... 查看详情
具有自定义元素或属性的 Tigase-XMPP 消息包
】具有自定义元素或属性的Tigase-XMPP消息包【英文标题】:Tigase-XMPPMessagePacketwithCustomElementsorAttributes【发布时间】:2014-03-1114:40:04【问题描述】:<messagexmlns="jabber:client"to="5410037:testingmine@muc.app.smsall.pk"type="groupchat"from="54100 查看详情
在 kvm 中实现自定义超级调用
】在kvm中实现自定义超级调用【英文标题】:Implementingacustomhypercallinkvm【发布时间】:2016-02-0900:28:27【问题描述】:我对虚拟化非常陌生,最近我一直在尝试熟悉VMM的操作方式以及如何进行超级调用。谈到我打算在安装在我的Ubu... 查看详情
如何在黄瓜中实现自定义监听器?
】如何在黄瓜中实现自定义监听器?【英文标题】:Howtoimplementcustomlistenersincucumber?【发布时间】:2021-12-2214:55:47【问题描述】:如何在cucumber中实现客户监听?哪个可以记录到控制台/报告失败方法的发生?使用黄瓜4.0注意:钩... 查看详情
在 SDK 中实现自定义取消按钮
】在SDK中实现自定义取消按钮【英文标题】:ImplementcustomCancelButtoninaSDK【发布时间】:2015-11-0917:24:08【问题描述】:我想用paysbuySDK实现支付功能....问题是它没有任何cancel选项,以便用户可以在支付成功后取消关闭操作。默认情... 查看详情
如何在 UIImagePicker 中实现自定义“使用”和“重拍”按钮?
】如何在UIImagePicker中实现自定义“使用”和“重拍”按钮?【英文标题】:Howtoimplementcustom\'Use\'and\'Retake\'buttoninUIImagePicker?【发布时间】:2011-03-2507:06:04【问题描述】:我的意思是,我已经关闭了相机控制器pickerCam.showsCameraContro... 查看详情
如何在自定义 Spring 存储库中实现自定义方法? [复制]
】如何在自定义Spring存储库中实现自定义方法?[复制]【英文标题】:Howtoimplementcustommethodincustomspringrepository?[duplicate]【发布时间】:2016-03-2719:36:21【问题描述】:假设我想要一个方法,获取超级主客户,有id=0。我有客户类:@Ent... 查看详情