After further testing, found that the problem is due to a call in aTalk VcardAvatarManager to addExtension to the stanza <presence>
Below are the source extractions of the aTalk/Smack (with added debug info) to find the root cause.
============== aTalk VcardAvatarManager =============
/**
* Creates a filter to only listen to presence stanza with the element name "x" but without the
* namespace "vcard-temp:x:update".
*/
private static final StanzaFilter PRESENCES_WITHOUT_VCARD
= new AndFilter(PresenceTypeFilter.AVAILABLE, new NotFilter(new StanzaExtensionFilter(ELEMENT, NAMESPACE)));
connection.addStanzaInterceptor(this, PRESENCES_WITHOUT_VCARD);
/**
* Intercepts sent presence packets in order to add VCardTempXUpdate extension.
*
* @param stanza The sent presence packet.
*/
@Override
public void processStanza(Stanza stanza)
{
// Do not add an elementExtension without hash value
if (vCardTempXUpdate.getAvatarHash() != null) {
LOGGER.warning("Stanza EE before add: " + stanza.toXML() + "\n" + stanza.getExtensions()
+ "\n" + vCardTempXUpdate.toXML());
stanza.addExtension(vCardTempXUpdate);
LOGGER.warning("New Stanza EE after add: " + stanza.toXML() + "\n" + stanza.getExtensions());
}
}
============== smack XmlStringBuilder ===============
/**
* Write the contents of this <code>XmlStringBuilder</code> to a {@link Writer}. This will write
* the single parts one-by-one, avoiding allocation of a big continuous memory block holding the
* XmlStringBuilder contents.
*
* @param writer
* @throws IOException
*/
public void write(Writer writer, String enclosingNamespace) throws IOException {
for (CharSequence csq : sb.getAsList()) {
if (csq instanceof XmlStringBuilder) {
((XmlStringBuilder) csq).write(writer, enclosingNamespace);
}
else if (csq instanceof XmlNsAttribute) {
XmlNsAttribute xmlNsAttribute = (XmlNsAttribute) csq;
if (!xmlNsAttribute.value.equals(enclosingNamespace)) {
writer.write(xmlNsAttribute.toString());
enclosingNamespace = xmlNsAttribute.value;
}
}
else if (csq == null)
LOGGER.warning("Stanza contains null: " + sb.getAsList());
else {
writer.write(csq.toString());
}
}
}
Following is the debug log captured. It is found that statement below actually added a “null” instead of the desired extension i.e. vCardTempXUpdate. Look like this problem only happen in the latest release of the smack source (believe smack now uses CharSequence toXML(XmlEnvironment xmlEnvironment - will change aTalk source) i.e. presently return null form aTalk, instead of the toXml()); the previous release did not cause the null reference exceptions to be thrown.
While testing, I also found that it is not necessary for aTalk to add the CardTempXUpdate elementExtension; it seems that the ejabberd server has implementation that will automatically add CardTempXUpdate to the <presence> stanza sending to all the contacts. Will remove the addExtension from aTalk.
!!!new!!!: Just confirmed new smack release call the method below. No more problem after aTalk source changes to implement the method instead of return null.
public CharSequence toXML(XmlEnvironment xmlEnvironment)
Not sure if smack will consider to check csq for null before writer.write(csq.toString());
stanza.addExtension(vCardTempXUpdate);
2019-02-09 10:01:27.322 18641-19267/org.atalk.android W/aTalk: [3793] org.jivesoftware.smackx.avatar.vcardavatar.VCardAvatarManager.processStanza() Stanza EE before add: <presence xmlns='jabber:client' id='9caj4-96'><status/><priority>30</priority><c xmlns='http://jabber.org/protocol/caps' hash='sha-1' node='http://android.atalk.org' ver='SPANeHrMhKxipyDRRXFZu1T21So='/></presence>
[org.jivesoftware.smackx.caps.packet.CapsExtension@9547c26]
<x xmlns='vcard-temp:x:update'><photo>1bfa4a6e285b3f609ddeeb7c95de851dcf3eb56c</photo></x>
2019-02-09 10:01:27.325 18641-19267/org.atalk.android E/aTalk: [3793] org.jivesoftware.smack.util.LazyStringBuilder.length() The following LazyStringBuilder threw a NullPointerException: <presence xmlns='jabber:client' id='9caj4-96'><status/><priority>30</priority><c xmlns='http://jabber.org/protocol/caps' hash='sha-1' node='http://android.atalk.org' ver='SPANeHrMhKxipyDRRXFZu1T21So='/>null</presence>
java.lang.NullPointerException: Attempt to invoke interface method 'int java.lang.CharSequence.length()' on a null object reference
at org.jivesoftware.smack.util.LazyStringBuilder.length(LazyStringBuilder.java:78)
at org.jivesoftware.smack.util.LazyStringBuilder.toString(LazyStringBuilder.java:112)
at org.jivesoftware.smack.util.XmlStringBuilder.toString(XmlStringBuilder.java:556)
at java.lang.String.valueOf(String.java:2827)
at java.lang.StringBuilder.append(StringBuilder.java:132)
at org.jivesoftware.smackx.avatar.vcardavatar.VCardAvatarManager.processStanza(VCardAvatarManager.java:319)
at org.jivesoftware.smack.AbstractXMPPConnection.firePacketInterceptors(AbstractXMPPConnection.java:1107)
at org.jivesoftware.smack.AbstractXMPPConnection.sendStanza(AbstractXMPPConnection.java:766)
at org.jivesoftware.smackx.caps.EntityCapsManager.updateLocalEntityCaps(EntityCapsManager.java:564)
at org.jivesoftware.smackx.caps.EntityCapsManager.access$500(EntityCapsManager.java:82)
at org.jivesoftware.smackx.caps.EntityCapsManager$8.onEntityCapailitiesChanged(EntityCapsManager.java:407)
at org.jivesoftware.smackx.disco.ServiceDiscoveryManager.renewEntityCapsVersion(ServiceDiscoveryManager.java:854)
at org.jivesoftware.smackx.disco.ServiceDiscoveryManager.addFeature(ServiceDiscoveryManager.java:389)
at org.jivesoftware.smackx.omemo.OmemoManager.initialize(OmemoManager.java:251)
at org.jivesoftware.smackx.omemo.OmemoManager$2.run(OmemoManager.java:266)
at java.lang.Thread.run(Thread.java:764)
2019-02-09 10:01:27.327 18641-19267/org.atalk.android E/aTalk: [3793] org.jivesoftware.smack.AbstractXMPPConnection.firePacketInterceptors() Packet interceptor threw exception
java.lang.NullPointerException: Attempt to invoke interface method 'int java.lang.CharSequence.length()' on a null object reference
at org.jivesoftware.smack.util.LazyStringBuilder.length(LazyStringBuilder.java:78)
at org.jivesoftware.smack.util.LazyStringBuilder.toString(LazyStringBuilder.java:112)
at org.jivesoftware.smack.util.XmlStringBuilder.toString(XmlStringBuilder.java:556)
at java.lang.String.valueOf(String.java:2827)
at java.lang.StringBuilder.append(StringBuilder.java:132)
at org.jivesoftware.smackx.avatar.vcardavatar.VCardAvatarManager.processStanza(VCardAvatarManager.java:319)
at org.jivesoftware.smack.AbstractXMPPConnection.firePacketInterceptors(AbstractXMPPConnection.java:1107)
at org.jivesoftware.smack.AbstractXMPPConnection.sendStanza(AbstractXMPPConnection.java:766)
at org.jivesoftware.smackx.caps.EntityCapsManager.updateLocalEntityCaps(EntityCapsManager.java:564)
at org.jivesoftware.smackx.caps.EntityCapsManager.access$500(EntityCapsManager.java:82)
at org.jivesoftware.smackx.caps.EntityCapsManager$8.onEntityCapailitiesChanged(EntityCapsManager.java:407)
at org.jivesoftware.smackx.disco.ServiceDiscoveryManager.renewEntityCapsVersion(ServiceDiscoveryManager.java:854)
at org.jivesoftware.smackx.disco.ServiceDiscoveryManager.addFeature(ServiceDiscoveryManager.java:389)
at org.jivesoftware.smackx.omemo.OmemoManager.initialize(OmemoManager.java:251)
at org.jivesoftware.smackx.omemo.OmemoManager$2.run(OmemoManager.java:266)
at java.lang.Thread.run(Thread.java:764)
2019-02-09 10:01:27.330 18641-19263/org.atalk.android W/aTalk: [3789] org.jivesoftware.smack.util.XmlStringBuilder.write() Stanza contains null: [<, presence, , id, =', 9caj4-96, ', >, <, status, />, <, priority, >, 30, </, priority, >, <c xmlns='http://jabber.org/protocol/caps' hash='sha-1' node='http://android.atalk.org' ver='SPANeHrMhKxipyDRRXFZu1T21So='/>, null, </, presence, >]
2019-02-09 10:01:27.332 18641-19263/org.atalk.android D/SMACK: SENT (0):
<presence id='9caj4-96'>
<status/>
<priority>
30
</priority>
<c xmlns='http://jabber.org/protocol/caps' hash='sha-1' node='http://android.atalk.org' ver='SPANeHrMhKxipyDRRXFZu1T21So='/>
</presence>
2019-02-09 10:01:27.396 18641-19264/org.atalk.android D/SMACK: RECV (0):
<presence xml:lang='en' to='swordfish@atalk.org/atalk' from='swordfish@atalk.org/atalk' id='9caj4-96'>
<c xmlns='http://jabber.org/protocol/caps' hash='sha-1' node='http://android.atalk.org' ver='SPANeHrMhKxipyDRRXFZu1T21So='/>
<x xmlns='vcard-temp:x:update'>
<photo>
1bfa4a6e285b3f609ddeeb7c95de851dcf3eb56c
</photo>
</x>
<priority>
30
</priority>
<status/>
</presence>