Skip to content

J2ME MIDlet programming on linux

I’ve found myself in the position of wanting to develop a portable mobile application. Now, I’m not a java programmer, nor do I use windows (I’m running 64-bit Gentoo Linux), and I prefer to use Vim + Makefiles over using some IDE, so I had a few challenges to overcome in building my first Hello World MIDlet. In the end though, it isn’t too bad to get going, so if you are in a similar situation, here are some quick notes on how I got from zero to MIDlet.

  1. First and foremost, you’ll need to have a full blown Java Development Kit (JDK) installed. I’m using Sun’s JDK 1.6.0.13, but I don’t think it is too important. (Both 32 bit and 64 bit versions seem to work fine.)
  2. If you are running a 64 bit version of Linux, you’ll need to have a 32 bit java runtime environment (JRE) installed somewhere to run the WTK device emulator. In gentoo, this means doing an ‘emerge emul-linux-x86-java’ (in gentoo, your installation will be in /opt/emul-linux-x86-java-1.X.Y.Z/).
  3. Next, you’ll need to download and install the Java Wireless Toolkit, I’m using version 2.5.2 (3.0 is out, but it is only for windows..). It is available here: http://java.sun.com/products/sjwtoolkit/download.html. You should end up with a file named something like “sun_java_wireless_toolkit-2.5.2_01-linuxi486.bin.sh”.  Run this shell script to install the WTK, and again, if you are using 64 bit linux, don’t forget to give the path to your 32 bit version of java when the installer asks for it.
  4. Now we can start working on our midlet. Create a file called HelloWorld.java containing the following code
      |  copy code |? 
    01
    import javax.microedition.lcdui.Alert;
    02
    import javax.microedition.lcdui.Display;
    03
    import javax.microedition.midlet.MIDlet;
    04
     
    05
    import java.util.Date;
    06
     
    07
    public class HelloWorld extends MIDlet {
    08
        Alert timeAlert;
    09
     
    10
        public HelloWorld() {
    11
            timeAlert = new Alert("Hello!");
    12
            timeAlert.setString("Hello World! The time is now " + new Date().toString());
    13
        }
    14
     
    15
        public void startApp() { 
    16
            Display.getDisplay(this).setCurrent(timeAlert);
    17
        }
    18
     
    19
        public void pauseApp() { }
    20
        public void destroyApp(boolean unconditional) { }
    21
    }
  5. Now, create a file called Manifest, containing the following lines
     shell |  copy code |? 
    1
    MIDlet-Name: HelloWorld
    
    2
    MIDlet-Vendor: YourName
    
    3
    MIDlet-Version: 1.0
    
    4
    MIDlet-Icon: /icon.png
    
    5
    MIDlet-Info-URL: http://hexist.com/?p=29
    
    6
    MicroEdition-Configuration: CLDC-1.0
    
    7
    MicroEdition-Profile: MIDP-2.0
    
    8
    MIDlet-1: HelloWorld, /icon.png, HelloWorld
  6. Save the following image icon as icon.png
  7. Create a Makefile and paste the below into it. Modify the JDK_BASE and J2ME_BASE variables appropriately depending on where you installed your JDK and your J2ME/WTK packages.
      |  copy code |? 
    01
    ### Modify these appropriately for your system!
    02
     
    03
    JDK_BASE=/opt/sun-jdk-1.6.0.13
    04
    J2ME_BASE=$(HOME)/WTK2.5.2
    05
     
    06
     
    07
    ### For the tutorial, you shouldn't have to modify anything below this line
    08
     
    09
    SRC=HelloWorld.java
    10
     
    11
    JAVAC=$(JDK_BASE)/bin/javac
    12
    JAVA_CFLAGS=-bootclasspath "$(J2ME_BASE)/lib/midpapi20.jar:$(J2ME_BASE)/lib/cldcapi10.jar"  \
    13
                -target 1.3                                                                     \
    14
                -source 1.3                                                                     \
    15
                -d compiled                                                                     \
    16
                -classpath compiled                                                             \
    17
                -sourcepath .                                                                   \
    18
                -g
    19
    PREVERIFY=$(J2ME_BASE)/bin/preverify
    20
    PREVERIFY_CLASSPATH=$(J2ME_BASE)/lib/midpapi20.jar:$(J2ME_BASE)/lib/cldcapi10.jar
    21
     
    22
     
    23
    all: HelloWorld.jar HelloWorld.jad
    24
     
    25
    run: HelloWorld.jad
    26
     $(J2ME_BASE)/bin/emulator -Xdescriptor:HelloWorld.jad
    27
     
    28
    HelloWorld.jar: verified compiled Manifest $(SRC:.java=.class)
    29
     jar cfm HelloWorld.jar Manifest icon.png -C verified $(SRC:.java=.class)
    30
     
    31
    compiled:
    32
     mkdir -p compiled
    33
     
    34
    verified:
    35
     mkdir -p verified
    36
     
    37
    %.class: %.java
    38
     $(JAVAC) $(JAVA_CFLAGS) $<
    39
     $(PREVERIFY) -classpath $(PREVERIFY_CLASSPATH):compiled -d verified HelloWorld
    40
     
    41
    %.jad: %.jar
    42
     unzip -aa -j -p $< "META-INF/MANIFEST.MF" > $@
    43
     echo "MIDlet-Jar-URL: $<" >> $@
    44
     echo "MIDlet-Jar-Size: " `stat -c%s $<` >> $@
    45
     
    46
    clean:
    47
     rm -Rf compiled verified
    48
     rm -f *.jar *.jad
    49
     
    50
    .PHONY: clean all run

Now, you should be able to run ‘make’ to build your JAR and JAD files, and ‘make run’ to run the WTK phone emulator. For those that just want to see the raw compile steps for everything that needs to be done to go from .java to a jad n jar, here they are:

mkdir -p verified
mkdir -p compiled
/opt/sun-jdk-1.6.0.13/bin/javac -bootclasspath "$HOME/WTK2.5.2/lib/midpapi20.jar:$HOME/WTK2.5.2/lib/cldcapi10.jar" -target 1.3 -source 1.3 -d compiled -classpath compiled -sourcepath . -g HelloWorld.java
$HOME/WTK2.5.2/bin/preverify -classpath $HOME/WTK2.5.2/lib/midpapi20.jar:$HOME/WTK2.5.2/lib/cldcapi10.jar:compiled -d verified HelloWorld
jar cfm HelloWorld.jar Manifest icon.png -C verified HelloWorld.class
unzip -aa -j -p HelloWorld.jar "META-INF/MANIFEST.MF" > HelloWorld.jad
echo "MIDlet-Jar-URL: HelloWorld.jar" >> HelloWorld.jad
echo "MIDlet-Jar-Size: " `stat -c%s HelloWorld.jar` >> HelloWorld.jad

Then a quick ‘make run’, which just executes

$HOME/WTK2.5.2/bin/emulator -Xdescriptor:HelloWorld.jad

HelloWorld MIDlet

HelloWorld MIDlet

and if everything went well, up will pop our device emulator ready to launch our MIDlet. Click ‘launch’, and you should see a screen that looks something like the image on the right.

To get the files installed on an actual phone, the easiest way (in my opinion) is to simply throw the .jad and .jar files up on a web page somewhere and to browse to the .jad file. Alternatively, most phones have USB hookups or some other way of installing apps without connecting them to the internet, so depending on your phone that might be easier for you.

 

Tar ball of all these files: HelloWorld.tar.bz2

{ 10 } Comments

  1. Goner Leone | 2009-09-20 at 3:47 pm | Permalink

    I’m facing a similar situation to the one you seem to have resolved. I am trying to install the WTK2.5.2 package downloaded from Sun. I get the following error when trying to point it to the 32bit emul-linux-x86-java installation location. I’ve tried changing things with java-config and eselect java-vm to no avail. Any ideas?

    Enter a path to the Java 2 SDK: /opt/emul-linux-x86-java-1.6.0.15/bin
    /opt/emul-linux-x86-java-1.6.0.15/bin/java
    Testing /opt/emul-linux-x86-java-1.6.0.15/bin/java…
    Exception in thread “main” java.lang.ClassFormatError: Incompatible magic value 0 in class file com/sun/kvem/environment/JavaVersionTester
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:621)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:260)
    at java.net.URLClassLoader.access$000(URLClassLoader.java:56)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:195)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:252)
    at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320)
    Could not find the main class: com.sun.kvem.environment.JavaVersionTester. Program will exit.
    /opt/emul-linux-x86-java-1.6.0.15/bin is not a suitable Java interpreter

  2. Goner Leone | 2009-09-20 at 5:31 pm | Permalink

    Me again. I managed to get everything working. Rather than install emul-linux-x86-java, I downloaded “jdk-6u16-linux-i586.bin” and moved the extracted files to /opt/jdk32

    I then re-installed WTK2.5.2 and pointed the Java 2 SDK path to: /opt/jdk32/bin

    I believe that the earlier error was due to conflicting java installations or a version mismatch somewhere along the line, even though java-check-environment reported no errors.

    Time to start hacking…

  3. admin | 2009-09-20 at 6:54 pm | Permalink

    Mmm weird, well glad you got it all figured out :)

  4. w00k | 2009-10-19 at 10:40 pm | Permalink

    [:(] I tried what Goner leoner said , but am getting the same error as before, have any ideas why this happens.

  5. wook | 2009-10-20 at 10:03 am | Permalink

    nvm….i was using the wrong version of WTK [2.2] seems like the problems dont arise in WTK[2.5] , am gonna try doing some stuff, will start of with the HELLO WORLD.

  6. admin | 2009-10-20 at 10:09 am | Permalink

    Ah excellent :)

  7. bling | 2009-12-23 at 9:02 am | Permalink

    great !!!

  8. bling | 2009-12-27 at 10:43 am | Permalink

    hi,
    I would like to know how do you manage to change the Makefile and the Manifest file if you are working with several java classes.
    Thanks for your reply

  9. charly | 2010-04-13 at 10:24 am | Permalink

    I get the following error when trying to point it to the amd 64bit . What’s the problem???

    /usr/bin/X11/javac -bootclasspath “/usr/local/WirelessToolkit/WTK2.5.2/lib/midpapi20.jar:/usr/local/WirelessToolkit/WTK2.5.2/lib/cldcapi10.jar” -target 1.3 -source 1.3 -d compiled -classpath compiled -sourcepath . -g parkingSarp.java

    /usr/local/WirelessToolkit/WTK2.5.2/bin/preverify -classpath /usr/local/WirelessToolkit/WTK2.5.2/lib/midpapi20.jar:/usr/local/WirelessToolkit/WTK2.5.2/lib/cldcapi10.jar:compiled -d verified parkingSarp

    /usr/local/WirelessToolkit/WTK2.5.2/bin/preverify1.1: error while loading shared libraries: libXt.so.6: cannot open shared object file: No such file or directory
    make: *** [parkingSarp.class] Error 127

  10. admin | 2010-04-13 at 10:52 am | Permalink

    Well, it’s complaining that you don’t have the libXt.so.6 file. I’d google ‘missing libXt.so.6 (your linux distro name here)’ and see if you can find what package you need to install.

{ 1 } Trackback

  1. [...] J2ME Midlet Programming on Linux [...]

Post a Comment

Your email is never published nor shared. Required fields are marked *