I,m using Smack to upload avatar. It takes long time and most of that time it times out (sometimes even 2min is not enough). Is there a way I can improve on that? Is there any other way to quickly upload avatar?
I know I can have just my own http service serving avatars, but I’m not willing to go that route right now. Fetching VCard avatar is very quick.
Here is the code I use:
fun setPhoto(path: String) = viewModelScope.launch(Dispatchers.IO) {
try {
val file = File(path)
val vCardMgr = VCardManager.getInstanceFor(connection)
val vCard = vCardMgr.loadVCard()
vCard.setAvatar(Base64.encodeToString(file.readBytes(), Base64.DEFAULT), FileUtils.getMimeType(path))
vCardMgr.saveVCard(vCard)
} catch (e: Exception) {
launch(Dispatchers.Main){
Toast.makeText(chatApp.applicationContext, e.message, Toast.LENGTH_LONG).show()
}
}
}
What am I doing wrong? Test is on local machine so I expected things to be very fast, but opposite is the case!
I’m not sure why uploading the avatar is slow for you. Maybe it is not Smack, but the server?
The recommended way to deal with user avatars is defined in XEP-0084: User Avatars. Sadly Smack does not have support for those (yet), however there is a pending PR that may add support for it soon.
Hi Paull,
thanks for the comment. Have you ever tried out ths feature and see the response?
I also found it strange behavior, especially since am using local machine!
I will try with Openfire (currently using ejabberd) and see if there will be any difference.
I haven’t yet tried out setting avatars via VCard, however judging from the XEP, the client does not have to do any heavy lifting at all. It just has to send out one stanza and wait for the response, so I guess it is most likely a slow server component.
Another theory might be that you registered some synchronous listeners on the connection that block the reader thread and cause a deadlock in Smacks code which results in the timeout. Maybe check your server logs (with debug level 5 in ejabberd) to see how fast the server acknowledges the vcard stanza.
Thanks for the hint, however I don’t understand the “you registered some synchronous listeners on the connection”. What do you mean by sync? How do I know the listerner is Sync or async? I have added chat listerner and am getting roster presence changes too
So I did further testing with Openfire and here is an error that actually occurs. I don’t know what it means exactly but my guess is the encoded text is too large to parse. I checked cropped file is 3MB. It is not a small size but I’m not sure why is it too large for XMPP.
Here is the log
2020.04.26 22:04:12 WARN [socket_c2s-thread-3]: org.jivesoftware.openfire.nio.ConnectionHandler - Closing connection due to exception in session: (0x00000007: nio socket, server, /192.168.1.103:42064 => /192.168.1.101:5222)
org.apache.mina.filter.codec.ProtocolDecoderException: Stopped parsing never ending stanza (Hexdump: (redacted hex dump of never ending stanza))
at org.jivesoftware.openfire.nio.XMLLightweightParser.read(XMLLightweightParser.java:192) ~[xmppserver-4.5.1.jar:4.5.1]
at org.jivesoftware.openfire.nio.XMPPDecoder.doDecode(XMPPDecoder.java:38) ~[xmppserver-4.5.1.jar:4.5.1]
at org.apache.mina.filter.codec.CumulativeProtocolDecoder.decode(CumulativeProtocolDecoder.java:180) ~[mina-core-2.1.3.jar:?]
at org.apache.mina.filter.codec.ProtocolCodecFilter.messageReceived(ProtocolCodecFilter.java:254) [mina-core-2.1.3.jar:?]
at org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextMessageReceived(DefaultIoFilterChain.java:650) [mina-core-2.1.3.jar:?]
at org.apache.mina.core.filterchain.DefaultIoFilterChain.access$1300(DefaultIoFilterChain.java:49) [mina-core-2.1.3.jar:?]
at org.apache.mina.core.filterchain.DefaultIoFilterChain$EntryImpl$1.messageReceived(DefaultIoFilterChain.java:1128) [mina-core-2.1.3.jar:?]
at org.apache.mina.core.filterchain.IoFilterEvent.fire(IoFilterEvent.java:106) [mina-core-2.1.3.jar:?]
at org.apache.mina.core.session.IoEvent.run(IoEvent.java:89) [mina-core-2.1.3.jar:?]
at org.apache.mina.filter.executor.OrderedThreadPoolExecutor$Worker.runTask(OrderedThreadPoolExecutor.java:766) [mina-core-2.1.3.jar:?]
at org.apache.mina.filter.executor.OrderedThreadPoolExecutor$Worker.runTasks(OrderedThreadPoolExecutor.java:758) [mina-core-2.1.3.jar:?]
at org.apache.mina.filter.executor.OrderedThreadPoolExecutor$Worker.run(OrderedThreadPoolExecutor.java:697) [mina-core-2.1.3.jar:?]
at java.lang.Thread.run(Thread.java:832) [?:?]
Openfire has a (configurable) maximum stanza size limit. I think it’s on 2MB. Note that when you base64 encode binary data, the encoded result will be a lot larger than the unencoded original. I suggest that you reduce the image size in your vcard, or use another mechanism to exchange the data.