Week 19: Introduction to Java ME
Last week we considered the different mobile development technologies available. This week we will focus specifically on possibly the most widely used: Java ME or Java Micro Edition.
Background
What is Java ME?
Java ME is a cutdown version of the full Java programming language, cut down so that it will fit onto mobile devices with limited memory and processing power. The first thing to make clear is that there is not one single version of Java ME. There are two editions, with different target devices (ref: Sun):
- Connected Limited Device Configuration (CLDC), designed for smaller devices such as mobile phones;
- Connected Device Profile (CDC), designed to be used for developing software for home electronic devices (ref Sun) such as DVD players.
Configurations and Profiles
A typical phone supporting Java ME would include not only the CLDC, which is referred to as a configuration, but also a profile, the most common of which is the Mobile Information Device Profile (MIDP). The difference between the two is as follows (ref: Sun):
- A configuration such as CLDC consists of the absolute basic features of the Java language (see documentation here);
- A profile such as MIDP adds more advanced features such as graphics to the basic capabilities provided by the configuration (see documentation here). Different profiles exist: MIDP 1.0 provides basic graphical capabilities while MIDP 2.0 adds more advanced features such as specialised features for game development.
The advantage of having both a configuration and a profile is that it allows mobile manufacturers to add different profiles (each profile might have different graphical capabilities for example) to the base configuration depending on the capabilities of the device. For example a basic phone could support CLDC 1.0 plus MIDP 1.0, while a more advanced phone with greater graphical capabilities could support CLDC 1.0 plus MIDP 2.0.
JSRs - Java Specification Requests
The combination of a configuration and a profile, such as CLDC and MIDP, provides the most commonly needed features in mobile development, such as a graphical user interface and date/time manipulation. However there are a series of add-ons which cover more specific requirements of mobile applications, such as 3D graphics, Bluetooth connectivity, or location based services (being able to find your position on the earth with GPS, as we talked about last week). Each add-on is referred to as a JSR or Java Specification Request, and each is numbered. Examples of JSRs include:
- JSR 75 - file handling; the ability to create files on the phone
- JSR 82 - Bluetooth connectivity
- JSR 172 - XML parsing and web services
- JSR 179 - location based services
- JSR 184 - 3D graphics
- JSR 226 - Scalable Vector Graphics
Java bytecode
It is important to realise that the phones do not actually run Java programming code directly. Java programming code (of which you will see an example below) is compiled to a binary format called Java bytecode, which is more optimised to be run directly by the phone. Java capable phones include a so-called Java Virtual Machine, a piece of software which actually runs the bytecode. You can think of it as being a bit like a software version of a CPU, so you have a Java Virtual Machine running Java bytecode, rather than an Intel CPU running Intel machine code.
Developing for Java ME
OK, that's enough background, now we'll move on to how to actually develop a Java ME application. As mentioned last week, you need to download a development environment to your computer. The development environment includes a graphical representation of a phone, which you can use to test out your application. For Java ME, the environment to use is the Sun Wireless Toolkit or WTK. This is available here.
Developing a Java ME application using the WTK
Once you have downloaded and installed the WTK, run it. Select the "New Project" button and enter a name for the project. This will create a new project. Note that the WTK is not a full Integrated Development Environment: you need to write your source files in a text editor like Notepad; but it does allow you to compile and run your Java code.
Where is the project created?
- Find the folder where the WTK was installed, this might be something like C:\WTK2.5.2.
- Inside this folder you'll find another folder called apps, where all your mobile applications are stored.
- Then inside this folder you'll find another folder specific for your project.
- The project folder contains various folders, for different aspects of your application. For instance the res folder contains any embedded images required for your application. The src folder is the most important, as the Java code for your application must go in here.
A first Java ME application
Here is the Hello World for Java ME:
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
public class HelloWorld extends MIDlet
{
TextBox txtName;
public HelloWorld()
{
txtName = new TextBox("Enter your name","",50,TextField.ANY);
}
public void startApp()
{
Display display = Display.getDisplay(this);
display.setCurrent(txtName);
}
// Midlets must have this even if blank - code to handle
// pausing the application
public void pauseApp()
{
}
// Likewise midlets must have this even if blank - code to handle
// destroying the application
public void destroyApp(boolean unconditional)
{
}
}
To explain this code:
- A MIDlet is a Java ME application for a mobile device. All MIDlets must
extend from the MIDlet class, e.g.
public class HelloWorld extends MIDlet
You can think of HelloWorld as being the name of the program. - The public HelloWorld section of code is called the constructor. This is the piece of code which runs when we first run the application. In it we create a text box with a label of "Enter your name".
- startApp() is the code which runs when the application is
started, or restarted. A user might restart an application if they switch
to another application and then switch back to this one. Thus,
startApp() differs from the constructor, in that the constructor only
runs once (when the application is first run) while startApp() runs
every time the user switches back to this application from another.
startApp() here does the following:
- Gets hold of the phone's display, with:
Display display = Display.getDisplay(this);
- and sets the display's current item to be the text box.
- Gets hold of the phone's display, with:
- pauseApp() and destroyApp() are blank in this example, but inside them you would write code to handle the application being paused (e.g. when switching to another application on the phone) and destroyed (this occurs when the user quits the application) respectively.
Making the application do something
So how can we react to user input? The next example demonstrates this:
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
public class Ex2 extends MIDlet implements CommandListener
{
TextBox name;
Command ok, quit;
public Ex2()
{
name = new TextBox("Name","",50,TextField.ANY);
ok = new Command("OK", Command.OK, 0);
quit = new Command("Quit", Command.EXIT, 0);
name.addCommand(quit);
name.addCommand(ok);
name.setCommandListener(this);
}
public void startApp()
{
Display display = Display.getDisplay(this);
display.setCurrent(name);
}
public void commandAction(Command c,Displayable s)
{
if(c.getCommandType() == Command.EXIT)
{
notifyDestroyed();
}
else if (c.getCommandType() == Command.OK)
{
Alert a = new Alert ("Hello!",
"Hello " + name.getString(), null, AlertType.INFO);
a.setTimeout(2000);
Display.getDisplay(this).setCurrent(a);
}
}
}
To explain the new features of this code:
- We create two Command objects, representing OK and Quit
options on a phone user interface. When we create a Command object, we
supply three parameters:
- The "OK" and "Quit" strings represent the text which will actually appear on the phone;
- while the Command.OK and Command.EXIT represent what type of command it is. The command type is used for such things as associating the action with a button on the phone.
- The final parameter (zero here) represents the command priority. Commands may have high or low priority. The phone will always try and display high priority commands at the bottom of the main phone screen, while lower priority commands might appear in a menu. Phones can only display two commands at a time, so if you try to add more than two, the phone will create a menu to display all but the highest-priority command. Lower numbers indicate higher priorities.
- We add the commands to the text box. The idea is that the user fills in the text box and then selects OK to move onto the next screen, so we need to associate the OK command with the text box.
- The line:
name.setCommandListener(this);
sets the command listener for the text box. The command listener is the object that will react to the user clicking OK or Quit. Here, we specify this to indicate that it is the current object (i.e. the MIDlet) which will act as the command listener. - The commandAction() method is the code which runs when the
user presses OK or Quit. It takes two parameters:
- Command c - the Command which was selected (here, it would be either the ok command or the quit command)
- Displayable s - the item currently being displayed, e.g. a TextBox. We can use this to react differently depending on which item is currently being displayed.
- Inside commandAction() we test whether the user selected the command with a type of OK, or the command with a type of EXIT. If they selected the EXIT command, we quit the application (notifyDestroyed() does this)
- We then display an Alert which is a short lived message to
the user which appears then disappears again. This Alert greets the user
with a Hello message, along with their name. It takes four parameters:
- The first parameter ("Hello!") is the title bar for the alert;
- The second parameter is the actual message; here it is:
"Hello " + name.getString()
which is the text "Hello" plus the text currently inside the text box name; - The third parameter represents an image we might want to display with the alert. Here, null indicates that there is no image.
- AlertType.INFO is the type of alert; others include WARNING, ERROR, CONFIRMATION or ALARM (see here)
- Alerts have a setTimeout() method which controls how long they appear for. You supply either a value in milliseconds, or a special value Alert.FOREVER which indicates that the Alert is to be displayed until the user manually dismisses it. In this example, the Alert appears for 2000 milliseconds (i.e. 2 seconds)
Exercise
Download the WTK (from here) and install it to your computer; the C: drive is probably best.
- Create a new application in the WTK. Write code to display a text box with a label of "Enter your password".
- Add OK and Quit commands to your application. If the user selects OK, display an alert box which reads "You entered the password " plus the password that the user entered.
- Try adding a Back command (a Command with a command type of Command.BACK) as well. What happens? Play around with the command priorities to see how the behaviour differs.
- Modify your commandAction() method so that if the user enters
"Java123" for the password, an alert box reading "Correct password!" appears,
while otherwise, an alert box reading "Wrong password!" appears. Use an
if statement, similar to the if statement in JavaScript or PHP. You can
test for a string being equal to something using equals(), e.g.:
if (text.equals("hello")) { // do something } - Advanced (for people comfortable with programming only!):
Write an application which asks for and validates both a username and
a password. The correct username and password should be "admin" and "Java123"
respectively. You need to:
- Create two text boxes, one for the username and one for the password;
- Initially display the username text box;
- Create OK and Quit commands again, and add them to both boxes, so that the phone can respond to the user entering something in either box;
- Remember to use addCommandListener() on both boxes so that the commands for each text box are linked to the commandAction() method;
- Inside commandAction(), test which text box is the currently displayed text box. You can use the parameter Displayable s to test which text box is currently displayed. If s is equal to the username box, display the password box instead. If s is equal to the password box, you know the user has entered both the username and password, so use an if statement to check that the username and password are 'admin' and 'Java123' respectively. Display an appropriate Alert depending on whether or not the login details were correct.
- Add a Back command to the Password TextBox. If the user selects the Back command while the password text box is being displayed, it should take them back to the username text box.