Porting Smack 1.0.1 to J2ME

Folks…

I once promised to post how one could port the Smack API to J2ME MIDP2.0, so here it is.

A side note; the API works in the emulator (SUN’‘s wireless toolkit), but not yet on a real J2ME MIDP2.0 phone. This is mainly due to the fact that the phones I tried (Nokia 6600 and SonyEricsson P900) don’‘t support full duplex sockets. Fixing this turned out to be rather cumbersome. It can be done, but I don’‘t have the time to do it in boss’’ time The discussion about a possible solution can be found here: http://www.jivesoftware.com/jive/thread.jspa?forumID=39&threadID=12074&messageID =81543#81543

Anyway, I hope you will find this information usefull when you want to porting the API. Here’'s the instructions:


  • Map -> Hashtable

  • HashMap -> Hashtable

  • List -> Vector

  • ArrayList -> Vector

  • LinkedList (in PacketWriter) -> Stack

  • LinkedList (in PacketCollector) -> Stack

  • Iterator -> Enumeration

  • and remove methods setName() and setDaemon() for threads in PacketReader and PacketWriter

  • Replaced Vector.add() with Vector.addElement()

  • Replaced Vector.set(index, obj) with Vector.setElementAt(obj, index); Mind the order of the arguments!

  • In RemoteRosterEntry zit: (Collections.unmodifiableList(groupNames).toArray(new String[groupNames.size()])), omgezet

  • Got rid of unusable types in Time.java

  • ProviderManager.java: got rid of use of URL to get an InputStream on a file. Instead I used: Class.forName(“org.jivesoftware.smack.provider.ProviderManager”).getResourceAsS tream(“META-INF/smack.providers”);

  • StringUtils.randomString(): made random function j2me compatible

  • MessageEventManager.java: Changed fireMessageEventRequestListeners() and fireMessageEventNotificationListeners() so that they do not determine the method to call dynamically (by using Class.getDeclaredMethod()). Now they use static strings to identify the methods (which can be found in MessageEventNotificationListener.java).

  • finalize() method should not appear, thus removed (from MessageEventManager.java and RosterEventManager.java)

  • in StringUtils.escapeForXML() the initial length of the StringBuffer is set to a float casted to an int. Replaced this by an int (2)

  • Replaced .class calls with Class.forName(), as in the following snippet (do a search for .class and don’‘t forget to catch errors that could be thrown). Also be aware that in J2SE they use ‘‘com.somecompany.Foo.class’’ and in J2ME you should use ‘‘com.somecompany.Foo’’, thus without the ‘’.class’’ in the end and with the full classpath.

  • Replaced the XML parser with KXML2 parser. So in ProviderManager.java and PacketReader.java I changed:

XmlPullParserFactory factory = XmlPullParserFactory.newInstance(“org.xmlpull.mxp1.MXParserFactory”, null);

to:

XmlPullParserFactory factory = XmlPullParserFactory.newInstance(“org.xmlpull.v1.XmlPullParser”, this.getClass());

  • XMPPConnection, PacketReader, GroupChat, PrivateDataManager, Roster: changed the time to wait when loging in to ‘‘LOGIN_TIMEOUT’’ seconds before throwing a timeout exception. This is needed for the higher latencies and slower dataconnections of mobile networks. Do a search efor ‘‘LOGIN_TIMEOUT’’.

  • Some MIDP phones don’'t support full duplex communication (simultaneous reading/writing over a socket connection). Therefore reading and writing had to be synchronized. See for information how to go about: http://www.jivesoftware.com/jive/thread.jspa?threadID=12074&tstart=0


TODO’'s


  • Smack seems to be case sensitive. This is problematic since other XMPP clients (such as Exodus) ignore case differences when adding new buddies. These buddies will appear in the roster of a smack client, but won’'t match with events from buddies with the same name but different cases. This gives errors in Roster$PresencePacketListener.processPacket()

  • XMPPConnection.init() normally uses a BufferedReader although a PacketReader only requires a Reader. Since J2ME doesn’'t have BufferedReaders I used InputStreamReader. It works, but double check.

  • In PacketWriter the LinkedList is replaced by a Stack. vervangen. It works, but double check.

  • Collections.unmodifiableList(new ArrayList(unfiledEntries)).iterator(); replaced by new Vector(unfiledEntries).elements(); This ignores the unmodifiable character. It works, but is it a problem? This happens in many places, check all classes that use a unmodifiableList.

  • convert Swing debug window in XMPP connection to J2ME compatible debugging system

  • Got rid of unusable types in Time.java, but that means that the location independence got lost… Try to restore that. Use the original file for inspiration.


Cheers,

Berco

Berco,

Thanks for sharing this info with the community. BTW, were you porting Smack 1.0.1 or is it that the subject of this post is wrong?

Thanks,

– Gato

Hi Gato,

I was indeed porting version 1.0.1. Does that suprise you? I don’‘t think later versions of Smack are much different when it comes to porting to J2ME, don’'t you think so?

Anyway, I hope I can find a few more hours somewhere in the future to solve the problems with full-duplex sockets, so we can finally run Smack on a real mobile phone.

Take care,

Berco