2013-06-13 3 views
2

Я использую aSmack в своем приложении для Android для связи с моим сервером XMPP, и я включил отладку для Smack, чтобы я мог видеть все входящие/исходящие XML. Моя проблема заключается в том, что я использую PacketListener, чтобы получить ответ сервера для отправленного мной пакета, но когда я вызываю метод toXML() пакета, я получил странный вывод.
Классы и более подробная информация ниже.aSmack - пакет в XML с использованием Packet Listener выводит элементы с нулевым значением

У моего сервера есть реализация XEP-0136, и поскольку у aSmack нет кода для него, я делаю пакет IQ и отправляю его, и это работает как ожидалось, как вы можете видеть ниже моего пакета XML, как она была задумана в XEP-0136, список коллекций (http://xmpp.org/extensions/xep-0136.html#manage-list)

Xml пакет, отправленный на сервер извлечения

06-13 14:11:21.769: D/SMACK(3018): 02:11:21 PM SENT (1079273464): 
<iq id="[email protected]/Smack/Conversations" type="get"> 
    <list with="[email protected]" xmlns="urn:xmpp:archive"> 
    <set xmlns="http://jabber.org/protocol/rsm"> 
     <max>30</max> 
    </set> 
    </list> 
</iq> 

чтобы создать этот XML я получил файлы XML-схемы, как разработанный в XEP- 0136, и с помощью SimpleXML lib я отобразил все элементы, и это th е код, я использую, чтобы создать и отправить пакет:

XMPPService.java

private static final int MAX_LIST = 30; 

public void getConversations(String email, BaseActivity activity) 
{ 
    if (isAuthenticated()) 
    { 
     String packetId = connection.getUser() + "/Conversations"; 
     Set set = new Set(); 
     set.setMax(MAX_LIST); 

     List list = new List(); 
     list.setWith(email); 
     list.setSet(set); 

     final IQ iq = new IQ(); 
     iq.setList(list); 
     iq.setType(IQType.get); 
     iq.setId(packetId); 

     PacketIDFilter filter = new PacketIDFilter(packetId); 
     connection.addPacketListener(new ChatListListener(activity), filter); 
     sendPacket(iq); 
    } 
} 

public void sendPacket(IQ iq) 
{ 
    if (isAuthenticated()) 
    { 
     connection.sendPacket(new IQPacket(iq)); 
    } 
} 

IQPacket.java

public class IQPacket extends Packet { 

private IQ iq; 

public IQPacket(IQ iq) 
{ 
    this.iq = iq; 
} 

public IQPacket(Packet packet, IQ iq) 
{ 
    super(packet); 
    this.iq = iq; 
} 

@Override 
public String toXML() 
{ 
    StringWriter writer = new StringWriter(); 
    Serializer serializer = new Persister(); 
    try 
    { 
     serializer.write(iq, writer); 
     return writer.getBuffer().toString(); 
    } catch (Exception e) 
    { 
     Log.e("COMPANY", "Error serializing xml", e); 
    } 
    return null; 
} 

} 

Как я уже сказал, эта часть работы, моя проблема для Listener, когда я вызываю метод toXML() для полученного пакета, я не могу получить важную информацию о чатах, но вывод отладки Smack выводит мне всю информацию, которую я выдаю тин, как вы можете увидеть ниже:

Смак Debug для полученного XML

06-13 14:11:21.989: D/SMACK(3018): 02:11:21 PM RCV (1079273464): 
<iq type="result" id="[email protected]/Smack/Conversations" to="[email protected]/Smack"> 
    <list xmlns="urn:xmpp:archive"> 
    <chat with="[email protected]" start="2013-06-10T13:19:25.000Z"/> 
    <chat with="[email protected]" start="2013-06-10T13:36:50.876Z"/> 
    <set xmlns="http://jabber.org/protocol/rsm"> 
     <first index="0">2</first> 
     <last>3</last> 
     <count>9</count> 
    </set> 
    </list> 
</iq> 

Кроме того, этот XML является ожидаемый ответ, так как у меня есть все те элементы, отображенные в JavaBeans, но это то, что я получаю, когда я получить пакет на моем ChatListener и вызвать метод ToXml():

06-13 14:11:22.009: I/System.out(3018): 
<iq id="[email protected]/Smack/Conversations" to="[email protected]/Smack" type="result">nullnullnullnullnullnull2nullnull3nullnull9nullnull</iq> 

ChatListListener.java

public class ChatListListener implements PacketListener { 

private BaseActivity activity; 

public ChatListListener(BaseActivity activity) 
{ 
    this.activity = activity; 
} 

@Override 
public void processPacket(Packet packet) 
{ 
    activity.notifyPacketReceived(); 
    System.out.println(packet.toXML()); 
} 
} 

Пакет от org.jivesoftware.smack.packet.Packet, так что Packet по умолчанию из Lib aSmack.

Так что мой вопрос в том, что я делаю другим отладчиком Smack? Я просмотрел его код и для того, что я видел, он также вызывает метод toXML() из пакета и добавляет ReceiveListener. Моя идея здесь после того, как я вызываю toXML() Я могу использовать SimpleXML, чтобы преобразовать его в свой IQ.java, который я сопоставил и начал использовать его информацию.

EDIT

Добавление дополнительной информации. Поэтому, посмотрев код Smack и как он обрабатывает полученный пакет, я выясню, что, возможно, мне следует использовать IQProvider. Я зарегистрировал IQProvider

ProviderManager.getInstance().addIQProvider("list", "urn:xmpp:archive", new ListIQProvider()); 

И после того, что я поставил точку останова на метод parseIQ (XmlPullParser arg0) моего IQProvider, и пакет на самом деле направляется к моему провайдеру, но все же он имеет все эти нулевые элементы. Прямо сейчас я добрый, потому что мне нужно, чтобы он продолжал работать, я буду продолжать изучать исходный код Smack.

ответ

4

После много исследований и поиска источников Smack я нашел решение. Шаги, добавьте IQProvider, добавьте PacketListener для вашего пакета, отправьте пакет. Подождите пакет на вашем IQProvider, проанализируйте его и получите ответ на свой прослушиватель.

Так addIQProvider и addPacketListener оба были правы, дело в том, что мне нужно сделать полный разбор в XML на моем ListIQProvider, это звучит просто, но мне потребовалось некоторое время, чтобы понять это.

public class ListIQProvider implements IQProvider { 

public ListIQProvider() 
{ 
} 

@Override 
public IQ parseIQ(XmlPullParser parser) throws Exception 
{ 
    Logger.d(String.format("Received iq packet, namespace[%s], name[%s]", parser.getNamespace(), parser.getName())); 
    ListIQ iq = new ListIQ(); 
    ListIQ.Set set = new Set(); 
    boolean done = false; 

    String with = "", start = ""; 
    while (!done) 
    { 
     int eventType = parser.next(); 
     if (eventType == XmlPullParser.START_TAG) 
     { 
      if (parser.getName().equals("chat")) 
      { 
       with = parser.getAttributeValue("", "with"); 
       start = parser.getAttributeValue("", "start"); 
       iq.addChat(new Chat(with, start)); 
      } 
      else if (parser.getName().equals("first")) 
      { 
       int index = parseInt(parser.getAttributeValue("", "index")); 
       set.setIndexAtt(index); 
       int first = parseInt(parser.nextText()); 
       set.setFirst(first); 
      } 
      else if (parser.getName().equals("last")) 
      { 
       int last = parseInt(parser.nextText()); 
       set.setLast(last); 
      } 
      else if (parser.getName().equals("count")) 
      { 
       int count = parseInt(parser.nextText()); 
       set.setCount(count); 
      } 
     } 
     else if (eventType == XmlPullParser.END_TAG) 
     { 
      if (parser.getName().equals("list")) 
      { 
       iq.setSet(set); 
       done = true; 
      } 
     } 
    } 

    return iq; 
} 

private int parseInt(String integer) 
{ 
    return Integer.parseInt((integer != null ? integer : "0")); 
} 
} 

После этого, все, что я должен был сделать на моем ChatListListener был заливка Packet моего класса ListIQ. Вот и все. Дело здесь есть, Packet поступают на мой ChatListListener тот же Packet, что возвращается на методе parseIQ на моем ListIQProvider. Итак, в этом вопросе/ответе у нас есть почти все, что вам нужно для XEP-0136, или, по крайней мере, начать использовать его. Поскольку я не нашел ни одного хорошего и простого источника в Интернете, чтобы помочь мне, я поделюсь с вами здесь. Ниже это класс ListIQ:

public class ListIQ extends IQ { 

private List<Chat> chats; 

private Set set; 

public ListIQ() 
{ 
    this.chats = new ArrayList<ListIQ.Chat>(); 
} 

public Set getSet() 
{ 
    return set; 
} 

public void setSet(Set set) 
{ 
    this.set = set; 
} 

public void addChat(Chat chat) 
{ 
    chats.add(chat); 
} 

public List<Chat> getChats() 
{ 
    return chats; 
} 

@Override 
public String getChildElementXML() 
{ 
    StringBuilder builder = new StringBuilder("<list xmlns=\"urn:xmpp:archive\">"); 
    for (Chat chat : chats) 
    { 
     builder.append(chat.toXml()); 
    } 
    builder.append(set.toXml()); 
    builder.append("</list>"); 
    return builder.toString(); 
} 

public static class Chat { 
    private String with; 
    private String start; 

    public Chat() 
    { 
    } 

    public Chat(String with, String start) 
    { 
     this.with = with; 
     this.start = start; 
    } 

    public String getWith() 
    { 
     return with; 
    } 

    public void setWith(String with) 
    { 
     this.with = with; 
    } 

    public String getStart() 
    { 
     return start; 
    } 

    public void setStart(String start) 
    { 
     this.start = start; 
    } 

    public String toXml() 
    { 
     StringBuilder builder = new StringBuilder("<chat with=\""); 
     builder.append(with).append("\""); 
     builder.append(" start=\""); 
     builder.append(start); 
     builder.append("\"/>"); 
     return builder.toString(); 
    } 

} 

public static class Set { 
    private int last; 
    private int count; 
    private int indexAtt; 
    private int first; 

    public Set() 
    { 
    } 

    public int getLast() 
    { 
     return last; 
    } 

    public void setLast(int last) 
    { 
     this.last = last; 
    } 

    public int getCount() 
    { 
     return count; 
    } 

    public void setCount(int count) 
    { 
     this.count = count; 
    } 

    public int getIndexAtt() 
    { 
     return indexAtt; 
    } 

    public void setIndexAtt(int indexAtt) 
    { 
     this.indexAtt = indexAtt; 
    } 

    public int getFirst() 
    { 
     return first; 
    } 

    public void setFirst(int first) 
    { 
     this.first = first; 
    } 

    public String toXml() 
    { 
     StringBuilder builder = new StringBuilder("<set xmlns=\"http://jabber.org/protocol/rsm\">"); 
     builder.append("<first index=\"").append(indexAtt).append("\">").append(first).append("</first>"); 
     builder.append("<last>").append(last).append("</last>"); 
     builder.append("<count>").append(count).append("</count>"); 
     builder.append("</set>"); 
     return builder.toString(); 
    } 
} 

} 
+0

вы можете ответить http://stackoverflow.com/questions/22566411/how-to-parse-a-customiq-in-asmack Я также сталкиваюсь с той же проблемой –

+0

Спасибо за полный источник, это именно то, что мне нужно. Именно поэтому люди предпочитают JSON сейчас или это просто ужасный дизайн? – sbaar

+0

Нет проблем. На самом деле у XEP есть хороший дизайн, это просто хлопотно реализовать его самостоятельно. Я не думаю, что JSON будет соответствовать требованиям XMPP, имеет смысл использовать XML, я думаю, а также протокол старше JSON. –

1

Привет я тоже была такая же проблема, и я могу сказать, что этот код работает, я бы просто изменить способ создания запроса для списка на сервере. (По крайней мере, на моем сервере)

final IQ iq = new IQ() 
    { 

     @Override public String getChildElementXML() 
     { 

      return "<list xmlns='urn:xmpp:archive'/>"; 

     } 
    }; 

    iq.setType(IQ.Type.GET); 

    PacketTypeFilter filter = new PacketTypeFilter(Packet.class); 


    connection.addPacketListener(new PacketListener() 
    { 
     @Override public void processPacket(Packet packet) 
     { 
      Log.i(TAG, packet.toXML()); 
     } 
    }, filter); 

    connection.sendPacket(iq); 

, как вы сказали, прежде чем она кажется довольно легко, но документация не совсем понятно, о том, как построить объект IQ. Я надеюсь, что это помогает.

+0

Но вы все равно не сможете разобрать ответ. Вы просто можете отправить запрос на получение чатов. –

+0

Конечно, нет, для обработки ответа вам необходимо зарегистрировать провайдера, как и вы. Я просто попытался сделать ваш пост немного лучше, но ваш код является важной частью, поэтому я разработал классы, которые простираются от IQProvider, чтобы разобрать чат (и сообщение) совершенно по-другому. Тем не менее я дал вам +1, потому что ваш пост очень помог мне. – pleonasmik

+0

Эй, я пробовал, но я получаю сообщение об ошибке 503 недоступно. <код ошибки => 503" type = "CANCEL"> Hardik