Tips & Hints
J2ME
This version of this site is expired, Tutorials available for archive purposes.
Click here for the latest version of the site http://www.jasonlam604.com
J2ME General / Generic

kSOAP and Basic Authentication
public String username = null;
public String password = null;

if (username != null && password != null) {
   StringBuffer buf = new
   StringBuffer(username);
   buf.append(':').append(password);
   byte[] raw = buf.toString().getBytes();
   buf.setLength(0);
   buf.append("Basic ");
   org.kobjects.base64.Base64.encode(raw, 0,raw.length, buf);
   connection.setRequestProperty("Authorization",buf.toString());
}


You will need to add in the public method to set the Credientials too.

Thanks to stonedMonk from the kSOAP forum for the tip.

By Jason Lam
HTTP Read Images
The code to read an image from the server is as follows:

DataInputStream iStrm = conn.openDataInputStream();
byte imageData[];


// If size is known
if (length != -1) {
imageData = new byte[length];

// Read the Image data into an array
iStrm.readFully(imageData);

// If size is NOT known
} else {
ByteArrayOutputStream bStrm = new ByteArrayOutputStream();
int ch;
while ((ch = iStrm.read()) != -1)
bStrm.write(ch);
imageData = bStrm.toByteArray();
bStrm.close();
}


// Contains Image retrieved in an Image Object
image = Image.createImage(imageData, 0, imageData.length);


By Jason Lam
HTTP POST
// 1. postmsg is the POST Values being sent to HTTP Server
// 2. What people usually miss is the content-type and content length

conn.setRequestMethod(HttpConnection.POST);

conn.setRequestProperty("User-Agent","Profile/MIDP-1.0 Configuration/CLDC-1.0" );
conn.setRequestProperty("Content-Language", "en-US" );

postmsg = request.getBytes();

conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("Content-Length",Integer.toString( postmsg != null?postmsg.length : 0 ) );

out = conn.openOutputStream();
out.write(postmsg);

By Jason Lam
HTTP GET
For GET Http calls all you need to do is indicate a GET is being used:

conn.setRequestMethod(HttpConnection.GET);
conn.setRequestProperty("User-Agent","Profile/MIDP-1.0 Configuration/CLDC-1.0" );
conn.setRequestProperty("Content-Language", "en-US" );

The url you pass you contains the GET parameters passed to the server.

By Jason Lam
HTTP Read Cookies
// After executing the HttpConnection you can parse out the "set-cookie" values, the // following method is configured to read cookies from JSP/Servlets, ASP or PHP. It can // easily be modified to handle other server-side scripts/languages like Cold Fusion // Zope... etc private String readCookie( HttpConnection conn ) throws IOException { String key; String value; String[] substrs; for( int i = 0; ( key = conn.getHeaderFieldKey( i ) ) != null; ++i ) { key = key.toLowerCase(); if( key.equals( "set-cookie" ) ){ value = conn.getHeaderField( i ); while( value != null ) { substrs = Utils.split( value, ';' ); if( substrs[0].startsWith("JSESSIONID=") || // Java substrs[0].startsWith("PHPSESSID") || // PHP substrs[0].startsWith("SessionId") // ASP ){ return substrs[0]; } value = substrs[1]; } } } return null; } By Jason Lam
HTTP Encode URL
When making HTTP calls you may need to encode the parameters because certains characters will cause problems usually the "space" is the prime suspect i.e.: http://www.somedomain.com/changeAddress? address=18394 West Wood Drive should be http://www.somedomain.com/changeAddress? address=18394%20West%20Wood%20Drive See the following for a reference of all the characters http://www.w3schools.com/html/html_ref_urlencode.asp, for more information on URL encoding specification see the RFC 1738 section 2.2 http://www.faqs.org/rfcs/rfc1738.html The following code snippet will help you encode the url parameters: public final static String encodeURL(String url) { String newurl = ""; int urllen = url.length(); for(int i = 0; i < urllen; ++i) { char c = url.charAt(i); if(((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')) || ((c >= '0') && (c <= '9')) || (c == '.') || (c == '-') || (c == '*') || (c == '_') || (c == '/') || (c == '~')) { newurl += c; } else if(c == ' ') { newurl += '+'; } else { newurl += encodeChar(c); } } return newurl; } private static String encodeChar(char c) { String encchar = "%"; encchar += Integer.toHexString((c / 16) % 16).toUpperCase(); encchar += Integer.toHexString(c % 16).toUpperCase(); return encchar; } By Jason Lam
Obfuscate Multiple JARS using Proguard
Okay obfuscating multiple JARS is not a really a big deal, the trick is when one JAR needs to know the how the 1st JAR was obfuscated, with Proguard you can use the filter option. This probably isn't really all that common with J2ME development most times you would deploy your game or application as one JAR. Some case will require JAR splitting, for example, for Blackberry development when deploying a game/application larget then 64 KB via OTA it is required to deploy 2 or more COD files, in this case split JAR obfuscation is required unless of course you don't obfuscate the code. Here is the sample proguard.pro input file: # The 2 JARS you want obfuscate -injars C:\HelloWorld\HelloWorldLib.jar -injars C:\HelloWorld\HelloWorld.jar # MIDP JARS - Whatever is appropriate here # for example blackberry could be # -libraryjars C:\HelloWorld\net_rim_api.jar # -libraryjars C:\wtk21\lib\midpapi20.jar.jar;c:\wtk21\lib\cldcapi10.jar # You need to use the filter option here, more then like you will have to run # this at least twice, the 1st just to get the mapping.txt # so you can find out what the class names are obfuscated to, but its more or # less obvisous they start from a,b,c..... z # # The question is which class do you want in which JAR # -outjars C:\HelloWorld\obf\HelloWorld.jar(HelloWorld.class,a.class,b.class,c.class) -outjars C:\HelloWorld\obf\HelloWorldLib.jar # Print out the mapping -printmapping C:\HelloWorld\mapping.txt -verbose -overloadaggressively -defaultpackage '' # Basic - Midlets. Keep all extensions of javax.microedition.midlet.MIDlet. -keep public class * extends javax.microedition.midlet.MIDlet By Jason Lam
Mime Type
Proper MimeType for Apache: AddType text/vnd.sun.j2me.app-descriptor .jad AddType application/java-archive .jar Apache with Blackberry Support: AddType application/vnd.rim.cod .cod Proper MimeType configuration for Struts Framework: By Jason Lam
String to Unicode
/** * Converts a unicode string code to the unicode symbol * * @param String value representating a unicode code ie: 0669 * @return unicode symbol as a String */ private String convertStrToUnicode(String value) { short valueAsShort = Short.parseShort(value.trim(),16); return String.valueOf((char)valueAsShort); } By Jason Lam
Read JAD File
To read values from the JAD file at runtime use the method getAppProperty from the Midlet class. For example a typical JAD file may contain the following: MIDlet-1: HelloWorld, HelloWorld.png, HelloWorld MIDlet-Jar-Size: 1092 MIDlet-Jar-URL: HelloWorld.jar MIDlet-Name: HelloWorld MIDlet-Permissions: javax.microedition.io.Connector.https MIDlet-Vendor: JasonLam604 MIDlet-Version: 1.0.0 MicroEdition-Configuration: CLDC-1.0 MicroEdition-Profile: MIDP-2.0 Say you wanted to display the current version in the application you would obtain it by using the following code:: String versionNumber = getAppProperty(MIDlet-Version); By Jason Lam



BlackBerry Specific

Blackberry Remove orphan libraries from real device
There are times you will find the Blackberry Desktop Manager is unable to remove an installed application this usually occurs when the application contains a dependant COD file along with several various methods of installation. What does it mean by various methods of installation. If the application is install via USB using .alx XML file then updated via OTA (without removing the original install first using the Desktop Manager not the removal option in the device) then the BlackBerry Desktop Manager may not be able to remove the application complete even if the exact same version is install via both methods. As well using the "delete" module option int the handset fails to remove the module as well. The solution is to manually use the JavaLoader.exe you will find this under the [instalation directory]\bin. So for example your application is made up of 2 COD files one name d HelloWorld.jar and the other named HelloWorldLib.jar and the HelloWorldLib.jar cannot uninstall. You simply type the following at command line:

JavaLoader -usb -erase HelloWorldLib.jar

Make sure you nothing else is communicating to the handset, ie: close down the Blackberry Desktop Manager

By Jason Lam
HTTP connections with BlackBerry
UPDATE - More the likely this is not needed anyomore due to the fact most carriers support Direct TCP/IP Now

Making HTTP Connections is the same as any other J2ME application/game except you need to add the wap parameters specific to the operator/carrier the application is running on if you so decide not run the Blackberry application/game in a Blackberry Enterprise Environment. In short BES is excatly the same as a "normal" HTTP Connection call. If you do not use a BES/MDS following parameters you need to add are:

* WapGatewayIP
* WapGatewayAPN
* WapGatewayPort


This information can be be usually obtain from the operators/carrier developer portal.

An example of what an actually call would look like:

url = "http://www.myserver.com/myscript.jsp;WapGatewayIP=1.1.1.1;WapGatewayPort=9301 ;WapGatewayAPN=1.1.1.1 conn = (HttpConnection)Connector.open(url);

Yes you can still use GET parameters, you just need to tag the WAP info at the end.

Note both Nextel and Telus Mobility (MIKE not there 1X service) use the iDEN network. Instead of passing in WAP info you need to set the parameter deviceside=true. For example:

url = "http://www.myserver.com/myscript.jsp;deviceside=true";

By Jason Lam
Reset RMS on BlackBerry handset
Attach your Blackberry to the USB. Then use the Blackberry Desktop Manager. Select "Backup and Restore" then select the "Advanced" option. On the right hand side select "RMS Databases" and press the button that says "Clear". That should clear the RMS storage off the device

By Jason Lam



Palm Specific

Unable to convert JAR to PRC using WebSphere Micro Env. Toolkit for PalmOS
UPDATE - Kept this around for legacy reasons. I highly suggest for Palm device to port the application over using Native language support. J2ME just doesn't cut it on the device and the support getting the VM to wrong can be hell!

When using the GUI converter and after filling out all the proper information you still find the result PRC file is only 1KB. This may seem stupid or very simple and obvious but sometimes the obvisous doesn't hit you. What you need to do is simply clear the classpath. Like most developers having dozens of classpath variables set up for various environment settings isn't uncommon but may clash with the conversion. So just type in the working directory of jartoprc_w.exe the following:

set classpath

That is it!

By Jason Lam



If you noticed some tips/hints are missing that is because I removed them. Basically, those tips are out of date and simply don't apply to todays mobile development. For example, I removed a J2ME tip related Pocket PC 2003, its just too old; the market place today mainly has Mobile 5 & 6 out; as well, Mobile 7 enabled devices are coming soon.