2013-06-28 20 views
5

Sto usando asmack l'ultima versione (asmack-android-8-source-0.8.3) in un progetto Android e Ho il seguente codice :(a) Smack's IQ.toXml() restituisce XML senza elementi figlio personalizzati

connection.addPacketListener(new PacketListener() 
{ 
    @Override 
    public void processPacket(Packet p) 
    { 
     if(p.getPacketID().equals("v3")) 
     { 
      Log.e("TAG", p.toXML()); 
     } 
    } 
}, new IQTypeFilter(IQ.Type.RESULT)); 


Packet iq = new Packet() 
{ 
    @Override 
    public String toXML() 
    { 
     String str = "<iq type='get' id='v3'><getservertime xmlns='urn:xmpp:mrpresence'/></iq>"; 
     Log.e("TAG", str); 
     return str; 
    } 
}; 

//sends <iq type='get' id='v3'><getservertime xmlns='urn:xmpp:mrpresence'/></iq> 
connection.sendPacket(iq); 

nel debugger risposta è ok e questo è previsto:

<iq type="result" id="v3" to="[email protected]/Smack"> 
    <servertime xmlns="urn:xmpp:mrpresence" utc="2013-06-28T11:45:32.380Z" local="2013-06-28T07:45:32.380Z"/> 
</iq> 

ma p.toXML() in The Listener pacchetto, la "DB" tag che manca:

<iq id="v3" to="[email protected]/Smack" type="result"></iq> 

Qualche suggerimento su cosa sto facendo male?

risposta

3

<servertime/> è un elemento figlio personalizzato, che non è noto per Smack. Viene semplicemente ignorato durante l'analisi della stanza. Devi rendere Smack consapevole dell'elemento creando un nuovo PacketExtension che deve essere registrato con lo ProviderManager.

È possibile leggere maggiori informazioni nella documentazione di Smack relativa allo Provider Architecture.

+0

Ho aggiunto un PacketExtensionProvider con ProviderManager.getInstance(). AddExtensionProvider (packetExtensionProvider) come in questo tutorial: http://oneminutedistraction.wordpress.com/2010/08/31/receiving-pep-broadcast-2/ ma il mio PacketExtensionProvider non viene mai chiamato. Uso ancora connection.addPacketListener()? Grazie. –

+0

Ho anche guardato questo codice sorgente: github.com/rummble/jfexmpp e questo un github.com/redsolution/xabber-android ma senza successo :( –

+0

@Flow puoi approfondire come creare un nuovo PacketExtension e registrarlo con ProviderManager. – Sushant

3

ho risolto questo problema estendendo IQ e IQProvider classi:

ServerTime_IQProvider.java

public class ServerTime_IQProvider implements IQProvider 
{ 
    public static final String NAMESPACE = "urn:xmpp:mrpresence"; 
    public static final String ELEMENT_NAME = "servertime"; 
    public static final String UTC = "utc"; 
    public static final String LOCAL = "local"; 
    private Map<String, String> list = new HashMap<String, String>(); 

    @Override 
    public IQ parseIQ(XmlPullParser parser) throws Exception 
    { 
     boolean stop = false; 
     String name = parser.getName(); 

     while(false == stop) 
     { 
      switch (parser.getEventType()) 
      { 
       case XmlPullParser.START_TAG: 
       { 
        if(ELEMENT_NAME.equals(name)) 
        { 
         list.put(UTC, parser.getAttributeValue("", UTC)); 
         list.put(LOCAL, parser.getAttributeValue("", LOCAL)); 
        } 

        break; 
       } 
       case XmlPullParser.END_TAG: 
       { 
        stop = ELEMENT_NAME.equals(name); 
        break; 
       } 
      } 
     } 

     name = null; 
     return new ServerTime_IQ(list); 
    } 
} 

ServerTime_IQ.java

public class ServerTime_IQ extends IQ 
{ 
    public static final String ID = "servertime"; 
    private Map<String, String> list; 

    public ServerTime_IQ(Map<String, String> l) 
    { 
     list = l; 
    } 

    @Override 
    public String getChildElementXML() 
    { 
     return null; 
    } 

    public String getServerTime_UTC() 
    { 
     return list.get(ServerTime_IQProvider.UTC); 
    } 

    public String getServerTime_Local() 
    { 
     return list.get(ServerTime_IQProvider.LOCAL); 
    } 
} 

Poi ho aggiunto il provider di DB alla lista del IQProvider:

ProviderManager.getInstance().addIQProvider(ServerTime_IQProvider.ELEMENT_NAME, ServerTime_IQProvider.NAMESPACE, new ServerTime_IQProvider()); 

questo assicurerà che la risposta xml dal server verrà analizzata con il mio parser personalizzato (ServerTime_IQProvider) che è a conoscenza dei tag personalizzati e non con il parser predefinito di asmack.

2

questo funziona per me

ServerTime_IQProvider.class

public class ServerTime_IQProvider implements IQProvider{ 
    public static final String NAMESPACE = "urn:xmpp:mrpresence"; 
    public static final String ELEMENT_NAME = "servertime"; 
    public static final String UTC = "utc"; 
    public static final String LOCAL = "local"; 
    private Map<String, String> list = new HashMap<String, String>(); 

    @Override 
    public IQ parseIQ(XmlPullParser parser) throws Exception 
    { 
     boolean stop = false; 
     String name = parser.getName(); 

     while(false == stop) 
     { 
      int i = parser.getEventType(); 

      switch (i) 
      { 
      case XmlPullParser.START_TAG: 
      { 
       if(ELEMENT_NAME.equals(name)) 
       { 
        list.put(UTC, parser.getAttributeValue("", UTC)); 
        list.put(LOCAL, parser.getAttributeValue("", LOCAL)); 
       } 
       parser.next(); 

       break; 
      } 
      case XmlPullParser.END_TAG: 
      { 
       stop = ELEMENT_NAME.equals(name); 
       break; 
      } 
      } 
     } 

     name = null; 
     return new ServerTime_IQ(list); 
    } 
} 

WebServiceIQ.class

public class ServerTime_IQ extends IQ{ 
    public static final String ID = "servertime"; 
    private Map<String, String> list; 

    public ServerTime_IQ(Map<String, String> l) 
    { 
     list = l; 
    } 

    @Override 
    public String getChildElementXML() 
    { 
     StringBuilder builder = new StringBuilder("<"+ServerTime_IQProvider.ELEMENT_NAME+" xmlns=\""+ServerTime_IQProvider.NAMESPACE+"\" "); 
     builder.append(ServerTime_IQProvider.UTC+"=\""+getServerTime_UTC()+"\" "); 
     builder.append(ServerTime_IQProvider.LOCAL+"=\""+getServerTime_Local()+"\" "); 
     builder.append("/>"); 
     return builder.toString(); 
    } 

    public String getServerTime_UTC() 
    { 
     return list.get(ServerTime_IQProvider.UTC); 
    } 

    public String getServerTime_Local() 
    { 
     return list.get(ServerTime_IQProvider.LOCAL); 
    } 
} 

quindi aggiungere il provider di DB alla lista del IQProvider

ProviderManager.addIQProvider(ServerTime_IQProvider.ELEMENT_NAME,ServerTime_IQProvider.NAMESPACE, new ServerTime_IQProvider()); 

Packet filter per ServerTime_IQ pacchetto

connection.addPacketListener(new PacketListener() { 
     @Override 
     public void processPacket(Packet packet) { 
      System.out.println("################# Custom packet received"); 

      ServerTime_IQ IQ = (ServerTime_IQ)packet; 
      //Do your stuff 

     } 
    }, new PacketTypeFilter(ServerTime_IQ.class)); 

Questa è la prima risposta presentate da me qui, Anziani si prega di fare modifiche, se necessario.