Mobile Information Device Profile (MIDP) Tutorial

As I am porting Tetris to mobile devices, using MIDP, I got to know how MIDP works and what features are important, and which features aren’t available to the programmer. This tutorial will guide you in your first steps with MIDP. I hope you can learn a thing or two here.

I will (try to) teach you MIDP 2.0, without using any GPRS, Bluetooth, Irda, MMS or anything, so I won’ talk about CLDC.

I will also assume that you have some good experience in Java programming, including Java Swing, as I will try to make some links between the Swing classes and the javax.microedition.lcdui.* classes.

At a glance

The key to learning about new technology is knowing where to start.

MIDP stands for Mobile Information Device Profile. Thats a big mouthful. But what does it mean? Modern phones that implement MIDP 1.0, 1.1 or 2.0 are capable of running MIDP “programs”. This means that you can program in Java, and run the code on a phone that supports MIDP. So you can actually port already written applications to MIDP or write brand new ones just for mobile devices. You still have the idea of classes and objects, the language itself doesn’t change at all. It’s Java – well actually pre-“Java 5” Java, so it’s the Java almost everyone knows. The only really different thing is the API, so the concrete classes have other names, behaviours and uses, specific to mobile phones (and other mobile devices, but in this article we only discuss mobile phones).

At first, this totally new API may scare you off a bit. Don’t be scared though. There are many classes you are familiar with already. Let’s take a look at the MIDP API documentation. Look at the packages in the main (right) frame. These all sound quite new. Only the last three are known to you: java.io, java.lang and java.util. Try clicking java.util. Look at the classes showing up. Wow, we have the Date, HashTable, Random, Vector, Timer, Stack,… classes! This will make programming a lot easier!
But then again, we have some classes that we can’t use: ArrayList (although virtually the same as Vector), Color (I suggest you recreate this class from J2SE source code), javax.swing.Timer (which includes pause(), resume() and setDelay(), we have to live with this…). But don’t lose your hope yet, programming MIDP is not so hard as it seems.
Remember, the API Documentation is your friend. Go ahead and read the package description, class and method usages. They got me up and running on how to use the software. For those still quite unsure on how to begin, continue reading ;-).

Helper applications

So how do you start coding for MIDP? As I was used to programming in NetBeans the solution was quite straightforward: NetBeans Mobility Pack. This includes the J2ME compiler, class libraries, documentation, … and four NetBeans phone emulators (at the time of writing).
I hoped to find something similar for Eclipse, DSDP, but they only support MTJ. So let’s continue using NetBeans.
Most phones also have SDK‘s for most of their phones, so check out the Developer’s section of your phone manufacturer. It’s always good to see more realistic emulators for your own phone, instead of the (sometimes) buggy ones of NetBeans.

What you need to know

We now go deeper into the structure of programs for MIDP 2.0. We call these strange creatures MIDlets. Notice the analogy to Applets, which were applications running in web browsers, we now have MIDlets.
The basic and topmost class for MIDP is therefore the MIDlet class. A MIDlet is like a window application: it can have multiple windows (called Displayables), each containing a variety of items like buttons, textboxes and labels.
A MIDlet can have many Displayables, but only one Displayable can be shown at a time.
There are two types of Displayables in MIDP 1.0:

  • Canvas
  • Screen

We will now shortly discuss these.

Canvas

The Canvas class provides low-level API calls to the system’s drawing and event dispatching routines. The interface for this class consists mainly of three categories of methods: drawing ((re)paint()), event handling (keyPressed(), getKeyCode(), …) and general display functions (hideNotify(), setFullScreenMode(), …). Reading the method descriptions should get you far to know how to use them.
Notice that you must sublclass Canvas in order to use it, so it’s not an out-of-the-box class, like JPanel, on which you can just add some elements. When subclassing, don’t forget to override the paint() method. Just like JPanels have a paintComponent(Graphics g) method, Canvas has a paint(Graphics g) method. This Graphics object is quite alike the one found in javax.swing. A few differences are that the setColor() method takes RGB values instead of a Color object, as the Color class doesn’t exist in MIDP. There is also no Graphics2D.

Notice that when you are creating a game, you might consider using GameCanvas, as this supports for offscreen buffers and keypress querying, if you could use that. By the time I found the GameCanvas class, I had already implemented my Tetris game (to be published later), so you can work without it too for games.

Screen

Notice that a Screen does NOT have the paint() method, like Canvas has.
So we must add things differently to a Screen. Notice that the Screen class has no public methods or constructors, so its just a base class for types of Screens.
MIDP 1.0 defines 4 Screens: Alert, Form, List and TextBox. You can use these classes out of the box, so you don’t need to subclass them.
Alerts are used to inform / warn the user about certain events taking place, compare with the JOptionPane.showMessageDialog().
Forms give the programmer the ability to pack a small amount of widgets (buttons, labels and textfields for example, these are called Items).
List provides the user with a list of choices. The user can then easily choose an option.
TextBoxes are used to get input from the user. A full screen is used to query e.g. a name from the user for a highscore table. Similar to JOptionPane.showInputDialog().

Note that the discussion of Screens is very limited, you must experiment with the elements yourself to get a grip of what they can do and how easily it’s done.

Using Displayables to get around

Now that you know which Displayables are available, how will you ever combine them to create a working application?
Here another class comes to the rescue: Display. Every MIDlet has its own Display object.
The Display manages the display and input devices of the system. So, if you want to put a Displayable on the screen, this is the class to talk to. If you want vibration or color effects, talk to Mr. Display. Also, if you need information about whether the display supports colors or not, what the default foreground color is, etc.
Now to return to our Displayable discussion. We want to show e.g. a TextBox. We create a TextBox:

TextBox box = new TextBox("Enter your name", "", 30, TextField.ANY);

This creates a textbox with the title “Enter your name”, no (“”) default entry, maximum size of 30 and no input constraints (ANY). Notice that nothing happens if you code this inside the constructor of your MIDlet for example. Just constructing the object isn’t enough. We need to tell the Display that this Displayable (as a TextBox is indeed a Displayable) needs to be shown on the display.
The next code sample will teach you how to do this:

TextBox box = new TextBox("Enter your name", "", 30, TextField.ANY);
Display theDisplay = Display.getDisplay(this);
theDisplay.setCurrent(box);

Notice on line 2 that we reference this. this is the MIDlet object, getDisplay() needs a MIDlet as its argument, to be able to retrieve the correct display for this MIDlet. Line 3 sets box as the new Displayable to be displayed. Notice that MIDP does not provide certainty of when the Displayable will be shown on the display, it’s up to the underlying operating system (of the phone itself), to provide a best-effort service. I stress again that only one Displayable can be shown on the display at any time.
We can shorten the code:

TextBox box = new TextBox("Enter your name", "", 30, TextField.ANY);
Display.getDisplay(this).setCurrent(box);
MIDP screenshot 1: TextBox
Figure 1: a simple TextBox

but any novice at Java figured that out already, so I’m always going to use the more compact notation from now on.

Figure 1 shows how this looks on the Nokia Series 40 SDK emulator. Pretty cool hey?

This is the MIDlet file:

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

public class Test extends MIDlet {
    public Test() { /* Empty constructor */ }
    public void startApp() {
        TextBox box = new TextBox("Enter your name", "", 30, TextField.ANY);
        Display.getDisplay(this).setCurrent(box);
    }
    public void pauseApp() {}
    public void destroyApp(boolean unconditional) {}
}

Notice here that the startApp() method logically gets executed every time the operating system wants the application to start. So we just put the code there.

Now the next problem is how to quit our application. Because, the only Options i have on e.g. the S40 SDK is to Insert a smiley or to use the dictionary. How do i quit the application without pressing the red “Destroy application” button? (Also known as the red “hang up” button)
Or how do I let the user choose he’s had enough of this Screen and needs the Canvas back and vice versa? This is all done using Commands.

Commands

One of the first things I didn’t really get is how Commands worked, and what they did exactly. I found out rather quickly when my application didn’t have a working Exit function. In the next paragraph I’ll do my best do explain what Commands are.

Every Displayable can have a list of commands. You can see this as e.g. the File menu in a word processor, but suppose that you only have one menu. This would be the menu containing all possible Commands you can give the current Displayable, or if you have an application with one main Displayable (which will be the case mostly), then this menu would contain an Exit command, a Settings command, an About command perhaps and maybe many others.
I hope you now understand what commands are and what they are used for, if not, feel free to read the API documentation, as it is a source of well-written but compact descriptions of classes and concepts.

Now to continue on commands. Lets return to our Test MIDlet with the sole textbox. We will want an “Ok” command to let the user confirm that he has entered the desired name. Then we display a goodbye message, notifying the user the application will terminate. The application should then (after the last confirmation of the user) cleanly terminate itself.

I provide the source code first, then discuss every step of it – here [#] will indicate that I’m talking about line #. Finally, I will show the three screens which we see during the application.

Source Code

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

public class Test extends MIDlet {
    private TextBox box;
    private String suppliedName;
    
    public Test() {
        box = new TextBox("Enter your name", "", 30, TextField.ANY);
        box.setCommandListener(new TestCommandListener());
        box.addCommand(new Command("Ok", Command.OK, 1));
    }
    
    public void startApp() {
        Display.getDisplay(this).setCurrent(box);
    }
    
    public void pauseApp() {}
    
    public void destroyApp(boolean unconditional) {
        // Nothing to destroy, objects get removed by garbage collector
        notifyDestroyed();
    }
    

    private class TestCommandListener implements CommandListener {
        public void commandAction(Command command, Displayable displayable) {
            suppliedName = box.getString();
            showLastScreen();
        };
    }
    
    private void showLastScreen() {
        Alert alert = new Alert("Bye", "Bye, " + suppliedName, null, AlertType.INFO);
        alert.setTimeout(Alert.FOREVER);
        alert.setCommandListener(new CommandListener() {
            public void commandAction(Command command, Displayable displayable) {
                if(command.equals(Alert.DISMISS_COMMAND))
                    destroyApp(true);
            }
        });
        Display.getDisplay(this).setCurrent(alert);
    }
}

Explanation

Feel free to open another window to easily switch between the code and the explanation. I hope you’re into some named and anonymous inner classes, because we’re stuffed here!
[5,6] We keep track of the TextBox and a string to contain the TextBox string. Okay, it’s somewhat overkill to duplicate the information, but this is just for educational purposes.
[8-11] Notice how the constructor has changed a bit. We now move the TextBox creation to the constructor, which is a better place than in the previous example. We also define the command “Ok” for that Displayable (i.e. the TextBox). We also define that an object of the class TestCommandListener listens to the command actions, generated by ALL commands associated to this Displayable. So every action performed (cfr. ActionListener in Swing) by the Displayable is handled by the CommandListener. Notice that on line 25 we have the definition of the – named inner – class TestCommandListener. The only thing the listener does is storing the name supplied by the user (using box.getString()) and signal the MIDlet it should show its last screen. The showLastScreen() is my own written method, it is not at all a default way of handling things, I just thought this was a clear way to show you the flow.
[18] We have no special actions for when the application is paused, as we have no timers to pause, etc…
[20-22] When the MIDlet thinks its time to destroy itself, this method gets called. This is a tear down operation, i.e. open resources and handles should be closed, settings saved, etc. We have nothing to save, so we’ll just signal the operating system that we have successfully destroyed ourself by calling notifyDestroyed(). The operating system takes over from there and the application – i.e. the MIDlet – gets shut down.
[32-41] The last screen just provides an Alert, this is a non-interactive screen, which shows some information. We will salute the user with a simple “Bye”, and wait for him to press the (e.g.) Dismiss button.
[34] The Dismiss Command is implicitly added to the Alert if the timeout is set to Alert.FOREVER.
[35-40] The command listener is set on the Alert by default. If we don’t specify a handler for the Alert, the Display will just return to the previously installed Displayable, which would be the TextBox again. We don’t want that, so we listen to commands ourselves. We catch the Alert.DISMISS_COMMAND and destroy ourselves if that action takes place.
[41] Everything is set now to set the Alert as the current Displayable of the Display.

Screenshots

MIDP screenshot 2: TextBox with Ok button
Figure 2: TextBox
with Ok button
MIDP screenshot 3: Alert with name
Figure 3: Bye John!
MIDP screenshot 4: Closing application
Figure 4: Closing down

Phew, we got through that piece of code. I hope you’re still alive and reading :oops:.
I hope you can get the code working on your system/emulator/phone, if not, don’t hesitate to ask questions in the comments. We’ll now continue showing the screenshots.
The first screen we see is now Figure 2, a modified version of Figure 1, now containing an Ok button (for the Ok command of course) and a name filled in.
Once we press Ok, we see the Alert screen, saluting us. You can see this on Figure 3.
Once we press Dismiss, the application is shut down, as you can see in Figure 4.

Storing data

All is well till now, you’ve written your own little MIDlet already – yes you’re of the fast learner type – but now you wish to – for example – store highscores or save a state to the phone memory when the application quits. Well, MIDP has a (rather small) solution for this.
The RecordStore classs provides every application with a way of storing data using the MIDlet name and a string you provide. There is a lot of finesse in this area, so you should better read the documentation for this. This area is also quite complex, for the RecordStore only allows you to write byte[] so you must use the ByteArrayInputStream and ByteArrayOutputStream classes of the java.io package. If you are not familiar with this, consider using the example class given in the documentation. It provides means for storing high scores into the database, but its structure may suit you to store different things.

An easier way?

Now that I’ve expained this all, you may be wondering what easy way there would be… Well, unfortunately for you, I’ve kept a little secret about NetBeans. It has a Visual MIDlet builder, just like you have a visual JFrame or JPanel builder. How awful that I have kept this information secret to you!! I know… šŸ˜ˆ
The thing about most of these GUI builders (and in this case, the order in which to display Displayables and the linking commands is also included) are not so very clean coded. For example if you use the GUI builder in swing, you will never actually use the Event/Listener system, but instead NetBeans will map events and listener functions directly with each other, which is in my eyes – as humble as I may be – awful coding.
So my advice to you, go with the long and slower approach, you’ll have more feeling into MIDP, and feel like you have much more control. NetBeans looks a lot like Visual Studio in this mode, so lets avoid that M$ flavour shall we?

Conclusion

There are three package clusters left to be discussed: Networking, Audio and Public Key. Once you know how to use the classes presented in this article, I think you’ll get the hang of these three less-frequent packages. The sound is rather optional to me as I don’t like applications making lots of noise…

What to conclude… Well I hope we can all agree that programming for MIDP is not so hard as it seems, if you have some good knowledge of Java and Swing. I’ve ported my own Tetris version already but it still needs some tuning. Its thanks to Tetris (and by buying a new cell phone) that I’ve seen the light about MIDP. Notice that there may be lots of design flaws in the applications provided, I am only programming MIDP for a few days, so don’t shoot me just yet.
I’ve written this tutorial as fast as possible AFTER understanding the concepts myself, so that I could provide you with an intuitive approach, rather than a details-first approach.
Hoping to have served you, I greet you!

Happy MIDPing!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s