Android aSmack - 如何为文件发送自定义消息扩展名?
Posted
技术标签:
【中文标题】Android aSmack - 如何为文件发送自定义消息扩展名?【英文标题】:Android aSmack - How to make custom message extension for file sending? 【发布时间】:2015-06-13 06:08:33 【问题描述】:我正在尝试为我的聊天应用程序实现离线文件扩展名。我正在使用 PacketExtension 和 EmbeddedExtensionProvider 添加和解析自定义扩展。我可以看到在发送消息时添加了值和标签,但在接收端这些不存在。我做错了什么?
发送消息:
<message id="224K2-7" to="testfirzan@sushant" type="chat">
<body>hi</body>
<custom xmlns="jabber2:x2:oob2">
<url>URL</url>
<desc>Description</desc>
</custom>
</message>
接收消息:
System.out(734): EmbeddedExtensionProvider
<message id="224K2-7" to="testfirzan@sushant" from="testsushant@sushant/Smack" type="chat">
<body>hi</body>
<custom xmlns="jabber2:x2:oob2"></custom>
</message>
File Extension description:(734): <custom xmlns="jabber2:x2:oob2"></custom>
数据包扩展和提供者管理器代码:
public class FileExtension implements PacketExtension
public static final String ELEMENT = "custom";
public static final String NAMESPACE = "jabber2:x2:oob2";
String description;
String url;
@Override
public String getElementName()
return "custom";
@Override
public String getNamespace()
return "jabber2:x2:oob2";
@Override
public String toXML()
StringBuilder builder = new StringBuilder();
builder.append("<" + getElementName() + " xmlns=\"" + getNamespace()
+ "\">");
if (url != null)
builder.append("<url>").append(url).append("</url>");
if (description != null)
builder.append("<desc>").append(description).append("</desc>");
builder.append("</" + getElementName() + ">");
return builder.toString();
public String getDescription()
return description;
public void setDescription(String description)
this.description = description;
public String getUrl()
return url;
public void setUrl(String imageUrl)
this.url = imageUrl;
public static class FileExtensionProvider extends EmbeddedExtensionProvider
@Override
protected PacketExtension createReturnExtension(String currentElement,
String currentNamespace, Map<String, String> attributeMap,
List<? extends PacketExtension> content)
System.out.println("EmbeddedExtensionProvider");
return new FileExtension();
注册提供商:
ProviderManager.getInstance().addExtensionProvider(
FileExtension.ELEMENT, FileExtension.NAMESPACE,
new FileExtension.FileExtensionProvider());
发送消息时:
FileExtension fileExt = new FileExtension("URL");
fileExt.setDescription("Description");
fileExt.setUrl("URL");
msg.addExtension(fileExt);
收到消息后:
FileExtension fileExt = (FileExtension) message
.getExtension("jabber2:x2:oob2");
Log.i("File Extension description:", fileExt.toXML());
【问题讨论】:
【参考方案1】:以下是使用 aSmack 制作自定义扩展的完整解决方案:
首先我必须创建 PacketExtension:
public class ExtensionFile implements PacketExtension
public static final String ELEMENT = "file";
public static final String NAMESPACE = "file:namespace";
private String fileURL;
private String fileSize;
@Override
public String getElementName()
return ELEMENT;
@Override
public String getNamespace()
return NAMESPACE;
@Override
public String toXML()
StringBuilder builder = new StringBuilder();
builder.append("<" + getElementName() + " xmlns=\"" + getNamespace()
+ "\">");
if (fileURL != null)
builder.append("<fileURL>").append(fileURL).append("</fileURL>");
if (fileSize != null)
builder.append("<fileSize>").append(fileSize).append("</fileSize>");
builder.append("</" + getElementName() + ">");
return builder.toString();
public void setFileURL(String fileURL)
this.fileURL = fileURL;
public String getFileURL()
return fileURL;
public void setFileSize(String fileSize)
this.fileSize = fileSize;
public String getFileSize()
return fileSize;
然后提供者解析这个数据包:
public class ExtensionProviderFile implements PacketExtensionProvider
@Override
public PacketExtension parseExtension(XmlPullParser parser)
throws Exception
ExtensionFile fileExt = new ExtensionFile();
int eventType = parser.next();
while (eventType == XmlPullParser.START_TAG)
String name = parser.getName();
switch (parser.getEventType())
case XmlPullParser.START_TAG:
if (name.equals("fileURL"))
fileExt.setFileURL(parser.nextText());
else if (name.equals("fileSize"))
fileExt.setFileSize(parser.nextText());
eventType = parser.next();
return fileExt;
发送带有文件扩展名的消息:
private void sendMessage(String recipient, String message)
Message msg = new Message(recipient,Message.Type.chat);
msg.setBody(message);
//Create extension and set values
ExtensionFile fileExt = new ExtensionFile();
fileExt.setFileURL("http://www.example.com/upload_files/"+ abc.jpg);
fileExt.setFileSize(fileSize);
//add extension to message
msg.addExtension(fileExt);
//send message
xmppConnection.sendPacket(msg);
要接收此消息,请实现 PacketListener
并覆盖 processPacket()
:
@Override
public void processPacket(Packet packet)
Message message = (Message) packet;
//Get extension from message
ExtensionFile extFile = (ExtensionFile) message
.getExtension("file:namespace");
if (extFile != null)
//Get values from extension
String filePath = extFile.getFileURL();
String fileSize = extFile.getFileSize();
System.out.println("Message :" + message.getBody() + " File url:" + filePath + " File size:" + fileSize);
并在连接到 xmpp 服务器之前添加此提供:
ProviderManager.getInstance().addExtensionProvider(
ExtensionFile.ELEMENT, ExtensionFile.NAMESPACE,
new ExtensionProviderFile());
【讨论】:
需要在 toXml() 方法中对 XML 进行转义。 @Flow 不一定需要。toXml()
可用于查看 xml 格式的消息。 ProviderManager
解析 ExtensionFile
。
您必须始终为 XML 转义字符串。例如 fileURL 可能包含需要转义的字符。
@Flow 我认为这就是 ExtensionProviderFile
在这种情况下所做的。
不,提供者负责反序列化。 toXml() 序列化一个节。【参考方案2】:
在最新版本的 Smack 4.1.7 中,删除了 PacketExtensionProvider (see this)。所以 ExtensionProviderFile 可以在扩展 ExtensionElementProvider 之后创建。请检查以下代码 -
public class ExtensionProviderFile extends ExtensionElementProvider
@Override
public Element parse(XmlPullParser parser, int initialDepth) throws XmlPullParserException, IOException, SmackException
ChatExtension extensionFile = new ChatExtension();
int eventType = parser.next();
while (eventType == XmlPullParser.START_TAG)
String name = parser.getName();
switch (parser.getEventType())
case XmlPullParser.START_TAG:
if (name.equals("fileName"))
extensionFile.setFileName(parser.nextText());
else if (name.equals("fullName"))
extensionFile.setFullName(parser.nextText());
eventType = parser.next();
return extensionFile;
希望这会对某人有所帮助。
【讨论】:
以上是关于Android aSmack - 如何为文件发送自定义消息扩展名?的主要内容,如果未能解决你的问题,请参考以下文章
在 Android 上使用 aSmack 发送和接收自定义 XMPP IQ