我使用简单的类来实现这个功能:
package mypkg;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.StanzaListener;
import org.jivesoftware.smack.filter.StanzaFilter;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.Stanza;
import org.jivesoftware.smack.packet.XMPPError;
import org.jivesoftware.smack.provider.IntrospectionProvider;
import org.jivesoftware.smack.provider.ProviderManager;
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
public class XEP0363 implements StanzaListener{
private XMPPTCPConnection connection;
private String id;
private SlotGrantedListener listener;
static {
ProviderManager.addIQProvider("slot", "urn:xmpp:http:upload", new SlotIQProvider());
}
public static class SlotIQProvider extends IntrospectionProvider.IQIntrospectionProvider {
public SlotIQProvider() {
super(SlotIQ.class);
}
}
public static class SlotIQ extends IQ {
private String put;
private String get;
public SlotIQ() {
super("request", "urn:xmpp:http:upload");
}
public String getPut() {
return put;
}
public void setPut(String put) {
this.put = put;
}
public String getGet() {
return get;
}
public void setGet(String get) {
this.get = get;
}
@Override
protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) {
return null;
}
}
public interface SlotGrantedListener {
void slotGranted(String put, String get);
void slotDenied(String error);
}
public XEP0363(XMPPTCPConnection connection) {
this.connection = connection;
}
public void requestSlot(String to, final String fileName, final long fileSize, SlotGrantedListener listener)
throws SmackException.NotConnectedException {
this.listener = listener;
final IQ iq = new IQ("request", "urn:xmpp:http:upload") {
@Override
protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) {
xml.rightAngleBracket();
xml.element("filename", fileName);
xml.element("size", String.valueOf(fileSize));
return xml;
}
};
iq.setType(IQ.Type.get);
iq.setFrom(connection.getUser());
iq.setTo(to);
id = iq.getStanzaId();
connection.addAsyncStanzaListener(this, new StanzaFilter() {
@Override
public boolean accept(Stanza stanza) {
return id != null && id.equals(stanza.getStanzaId());
}
});
connection.sendStanza(iq);
}
@Override
public void processPacket(Stanza packet) throws SmackException.NotConnectedException {
connection.removeAsyncStanzaListener(this);
if (((IQ)packet).getType() != IQ.Type.error) {
SlotIQ slotIQ = (SlotIQ) packet;
listener.slotGranted(slotIQ.getPut(), slotIQ.getGet());
} else {
XMPPError error = packet.getError();
String errDesc = error.getDescriptiveText(null);
String errText = errDesc != null ? String.format("%s (%s)", errDesc, error.toString()) : error.toString();
listener.slotDenied(errText);
}
}
}
然后,创建一个实现了
SlotGrantedListener
接口的监听器,并调用
requestSlot()
方法:
XEP0363 fileUpload = new XEP0363(connection)
fileUpload.requestSlot("upload.myxmppdomain", "mypic.jpg", 12345, listener)
请注意,此类不是线程安全的。