In the first two modules we dealt with MIDP 2.0 fundamental concepts and we started programming a simple MIDlet. We talked about the midlet-device interaction lifecycle and we developed a simple application. In this module we’ll dive into MIDP 2.0 programming, beginning with the high level API for midlet GUI creation. This is an important module since it covers the fundamental widgets we can use in a portable midlet application. It’ll be shown how to use these widgets by creating a simple midlet which simulates a user registration.
High level API
As we’ll see in the present and in the next module, MIDP 2.0 admits two different ways to create midlet GUIs. They can be classified as follows:
- high level API
- low level API
High and low level APIs differ from the portability point of view. The concept of high level API is very similar to the Abstract Window Toolkit (AWT) concept in J2SE. As we know, AWT is the oldest Java framework for developing application GUIs (included in JDK since version 1.0). The key concept here is that the JDK includes a set of classes representing a set of widgets. Different Operating Systems (OS) may display the same widget in different ways. From the API point of view a button is represented by the java.awt.Button class in every OS but its actual appearance is OS dependent (a Windows button is different from a Solaris button). Hence the adjective “Abstract”. Swing widgets came with the 1.1 JDK version and approach the matter in a different way, using a common canvas (the transparent Component) in which every look-and-feel manager creates its own widget set. In this case, every feature previously managed by the OS must be managed by the programmer.
High level API is a set of widget classes we can use to create portable midlet GUIs, since it delegates the appearance and user interaction to the underlying device. As we’ll see later, an operation selection command may appear in different ways on different devices. Just think about devices with a pen or with a complete keyboard.
The way the user interacts with a command on a particular device must be matched by the corresponding midlet but we, as programmers, don’t want to create different classes for different devices. The high level API allows us to create GUIs in an abstract way, delegating the distinctive appareance and user interaction to the device.
In the next module we’ll study the low level API, which grants us more power at the cost of a portability loss. The low level API permits us to draw geometric shapes on a Canvas. We should keep in mind, for instance, that not all screens share the same dimensions. A rectangle centered on a screen may not be centered on a different device, because screen sizes may be different; color depth may change. This may have consequences also from the usability point of view if the rectangle is, for instance, a button we can select with a pen. The low level API, as we’ll see later, permits us to create games because it gives us more control on the device’s specific screen.
Which set of API is the best ? Well, it depends. If we have to manage a simple and user friendly GUI, maybe the high level API is the best choice. If we need more control on the device’s screen the low level API is the only option. In general terms, the high level API is employed to create list and menu items (standard objects), while the low level API is used for specific functionalities, such as graphics, games and things like that.
High level API architecture
In this module we’ll describe some of the fundamental widgets we can use with the high level API, as shown in the class diagram in Fig 3_1. We’ll analyze some classes in a detailed way but, for now, we just want to look at an overview of the architecture. What we don’t see in the diagram is the java package they belong to, which is javax.microedition.lcdui. As we can see in the diagram, many classes are a realization of the Displayable abstract class, which is a class describing all common properties and functionalities such as:
- the title
- the Ticker (a scrolling text)
- command management
common to every widget that can be displayed on a display. For every widget on the display, we can set a title, a scrolling text and we can manage its events (to whom we refer here as “commands”). As we’ll see later, the Display class has a method we can use to show a specific Displayable on the screen. We used the following method:
public void setCurrent(Displayable nextDisplayable)
also in the first midlet we developed in previous modules. If we look both at the javax.microedition.lcdui package and at our diagram, we can notice that there are two different Displayable realizations, which are described by Screen and Canvas classes. These two classes can be held as a share-point between high level and low level APIs. We can say that Screen is the parent class of all classes for the high level API, and Canvas is the parent class for low level ones. In the next module we’ll see that a Canvas permits us to draw on the screen and so grants us more control on it. We’ll see now in detail some Screen realizations which are described by TextBox, Alert, Form and List classes. If we read the API documentation , we can notice that a Screen doesn’t give to the Displayable class any specific method or ability. It’s just a class grouping all the widgets which can cover completely the display. That means, for instance, that one Form and one TextBox can’t be displayed on the screen at the same time. If we need to have more than one widget displayed on the screen we can use the Form widget, which is a container of specific Item realizations. The Item class is not linked to any of the previous classes, but it’s a class containing common characteristics of every widget we can put on a Form. We’ll see some of them in our example at the end of the present module. New to the 2.0 version of MIDP is the CustomItem class, useful for creating specific Item realizations using a technique similar to the one we would employ dealing with the Canvas class in the low level API.
In the previous chapter we saw that a Displayable class describes all the features shared by every widget we can put on a device display. One of them concerns the capability to select a specific command through a device button, which is often called soft key. Every widget can have a set of commands the user may select in its usual way. The Displayable class must have a way to register a command, which will be invoked when the soft key is selected. In order to do that MIDP uses the delegation model, included in J2SE since version 1.1 as a consequence of JavaBeans specification. This model tells us that if we want to listen to a specific event, we have to implement an interface which encompasses all the callback methods the event source may call to notify the specific event. MIDP 2.0 follows the same line. Every possible action is described by a different Command object we can register to a specific Displayable using the method:
public void addCommand(Command command)
The add prefix tells us that a Displayable can have more than a Command which is described by the following important properties:
- the label (short and/or long)
- the command type
- the priority
The label property is the one we can see on the device and may be short or long. Not all devices manage both descriptions, but they show what they consider to be the best presentation of the command. The important information is the command type, which allows the device to display them in different ways. We’ll understand better the meaning of command type by reading the following list (part of Command class constants):
The command type allows the device to display commands in the best way. For instance, a BACK command may be shown as an other command, or managed by a specific soft key. Furthermore, if a device uses a specific button for exiting from an application, a command of type EXIT will be associated with that button, and so on. So, the type of the command is used by the device to display the command in the best way and also, as we’ll see later, to tell a command from another in the callback method. The priority information is used to assign a different weight to different commands sharing the same type, but with different priority in the application context.
Thus if we want to link a set of commands to a specific Displayable we have to create a Command instance and then we have to register them to the Displayable. The next step deals with the command selection management. In order to do that, following the delegation model rules, we have to implement a specific interface which encompasses all the callback methods. We’re talking about the CommandListener interface and the method:
public void commandAction(Command c, Displayable d)
The next step is to register the CommandListener implementation using this Displayable class method:
public void setCommandListener(CommandListener l)
We followed the same steps in the second module’s example (see List3_1.txt). From the command management point of view, we can see that our AlarmClockMIDlet implements the CommandListener interface. Therefore it’s entitled to manage Commands from a Displayable. We notice that our class implements the interface, and therefore it contains the method commandAction() the interface describes. Command objects are created in the startApp() method and then registered to the Displayable which in this case is represented by a Form instance. We notice how we add Command to the Form and how we register our midlet realization class as its CommandListener. Command management is done into the commandAction() method which is called in case of command selection. The callback method invoked is always the same, so we need a way to tell a command from another. In our example we used the label information, but we could use the command instance as well. In this case we didn’t do that because we didn’t have the command reference as an instance variable. It’s not important the way we tell different commands into the commandAction() method. For each command we take different actions. In our midlet we’re now able to understand the way to show a Displayable on the screen using the Display class, which has two different overloaded setCurrent() methods. The first one:
public void setCurrent(Displayable nextDisplayable)
allows us to show on the screen the Displayable passed as parameter. This version:
public void setCurrent(Alert alert,Displayable nextDisplayable)
allows us to show a Displayable after an Alert, which is a specific Screen realization for user messages notification.
As we said before, every Displayable may manage a Ticker object which describes a scrolling text (whose appareance is device-dependent). The Ticker class is an object which wraps a text but it doesn’t include any information about character font, speed and other features related to the way the text should be displayed. This is a device responsibility (in accordance with the high level API approach). To show how we can use a Ticker object we’ll start developing our user registration midlet. This is a midlet whose task is to insert some information about different questions which can be displayed using the Ticker. To create the Ticker we can simply use its constructor, specifying the string to show. We can then add the same Ticker reference to every Displayable, changing the string to show (the specific question). To set the Ticker we can use the method:
public void setTicker(Ticker ticker)
common to every Displayable realization. It’s important to remark that the same Ticker reference can be associated to different Displayable. Not every widget is capable of that.
The Choice interface and the List class
Before continuing with the developement of our application we’ll look briefly to the Choice interface, which we’ll employ often. If we read the documentation, we’ll notice that it lists all the methods related to a user selection. Choice implementation classes are List and ChoiceGroup. The first is a Screen and so it can be put on the device display, the second is an item and so it must be placed inside a Form. The Choice interface describes methods about:
- adding or removing user choices, such as labels and images
- telling the user selection
- setting the fit policy
As we’ll see in our example – employing the List class-, the Choice interface describes methods to add and to remove options that we can represent as labels, images and information about their activation. If the user selection is done using a command, the Choice interface has methods to tell which is or which are the user selections. The fit policy is the way the List or others widgets can fit text and labels into their available space. The constants set described by the Choice interface is very important, as we’ll see later.
As we said, the List is a Choice implementation and it can be used to represent on the display the list of possible user choices. Creating a List is very simple, as shown in our example. We can use two different overloaded constructors; if all possibile choices are immediately available we can use the following one:
public List(String title, int listType, String stringElements,Image imageElements)
where every choice is represented by a String array with option Image elements. If choices are not immediately available because they depend on midlet execution (for instance: available bluetooth devices to connect with), we can use this constructor:
public List(String title,int listType)
We can always add later the choices with the Choice interface methods the List class implements.
In our example we create a List with three different options which we’ll use to insert data about the user name, birthdate and sex using the proper widget. Then, we register commands of type OK and of type EXIT.
Maybe, the most important List constructor parameter is the listType. Possible values are Choice constants values and they are:
Every list type allows a different option selection. The first one is probably the most common option. It means that the selection is the one currently highlighted when the user presses a soft key. One choice is always highlighted at all times. The exclusive list type allows users to choose one selection in a way very similar to the radio-button-set’s. Every device can display this kind of list in its own manner, but the appearance should suggest to the user that just one option must be selected. For a better understanding of this kind of list type, we can say that to make a choice we must first mark it and then press ok. In the implicit case, mark and selection actions occur at the same time. The last possible list type value describes a list which encompasses more than a single choice. The appearance will be similar to a check boxes set where more that one checkbox can be selected. When to use a list type or another? Well, for a menu selection maybe the IMPLICIT value is the best choice, as in our example. If we have to select exclusive choices, as we’ll see in our user sex selection, the second choice is certainly the best. If we have to select more than one value, we’ll use the multiple one. This is the case, for instance, of a user interest set selection.
We’ll see Image management in detail in the next module of this course.
Using Forms and Items
As we saw in our class diagram, high level API contains a Form widget as an Item container. We can say that an Item is a way to manage a specific kind of data. We can have Items for images, for texts, for calendar values and so on. We can group these items inside one Form, as we can do in one HTML form in a Web page. Creating a Form is very simple. We just have to create a Form object, and then add to it different kinds of Items using its append() overloaded method. For a better knowledge about all types of Items we advise to read the API documentation. In our case we’ll see TextField and DateField in order to manage text and calendar information, respectively. As we see in our example, using this kind of objects is straightforward. What we want to remark here is the way midp manages different kind of data a user may digit with a very simple keyboard such as a cellular phone’s one. We know that a user may insert characters, numbers, email addresses, phone number ans so on. The phone manages this automatically. This means that we cannot insert a letter when we digit a phone number to start a phone call. When we use a TextField to insert some data, we want the possibility to specify the kind of data we intend to manage. In order to this, we are given a set of constants – belonging to the TextField class – that represent the type of data we can insert into a TextField item. If we read the API documentation, we can notice:
with obvious meaning. TextField class also contains constants we can use along with the previous ones, using the or | operator and that we can use as modifiers. They are:
For instance, if we need to insert a text as a password, we can employ this combination:
The SENSITIVE and the NON_PREDICTIVE modifiers are very useful. The first one tells the device that the text the user inserts is a sensible datum and so it shouldn’t be stored into the device itself. The second one is a way to tell the device that the text shouldn’t be self-completed (i.e. reading from a dictionary or things like that). As we can see in our example, creating a TextField is a very simple task, using its only constructor:
public TextField(String label, String text, int maxSize, int constraints)
The first parameter is the label we can use to describe the datum and the second is its initial value. With the maxSize parameter we can set the maximum number of digits we can insert. The last parameter is one we already talked about. In our example we insert a name, so we can use the ANY constant with the INITIAL_CAPS_WORD modifier, which automatically puts the first letter in upper case.
The DateField object is very similar to the TextField. We notice the following two constructors:
public DateField(String label,int mode)
public DateField(String label, int mode,TimeZone timeZone)
in which the mode parameter has a meaning very similar to the one we described talking about TextFields. Using a DateField we can insert information about a simple date, a time or both and this is set using specific DateField class constants. In our case we use the DateField.DATE value because we need to insert a simple date. It’s very important to remark that the way the device represents these kind of items is strongly device-dependent and that it’s a fundamental characteristic of the high level API.
We finish this pharagraph observing that TextFields and DateFields are used inside a Form and that they cannot be shown by themselves on the screen. A Form is a Screen but an Item isn’t.
Manage Command, Item and data model
We finish our module observing the way in which commands are managed by the CommandListener callback method:
public void commandAction(Command command, Displayable displayable)
We notice that event information is about the source of the event and the specific command the user selected. A single command can be linked to a set of different Displayable objects and so it’s not enough to tell the exact source. Usually, this method will contain many if, else or swith/case blocks.
The midlet manages its simple data models, containing name, sex and birthdate information. We can notice how – inside the commandAction() method – we manage model updates when we select the ok command, but not when we select the back button. In real-world applications, we often have to choose whether to represent our model as a set of midlet instance properties or as a new model class.
In this module we talked about the main widgets belonging to the high level API for midlet GUI creation. We saw how to create and how to manage command objects, and how to use the main widgets: List, Form and Item. In the next module we’ll study the details of the low level API, beginning to see the foundations of the API for game applications programming.
 MIDP 2.0 API http://java.sun.com/javame/reference/apis/jsr118/
 API MIDP 2.0 documentation
Related Download: HighLevelAPI.zip