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

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

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

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

如何为 AVD 管理器创建自定义 Android 设备配置文件?

android如何为自定义的类传递参数?