The Wireless Toolkit
Peter Komisar ©  Conestoga College  version  1.1 /  2008

reference: User’s Guide Sun JavaTM Wireless Toolkit for CLDC
Version 2.5.2, Sun Microsystems


Fortunately for us there are simpler ways of developing
MIDlets. It is good to know about the steps involved in
generating a MIDlet application.

Before considering, more elaborate IDE's like NetBeans
we look at what the WTK has to offer. If we are use to it
we can easily transition to a more elaborate IDE if we
find it necessary.

In the last note, we described downloading the Wireless
TookKit, installing it and adding it's path. We now look
at how it can be used to facilitate MIDlet development.


Starting the Toolkit

On  Windows you start the WDK from 'All Programs'.
On Linux, change directories to toolkit/bin. and enter
./ktoolbar.

We saw last class that we could look at existing programs
by opening 'Open Projects'.

The Toolkit has three primary parts.


Toolkit Components
To the mix you need to supply your own text editor.

Toolkit Features

The Sun JavaTM Wireless Toolkit supports:

An Update Feature Checks every seven days if you need
an update based on system information it collects.  Disable
with the following clicks.


Controlling the Update Feature

Edit > Preferences > click Network Configuration >
check / uncheck 'Check for updates' box.


Toolkit API Support

Following is a quick summary of APIs supported by the
toolkit with associated links. The list is impressive including
Security, Scalable 2D Vector Graphics, 3D Graphics APIs
and Bluetooth support.


Toolkit Supported APIs

Projects

With Sun's Toolkit  "MIDlet suites are organized into
projects, where the end result of one project is one
MIDlet suite. A project contains all of the files that will
be used to build a MIDlet suite, including Java source
files, resource files, and the MIDlet descriptor."

// a project holds the MIDlet suite and all the pieces
// that were used to create it.


Creating a Project

Notice the important information on the toolkit console
regarding where to put development files is listed on
the Toolkit's UI.


Simple Cycle

The User Guide Describes the Simple Development
Cycle.

From the most general viewpoint the cycle is as follows.


Edit source code > Build > Run

To make life easy we can lift the example from the Sun's User
Guide

Java Example  // from the Sun's User Guide

import javax.microedition.lcdui.*;
import javax.microedition.midlet.MIDlet;

public class TinyMIDlet
extends MIDlet
implements CommandListener {
public void startApp( ) {
Display display = Display.getDisplay(this);
Form mainForm = new Form("TinyMIDlet");
mainForm.append("Welcome to the world of MIDlets!");
Command exitCommand = new Command("Exit", Command.EXIT, 0);
mainForm.addCommand(exitCommand);
mainForm.setCommandListener(this);
display.setCurrent(mainForm);
}
public void pauseApp () {}
public void destroyApp(boolean unconditional) {}
public void commandAction(Command c, Displayable s) {
if (c.getCommandType() == Command.EXIT)
notifyDestroyed();
}
}


1. Save Source File


Notice the directory that the WTK saved to was way
inside the User's location on Windows.

Example Save Location

C:\Document and Settings\Peter\j2mewtk\2.5.2\apps\memos\src

// the toolkit did not offer us options here


2. Build            

Click Build. If you have errors the build will fail.
Fix and try again!

3. Run          // emulate

Choose the MIDlet to run in the emulator. Clicking the
square button activates 'Launch'.


Full Development Cycle

The full cycle is more complicated and includes the
following steps:

Edit source code > Package > Install > Run


There are important differences between running an
installed application and running an application in the
simple development
cycle.


Packaging


To have the Toolkit package your MIDlet suite, choose:

 Project > Package > Create Package.

The MIDlet suite descriptor and JAR file are generated
and placed in the bin directory of your project.

Here is the JAD File created for the a simple project
called Memos.


JAD File Created by Toolkit

MIDlet-1: Memos, Memos.png, Memos
MIDlet-Jar-Size: 923
MIDlet-Jar-URL: Memos.jar
MIDlet-Name: Memos
MIDlet-Vendor: Unknown
MIDlet-Version: 1.0
MicroEdition-Configuration: CLDC-1.1
MicroEdition-Profile: MIDP-2.1


Here is the manifest that goes with the Jar Archive.


Generated Manifest File For Jar File


MIDlet-1: Memos, Memos.png, Memos
MIDlet-Name: Memos
MIDlet-Vendor: Unknown
MIDlet-Version: 1.0
MicroEdition-Configuration: CLDC-1.1
MicroEdition-Profile: MIDP-2.1



Install

Proper testing of a MIDlet requires an install. When
a MIDlet is run in the emulator, it loads directly from
the class files and doesn't test the packaging.


OTA, Over the Air

To resemble how applications work on real devices,
OTA mode can be used.

To install applications in the Sun Java Wireless
Toolkit emulator, choose the following:

Running OTA

Project > Run via OTA.

The emulator window opens, but instead of running the
MIDlet directly, the emulator shows the Application
Management Software (AMS) welcome screen. This
software is like that which real devices must have to
manage MIDlet suites.

The toolkit also allow you to create a project from
a jar and jad file.

While there are many other features to explore
on the toolkit we have enough functionality to
facilitate programming MIDlets.

A final feature that is of interest to note now is the
obfuscator.

The Obfuscator & ProGuard

The obfuscator is used to reduce the size of class files.
MIDlet suites have to be compact, both to minimize
download times and to meet JAR file size limits. The
obfuscator can be used at the packaging step.

The Sun Wireless Toolkit for CLDC doesn’t come with
an obfuscator but it is already configured to use the
ProGuard obfuscator. You will need to do is download
ProGuard and put it in a place where the toolkit can
find it. ProGuard is published under the terms of the
GNU General Public License (GPL). Agree to the
licence, and the download is free.


A Couple of Interesting First Observations


Following is a stripped down MIDlet pretty much
as small as it can get called MiniMidlet.


Minimal MIDlet Example

import javax.microedition.lcdui.*;
import javax.microedition.midlet.MIDlet;

public class MiniMidlet extends MIDlet{

public void startApp() {
   Display display = Display.getDisplay(this);
   Form mainForm = new Form("TinyMIDlet");
   mainForm.append
  (
  "******Hello Tiny********"
  );
 
 display.setCurrent(mainForm);
 }

  public void destroyApp(boolean unconditional){}
  public void pauseApp(){}
}



Abstract Methods in Parent Have to be Overridden


Now if MIDlets were like applets we would
not need to explicitly override the destroyApp( )
and pauseApp() methods. Commenting them
out though indicate they are defined abstractly
in the parent class. Thus you see why they need
to be present even if they are not asked to do
anything.


MIDLET Class

One of the key imports we have seen in all our
examples is the following:


Example

import javax.microedition.midlet.MIDlet;


If you look in that package there is the single class
MIDlet. It has a single protected no-args constructor
and the following methods.


MIDlet Methods   // from the J2ME Documentation


Exceptions


MIDlet defines one exception, the MIDletStateChangeException
which is thrown by startApp( ) and destroy( ).

Here we see where some of the life cycle methods are
defined as abstract and require explicit overriding even
if just to stub the methods out.

Primitives in MIDlets

The following example expands to include the use
of the different primitive values Java has to offer.
As well there is a  couple System.out.println
statements.

Recall our primitives in Java are as follows:

Table showing the Basic Categories of Java Primitives
 
 Type  Use
 boolean  represents truth values, true and false
 int,  long,  byte,  short  Integral Numbers   { 1 , 2 , 3  }
 double, float  Real ( floating point ) Numbers   { 1.1, 2.2, 3.3 }
 char   represents character data   {  'A ' }
    



A MIDlet with Primitives with System.out Println Statement

import javax.microedition.lcdui.*;
import javax.microedition.midlet.MIDlet;

public class ME_Lang extends MIDlet{

boolean boo=true;
byte b=32;
short s=32000;
char c='A';
int i=1299999;
long l =2999999999999L;
float f=3.2F;
double d= 12345.123456;


public void startApp() {
   Display display = Display.getDisplay(this);
   Form mainForm = new Form("TinyMIDlet");
   mainForm.append
  (
  " Primitive Types    \n"  +
  "====================\n"  +
  "boolean: " + boo + "\n"  +
  "byte:    " + b   + "\n"  +
  "short:   " + s   + "\n"  +
  "char:    " + s   + "\n"  +
  "int:     " + i   + "\n"  +
  "long:    " + l   + "\n"  +
  "float:   " + f   + "\n"  +
  "double:  " + i   + "\n"  +
  "===================="
  );
 
 display.setCurrent(mainForm);
 
 System.out.println("\nThe console is represented by the WTK screen!");
  System.out.println("Add f plus d : " + f + d +"\n");
 }

// destroyApp(boolean) is abstract and must be overridden

   public void destroyApp(boolean unconditional){}

// ditto for pauseApp()

   public void pauseApp(){}
}


Notice when the above code is run the System.out.println
print to the console of the WTK UI. That represents the
command line console.


All Primitives Are Now Supported

A second point to note is that all the primitive types are
supported. Early on in MIDlet history, developers were
adviced not to use the float or double type as you could
not suppose that target devices would support these
types.

Clarification

CLDC 1.0 did not support floating point numbers however
CLDC 1.1 does and is what is supported in the WTK.


From the Sun Site


"CLDC 1.1 is a revised version of the CLDC 1.0 specification,
and includes new features such as floating point and weak
reference support, in additional to other enhancements. CLDC
1.1 is backward compatible with CLDC 1.0, and continues to
target small and resource-constrained devices with the objective
of maintaining a tight footprint."   

                                                       - Sun Site Documentation



Characterizing the J2ME Environment

Anyone coming from a Java Standard or Enterprise
environment immediately wants to know how they
will be impacted by the constrained environment of
the Micro world.  First we may reiterate some of the
limitations imposed by the Micro JVM. Really the
limitations are not that bad and are often imposed
by security considerations.


Micro Java Virtual Machine Constraints
// RIM's API supports a version of RMI

The MIDP 2.1 API

What is impressive is the number of new APIs that are
have been added to augment the initially austere offering
made in MIDP.  We saw the list of many above. The original
offering has been enhanced and is now available in the
MIDP 2.1 API .

Originally the API was a slimmed version of JDK1.2
packages, namely the following:


MIDP2.1 API Core Packages
In addition to these packages the API is augmented
with the following packages which we investigate as
we proceed.


Additional MIDP2.1 Packages

Following are Classes that come down from java.lang.
Many of them are wrapper classes for the primitives.
There are the essential Math, String and StringBuffer
classes and Thread, System and Throwable.


The java.lang Package Classes
There is a pretty good set of Exception classes
you can refer to the API documentation to see.

There is one interface the 'Runnable' interface
needed for multithreading.

Following is a MIDlet that displays some of the
above noted classes in use.

Example

import javax.microedition.lcdui.*;
import javax.microedition.midlet.MIDlet;

public class ME_MoreLang extends MIDlet{

public void startApp() {
   Display display = Display.getDisplay(this);
   Form mainForm = new Form("TinyMIDlet");

  String statement1 = "The newer MIDlet API supports Wrapper Classes";
  Boolean booWrap= new Boolean(true);
  String  statement2 = "This is " + booWrap.toString() + "\n";
  String statement3 = "It does Math! The square root of 91 is " + Math.sqrt(91) + "\n";
  String statement4 = "It has a Throwable! Throw an Exception.";
  String statement5 = catchIt(); 
 

   mainForm.append
  (
   statement1  + "\n" +
   statement2  + "\n" +
   statement3  + "\n" +
   statement4  + "\n" +
   statement5
   );
 
 display.setCurrent(mainForm);

  // method that throws exception is called
  catchIt( );
 }
// exception throwing method defined

   String catchIt( ){
        String catcher="";
        try{
           throw new Throwable("Sinker!");
           }
        catch(Throwable t){
           catcher= "Not so fast " + t.getMessage();
           }
        return catcher;
        }        

// destroyApp(boolean) is abstract and must be overridden
   public void destroyApp(boolean unconditional){}

// ditto for pauseApp()
   public void pauseApp(){}
}



Again the IO package is trimmed but the key
classes are there for doing input and output.

We do not have a FileWriter or FileReader class
and can't expect to write to file. This of course makes
sense, when you think about the fact that a mobile
device like a cell phone will not have a file system,
at least not yet!

We see later the limited sort of storage that is
available on wireless devices later. We also see
different sorts of streaming connections that can
be made over networks using wireless devices.


The java.io Package Classes


Included in this package are five typical IO Exceptions
plus the DataInput and DataOutput interfaces.


The java.util Package Classes


The util package includes the Enumeration interface
and two exceptions, the EmptyStackException and
the NoSuchElementException.


Programming Practices for the J2ME

Before getting into details of the different classes
of the API, we might consider some general good
programming practices. These are taken from 'Lurker's
Guide to Optimizing MIDP apps'. The article can be
found at the following site.


The Lurker's Guide to J2ME

http://www.blueboard.com/j2me/index.htm

Lurker see optimization possible for the following:

Maintainability

Maintaining good organization, structure, and code readability
are important goals.  A first practical tip made on the Lurker
site is to avoid creating more objects than are necessary.

Lurkers makes the point that objects are allocated from runtime
memory which is a scarce resource. Primitive data types on the
other hand are allocated directly on the stack.

Another tip is to use StringBuffer rather than the String class.
In Lurker's example the String code is replaced with similar code
based on String buffer.


Lurker's String Example

String tempString="";
iceCreamGroup x=new IceCreamGroup();
for (int i=0;i<someNumber;i++) {
      tempString+=x.getIceCream (i);
      }

The Alternate StringBuffer Class
StringBuffer buff=new StringBuffer();
iceCreamGroup x=new IceCreamGroup();
for (int i=0;i<someNumber;i++) {
      buff.append(x.getIceCream (i));
      }

Speed

One has to assume that a hand-held device has a
slow processor.


An interesting point that is made at the Lurker's site
is that perceived speed is more important than the
actual time it takes to do something. Consider how
an hour glass symbol can make a wait seem OK!

If you have used loops in graphics you know they
can eat up processor power. The Lurker's site
suggests removing any unneccessary evaluations
from loops.

The Lurker's Example

for (int i=0;i<theVector.size();i++) {
      Object x=theVector.elementAt(i);
      }

// calculate Vector size( ) before using it in the loop

Alternative

int theSize=theVector.size();
for (int i=0;i<theSize;i++) {
      Object x=theVector.elementAt(i);
     }

Another good tip, is to, where possible use arrays
instead of Vectors or HashTables. Underneath these
objects, arrays are used anyway so to escape the
overhead of the objects try to use arrays only.

A fifth rule Lurker's offers is to use local variables
instead of instance variables which take a little longer
to process.

Size

Phone companies will often impose size limits on
applications.
Lurkers suggest minimizing the number of classes in 
your jar file. To quote "(a) Only include the classes you
need in your final jar, (b) consider removing "bells and
whistles" functionality, and (c) refrain from using inner
classes."

Lurker's seventh rule is to use the obfuscation function
to reduce the size of the download.

The final tip is to reduce the number an size of resource
files such as images.


Assignment

1 ) Run the Minimal MIDlet above. Comment out
each of the pauseApp( ) and destroy( ) app methods.
What is the error report given at the WTK console.

2) Create a new project with the WTK toolkit. You
may use the Primitive MIDlet above as a template.

a ) Comment out each of the pauseApp( ) and destroy( )
app methods. What is the error report given at the WTK
console.

b) Recreate the primitives output this time using wrapper
classes supplied in the API to wrap different values
that are good representatives of their types.

c ) Create a method in the MIDlet that uses the Date( )
or Calendar class to return the date.

3) Inside the Primitive MIDlet create a method that
returns the Date and call it within the output that is
put to the device screen.


Example

String td = " Time and Date " + myGetDateMethod( );


Read the following if you want or need a head start on
this.

Time Saving Tips

// You will probably use the Calendar class that you don't instantiate.
// Instead you use the
getInstance( ) method. I then called getTime( )
// on
the object. The method will be placed in the MIDlet at the same
// scope as the other methods. You will
need to import the java.util package.


Example

import java.util.*;

class theTime {
public static void main(String [] args){

System.out.println("Day, Date, Time & Year: " + Calendar.getInstance().getTime());
}
}