Java ME

We need to install Eclipse software for developing application and game for mobile devices using Java programming language.

STEP 1. Make sure JDK is installed properly for windows computer according to the video
http://www.youtube.com/watch?v=EhH02lqJ4tM

STEP 2. Download Eclipse Java ME from Nokia developer site (Only for used for Nokia Asha platform, for Android Java see the Android tutorial)
http://developer.nokia.com/downloads/download/3978/?id=3978

Now if you have been able to make your "hellow world" application you are ready to go with Java.

STEP 3. Now make "Hello world" with Eclipse
http://www.youtube.com/watch?v=J9lkAK0L16I

STEP 4. Learn how to write program in Java in 21 days
http://hemelix.com/tutorial/Teach_Yourself_Java_6_in_21_Days_5th_Ed.pdf

If you have followed the above steps then follow the following code.
-Read it,
-Make each time a new project in Eclipse
-Build the code to program
-Run the program, change it as you imagine.

1. Requirements of MIDP 2.0

MIDP device has the following minimum characteristics:

  • Display:
    • screen size 96x54
  • Input:
    • One or more of the following user-input mechanisms: one-handed keyboard, two-handed keyboard, or touch screen
  • Memory:
    • 256 kilobytes of non-volatile memory for the MIDP implementation, beyond whats required for CLDC
    • 8 kilobytes of non-volatile memory for application-created persistent data
    • 128 kilobytes of volatile memory for the Java runtime (e.g., the Java heap)
  • Networking:
    • Two-way, wireless, possibly intermittent, with limited bandwidth
  • Sound:
    • The ability to play tones, either via dedicated hardware, or via software algorithm.

 

2. Midlet

MIDP application is a MIDlet. The activity of a MIDlet is managed by the Application Management Software of the mobile device. AMS control the life cycle of a midlet. AMS creates, starts, pauses and destroys the instance of MIDlet. AMS controls the activity of a MIDlet by means of startApp(), pauseApp() and destroyApp() methods.

Our MIDP application, MIDlet, must extend the abstract MIDlet class, which consists of the abstract methods startApp(), pauseApp() and destroyApp(). We have to write these methods also into our MIDlet.

MIDlet States

AMS creates the MIDlet object by allocating memory for it and calling its no-argument constructor. The application can do only little initialization in no-argument constructor. Middlet instance is first in the paused state. If an exception occurs during create phase of the MIDlet object, the application enters immediately the destroyed state. After the exceptionless return from constructor  AMS calls startApp() method of the MIDlet. The application enters just before startApp() method call active state. Application has most of the initialization tasks in the startApp() method.

Example.

The following simple MyMIDlet has a TextBox user interface component with some text and an exit command. MyMIDlet is derived from the MIDlet class and it has the no-argument constructor, startApp(), pauseApp() and destroyApp() methods.

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

public class MyMIDlet extends MIDlet implements CommandListener
{
   private Command exitCommand;
   private Display display;

   public MyMIDlet()
   {
       display = Display.getDisplay(this);
       exitCommand = new Command("Exit", Command.SCREEN, 2);
   }

   public void startApp()
   {
      TextBox t = new TextBox("The first midlet", "Welcome to the wonderfull world of midlets", 50, 0);
      t.addCommand(exitCommand);
      t.setCommandListener(this);
      display.setCurrent(t);
   }

   public void pauseApp(){}

   public void destroyApp(boolean b){}

   public void commandAction(Command c, Displayable s)
   {
      if(c == exitCommand)
      {
          destroyApp(false);
          notifyDestroyed();
      }
   }
}

3. User interface

The user interface for MIDP applications consists of the UI API in the javax.microedition.lcdui package.

Display class represents the manager of the display and input devices of the system. There is exactly one instance of Display per MIDlet and the application can get a reference to that instance by calling the Display.getDisplay() method. Method call is in the constructor or in the startApp() method.

Display instance has no graphical representation form, it only manages the display and input device of the mobile device. Display instance has setCurrent(Displayable displayable) method, which makes Displayable object visible on the display. Displayable class is the super class of all GUI component classes, that has the capability of being placed on the display and that can contain user command activities. The following figure contains the most important classes of the MIDP graphical user interface.

Screen and Canvas classes are extended from Displayable class. Screen class is common superclass of all high-level user interface classes. Canvas is a base class for applications, that need to handle low-level events and to issue graphics for drawing to the display. Java games use Canvas class and its subclasses.

One instance of the four subclasses of the Screen class, TextBox, List, Alert or Form, can be made visible on the display of a mobile device.

Form class represents a form which can contain other user interface controls. The controls added to a Form instance must be derived from Item class. The following classes of MIDP are derived from Item: ChoiceGroup, TextField, DateField, ImageItem, StringItem, Gauge, CustomItem and Spacer.

User interface classes extended from Displayable class derive addCommand() method which enables them to add user interface actions and commands to themselves. All MIDP user interface actions are presented by means of Command classes.

Command class

The Command class is a construct that encapsulates the semantic information of an user interface action. Command only contains information about the command activity, it doesn't contain the program code of the activity. Program code is written in a CommandListener object associated with the Displayable instance.

Commands can be presented to the user of a device in different ways depending on the model of the device, on the type of the command, on the total number of commands, etc.. The presentation way of a action can be a soft key, item in a menu, some other direct user interaction contruct, voice command, ... A Command object is mapped to a GUI component through addCommand() method.

The constructors of the Command class are below:

  • Command(String label, int commandType, int priority)
  • Command(String shortLabel, String longLabel, int commandType, int priority)

Paramters label, shortLabel and longLabel are a string the application shows to the user which. The string can be direct on the display or a item of a menu. If the string is direct on the display, it presents a soft key.

The second parameter, commandType, specifies the intent of the command. MIDP defines the following command types:

  • BACK, return to the previous screen
  • CANCEL, standard negative answer to a dialog
  • EXIT, exit from application
  • HELP, on-line help
  • ITEM, hint the implementation of item of the Screen or the elements of a Choice 
  • OK, standard positive answer to a dialog
  • SCREEN, application defined command
  • STOP, stop some currently running process, operation, etc.

The commandType definition doesn't do any activity automatically in the application. The activity have to been programmed in the midlet. Command can have a standard presentation way on a display by means of commandType definition. For example, if the application specifies that the command is of type BACK, and if the device has a standard of placing the "back" operation on a certain soft-button, the implementation can follow the style of the device by using the semantic information as a guide.

The last parameter of Command constructor, priority, describes the importance of this command relative to other commands on the same screen. Priority values are integers, where a lower number indicates greater importance. The priority of a command can have meaning, when application decide, if the command is showed in a menu or in a soft key. The in the constructor given value of the priority is only directive, the actual values of priority are chosen by the application.

Example of a definition of a Command instance is below:

new Command("Back", Command.BACK, 1)

 

CommandListener interface

A program code for user interface action is written in a class that implements CommandListener interface. The CommandListener interface contains only a method, commandAction(). The signature of the method is:

public void commandAction(Command command, Displayable d)

The first parameter, command, identifies the Command instance, which is attached to the user interface command and the second parameter, d, identifies the user interface component, which the activity occured in.

A CommandListener is attached to a user interface component with its setCommandListener() method, whose signature is below:

public void setCommandListener(CommandListener listener)

Parameter listener is a class that implements CommandListener interface.

Often the midlet self implements CommandListener interface and contains commandAction() method, where the program is coded.

Form

A Form is a screen that contains other from Item class derived GUI components: TextField, DateField, ChoiceGroup, ImageItem, StringItem, Gauge, CustomItem, Spacer.  In general, any subclass of the Item class may be contained within a form. The Form instance handles layout, traversal and scrolling of the GUI components it contains.

Items within a Form are referred to by their indexes, which are consecutive integers in the range from zero to size()-1, with zero referring to the first item and size()-1 to the last item.

The items contained within a Form may be managed by using following methods:

  • append(Item item) adds an Item into the Form and it becomes the last Item in the Form
  • append(String string) adds a String into the end of the Form
  • append(Image image)adds an Image into the end of the Form
  • insert(int itemNum, Item item), inserts an Item into the Form just prior to the item specified.
  • delete(int itemNum), deletes the Item referenced by itemNum
  • set(int itemNum, Item item),  sets the item referenced by itemNum to the specified item, replacing the previous item

 Because a Form class is derived form Displayable class, a Command objects can be attached to the Form instance. In addition a Form  instance can set a CommandListener object by using the method setCommandListener().

The constructors of the Form class are following:

  • public Form(String title),  creates an empty Form with a title
  • public Form(String title, Item[] items), creates a Form with specified content ja a title

TextField

A TextField is an editable text component that may be placed into a Form. The TextField has a maximum limit, how many characters it can contain. This limit is given at the creation time of the component.

The TextField can have input constraints so that user's input is restricted in a variety ways:

  • ANY, the user is allowed to enter any text.
  • CONSTRAINT_MASK, the mask value for determining the constraint mode
  • DECIMAL, numeric values with optional decimal fractions
  • EMAILADDR, an e-mail address
  • INITIAL_CAPS_SENTENCE, the initial letter of each sentence should be capitalized
  • INITIAL_CAPS_WORD, the initial letter of each word should be capitalized
  • NON_PREDICATIVE,
  • NUMERIC, only an integer value
  • PASSWORD, he text entered is confidential data that should be obscured whenever possible
  • PHONENUMBER, a phone number
  • SENSITIVE,
  • UNEDITABLE, editing is currently disallowed
  • URL, the user is allowed to enter a URL

The constructor of the TextField is following:

  public TextField(String label, String text, int maxSize, int constraints)

, where the parameter label is a given label, parameter text is the initial contents, parameter maxSize is the maximum size in characters and parameter constraints is the input constraints, whose possible values are listed above.

Example
The following Form1 midlet has Form instance f1 with two TextField components, user and password, and two Command objects, okCommand and exitCommand. When a user inputs the user id and password and selects "Ok" command, the midlet changes the Form instance and shows it with a text.

 

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

public class Form1 extends MIDlet implements CommandListener
{
   private Display display;
   private Form f1;
   private Form f2;
   private TextField user;
   private TextField password;
   private Command okCommand;
   private Command exitCommand;

   public Form1()
   {
      display = Display.getDisplay(this);
      f1 = new Form("Login");
      user = new TextField("User", "", 10, TextField.ANY);
      password = new TextField("Password", "", 6, TextField.PASSWORD);

      okCommand = new Command("Ok", Command.OK, 0);
      exitCommand = new Command("Exit", Command.SCREEN, 0);
   }

   public void startApp()
   {
      f1.append(user);
      f1.append(password);

      f1.addCommand(okCommand);
      f1.addCommand(exitCommand);
      f1.setCommandListener(this);
      display.setCurrent(f1);
   }

   public void pauseApp(){}

   public void destroyApp(boolean b){}

   public void commandAction(Command c, Displayable s)
   {
      if(c == okCommand)
      {
         f2 = new Form("Welcome");

         String text = new String();
         text = "Welcome, " + user.getString() + ", your password is wrong";
         f2.append(text);

         f2.addCommand(exitCommand);
         f2.setCommandListener(this);
         display.setCurrent(f2);
      }else if(c == exitCommand)
      {
         destroyApp(false);
         notifyDestroyed();
      }
   }
}

 

ChoiceGroup

A ChoiceGroup is a group of selectable elements intended to be placed within a Form. The component has tree modes:

  • single choice, user can select only one item (radio buttons), EXLUSIVE type
  • multiple choice, user can select multiple items (check boxes), MULTIPLE type
  • single choice, user can see first only one item and after a action the user can see all items, POPUP type

The ChoiceGroup class has 2 constructors:

  • ChoiceGroup(String label, int choiceType)
  • ChoiceGroup(String label, int choiceType, String[] stringElements, Image[] imageElements)

The first parameter label describes the selectable item's label and the second parameter choiceType describes the type of the ChoiceGroup, the value of which can be EXCLUSIVE, MULTIPLE or POPUP. The parameters stringElements and imageElements are arrays to be used as initial contents of the ChoiceGroup component.

Example
The following ChoiceGroup1 midlet has EXCLUSIVE type ChoiceGroup component. A user can select a phone and the midlet shows the selection in another Form.

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

public class ChoiceGroup1 extends MIDlet implements CommandListener
{
   private Display display;
   private Form f1;
   private Form f2;

   private ChoiceGroup phones;

   private Command selCommand;   //select
   private Command exitCommand;  // exit
   private Command backCommand;  // back

   public ChoiceGroup1()
   {
      display = Display.getDisplay(this);
      String models[] = {"Nokia", "Motorola", "Sony-Ericsson"};

      phones = new ChoiceGroup("Select a phone", ChoiceGroup.EXCLUSIVE, models, null);

      f1 = new Form("Selecting");

      selCommand = new Command("Select", Command.SCREEN, 0);
      exitCommand = new Command("Exit", Command.EXIT, 0);
      backCommand = new Command("Back", Command.BACK, 0);
   }

   public void startApp()
   {
      f1.append(phones);

      f1.addCommand(selCommand);
      f1.addCommand(exitCommand);
      f1.addCommand(backCommand);
      f1.setCommandListener(this);
      display.setCurrent(f1);
   }

   public void pauseApp(){}

   public void destroyApp(boolean b){}

   public void commandAction(Command c, Displayable s)
   {
      if(c == selCommand)
      {
         f2 = new Form("Selection");
         String text = "Your selection was " + phones.getString(phones.getSelectedIndex());
         f2.append(text);

         f2.addCommand(backCommand);
         f2.setCommandListener(this);
         display.setCurrent(f2);

      }else if(c == exitCommand)
      {
         destroyApp(false);
         notifyDestroyed();
      }else if(c == backCommand)
      {
         display.setCurrent(f1);
      }
   }
}

 

 

Example.
The following ChoiceGroup2 midlet has a MULTIPLE type ChoiceGroup. A user can select multiple phones and the midlet shows the selections in an other Form.

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

public class ChoiceGroup2 extends MIDlet implements CommandListener
{
   private Display display;
   private Form f1;
   private Form f2;
   private ChoiceGroup phones;

   private Command selCommand;
   private Command exitCommand;
   private Command backCommand;

   public ChoiceGroup2()
   {
      display = Display.getDisplay(this);
      phones = new ChoiceGroup("Select phones", ChoiceGroup.MULTIPLE);
      f1 = new Form("Selecting ..");

      selCommand = new Command("Select", Command.SCREEN, 0);
      exitCommand = new Command("Exit", Command.EXIT, 0);
      backCommand = new Command("Back", Command.BACK, 0);
   }

   public void startApp()
   {
      phones.append("Toshiba", null);
      phones.append("Nokia", null);
      phones.append("Siemens", null);
      phones.append("Sony-Ericsson", null);
      phones.append("Motorola", null);

      f1.append(phones);

      f1.addCommand(selCommand);
      f1.addCommand(exitCommand);
      f1.addCommand(backCommand);
      f1.setCommandListener(this);
      display.setCurrent(f1);
   }

   public void pauseApp(){}

   public void destroyApp(boolean b){}

   public void commandAction(Command c, Displayable s)
   {
      if(c == selCommand)
      {
         f2 = new Form("Selections");
         String text = "Your selection was ";
         for(int i = 0; i < phones.size(); i++)
         {
            if(phones.isSelected(i) == true)
            text = text + "\n" + phones.getString(i) ;
         }
         f2.append(text);
         f2.addCommand(backCommand);
         f2.setCommandListener(this);
         display.setCurrent(f2);

      }else if(c == exitCommand)
      {
         destroyApp(false);
         notifyDestroyed();
      }else if(c == backCommand)
      {
         display.setCurrent(f1);
      }
   }
}

Example.
The following ChoiceGroup3 midlet has a POPUP type ChoiceGroup. A user can see first only one item and after some action the user can see all items. The user can select only one item and the midlet shows the selection in an other Form.

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

public class ChoiceGroup3 extends MIDlet implements CommandListener
{
   private Display display;
   private Form f1;
   private Form f2;
   private ChoiceGroup phones;

   private Command selCommand;
   private Command exitCommand;
   private Command backCommand;

   public ChoiceGroup3()
   {
      display = Display.getDisplay(this);
      phones = new ChoiceGroup("Select phones", ChoiceGroup.POPUP);
      f1 = new Form("Selecting ..");

      selCommand = new Command("Select", Command.SCREEN, 0);
      exitCommand = new Command("Exit", Command.EXIT, 0);
      backCommand = new Command("Back", Command.BACK, 0);
   }

   public void startApp()
   {
      phones.append("Toshiba", null);
      phones.append("Nokia", null);
      phones.append("Siemens", null);
      phones.append("Sony-Ericsson", null);
      phones.append("Motorola", null);

      f1.append(phones);

      f1.addCommand(selCommand);
      f1.addCommand(exitCommand);
      f1.addCommand(backCommand);
      f1.setCommandListener(this);
      display.setCurrent(f1);
   }

   public void pauseApp(){}

   public void destroyApp(boolean b){}

   public void commandAction(Command c, Displayable s)
   {
      if(c == selCommand)
      {
         f2 = new Form("Selections");
         String text = "Your selection was ";
         for(int i = 0; i < phones.size(); i++)
         {
            if(phones.isSelected(i) == true)
            text = text + "\n" + phones.getString(i) ;
         }
         f2.append(text);
         f2.addCommand(backCommand);
         f2.setCommandListener(this);
         display.setCurrent(f2);

      }else if(c == exitCommand)
      {
         destroyApp(false);
         notifyDestroyed();
      }else if(c == backCommand)
      {
         display.setCurrent(f1);
      }
   }
}

DateField

A DateField is an editable component for presenting date and time (calendar) information that may be placed into a Form.

 

Example
DateField1 midlet contains two DateField components. The first component is for entering a date and the second is for entering a time.

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

public class DateField1 extends MIDlet implements CommandListener
{
   private Display display;
   private Form f1;
   private Form f2;
   private DateField date;
   private DateField time;

   private Command okCommand;
   private Command exitCommand;
   private Command backCommand;

   public DateField1()
   {
      display = Display.getDisplay(this);
      date = new DateField("Date", DateField.DATE);
      time = new DateField("Time", DateField.TIME);
      f1 = new Form("Date and time");

      okCommand = new Command("Ok", Command.SCREEN, 0);
      exitCommand = new Command("Exit", Command.EXIT, 0);
      backCommand = new Command("Back", Command.BACK, 0);
   }

   public void startApp()
   {

      f1.append(date);
      f1.append(time);

      f1.addCommand(okCommand);
      f1.addCommand(exitCommand);
      f1.setCommandListener(this);
      display.setCurrent(f1);
   }

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

   public void commandAction(Command c, Displayable s)
   {
      if(c == okCommand)
      {
         f2 = new Form("Date and time");

         Calendar cal = Calendar.getInstance();
         Date datex = date.getDate();
         cal.setTime(datex);

         String text = "Date: " + cal.get(Calendar.DATE) + "." +
                                  cal.get(Calendar.MONTH) + "." +
                                  cal.get(Calendar.YEAR);
         cal.setTime(time.getDate());
         text = text + "\ntime: " + cal.get(Calendar.HOUR) + ":" +
                                  + cal.get(Calendar.MINUTE);
         f2.append(text);
         f2.addCommand(backCommand);
         f2.setCommandListener(this);
         display.setCurrent(f2);

      }else if(c == exitCommand)
      {
         destroyApp(false);
         notifyDestroyed();
      }else if(c == backCommand)
      {
         display.setCurrent(f1);
      }
   }
}

 

List

A List is a choice component and because it is derived from Screen class, it is present on the whole display. The List is suitable for representing a menu. The List has three types: IMPLICIT, EXCLUSIVE and MULTIPLE.

 

Examples

  • List1 midlet has an IMPLICIT type List component. Notice the use of SELECT_COMMAND 
  • List2 midlet has an EXCLUSIVE type List component 
  • List3 midlet has a MULTIPLE type List component 

 

Alert

An Alert is a screen that shows data to the user and waits for a certain period of time before proceeding to the next screen. The intent of Alert is to inform the user about events,  warnings, errors and other exceptional conditions. An alert can contain a text string and an image.

The Alert class has 2 constructors:

  • Alert(String title)
  • Alert(String title, String alertText, Image alertImage, AlertType alertType)

Parameter title is the title string, alertText is the text in the display, alertImage is the image in the display and alertType is the type of alert (ALARM, CONFIRMATION, ERROR, INFO or WARNING).

The application can set the alert time with setTimeout(int time) method. The time is in milliseconds. If the time parameter is Alert.FOREVER, the alert time is infinite. Then the Alert is in the modal mode and user have to quit the alert.

 

Example.
If you select Email in the display of the Alert1 midlet, an Alert screen appears on the display for 3 seconds. If you select Text messages, an modal Alert screen appears and you have to quit it, if you want it  to disappear.

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

public class Alert1 extends MIDlet implements CommandListener
{
   private Display display;
   private List list;
   private Alert alert1;
   private Alert alert2;
   private Command cmExit;

   public Alert1()
   {
      display = Display.getDisplay(this);
      String medias[] = {"Emails", "Text messages", "Calls", "MMS messages"};
      list = new List("Medias", List.IMPLICIT, medias, null);
      cmExit = new Command("Exit", Command.EXIT, 0);
   }

   public void startApp()
   {
      list.addCommand(cmExit);
      list.setCommandListener(this);
      display.setCurrent(list);
   }

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

   public void commandAction(Command c, Displayable s)
   {
      if(c == List.SELECT_COMMAND)
      {

         if(list.getSelectedIndex() == 0){
            alert1 = new Alert("Warning", "Email is out of order", null, AlertType.WARNING);
            alert1.setTimeout(3000);
            display.setCurrent(alert1);
         }

         if(list.getSelectedIndex() == 1){
            alert2 = new Alert("Question", "Do you really want to read the text messages?", null, AlertType.INFO);
            alert2.setTimeout(Alert.FOREVER);
            display.setCurrent(alert2);
         }

         String selection = list.getString(list.getSelectedIndex());
         System.out.println("Selection: " + selection);
      }
      else if(c == cmExit)
      {
         destroyApp(false);
         notifyDestroyed();
      }
   }
}

Image

The Image class is used to hold graphical image data. Images may be placed within Alert, Choice, Form, or ImageItem objects.

Image object is created with one of the static createImage() methods of the Image class: 

  • createImage(byte[] imagedata, int imageOffset, int imageLength), 
  • createImage(Image source)
  • createImage(Image image, int x, int y, int width, int height, int transform)
  • createImage(InputStream stream)
  • createImage(int width, int height)
  • createImage(String name)
  • createImage(int[] rgb, int width, int height, boolean processAlpha)

ImageItem

ImageItem class is extended from Item class and can so be placed into a form. ImageItem object can contain a image. Each ImageItem object contains a reference to an Image object.

ImageItem has 2 constructors:

     ImageItem(String label, Image img, int layout, String altText)
     ImageItem(String label, Image img, int layout, String altText, int appearanceMode)

Parameter label is a label string, img is the image, layout is combination of layout directives, altText is a alternative text and appearanceMode is an appearance mode.

The layout directives are LAYOUT_CENTER, LAYOUT_DEFAULT, LAYOUT_LEFT, LAYOUT_NEWLINE_BEFORE, LAYOUT_NEWLINE_AFTER, LAYOUT_RIGHT.

The appearance modes are PLAIN,  HYPERLINK,  BUTTON.

Example.
Image1 midlet creates an Image and ImageItem objects with an image of Duke. Download the image , Duke.png, to the res directory of your project.

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

public class Image1 extends MIDlet
{
   private Display display;
   private Form form;
   private ImageItem image;

   public Image1()
   {
      display = Display.getDisplay(this);
      form = new Form("Picture");
      Image im = null;
      try{
         im = Image.createImage("/Duke.png");
      }catch(Exception e){
         System.out.println("** Error creating image");
      }
      image = new ImageItem("Picture of Duke",im, Item.LAYOUT_CENTER, "Duke's image" );
   }
   public void startApp()
   {
      form.append(image);
      display.setCurrent(form);
   }
   public void pauseApp(){}
   public void destroyApp(boolean b){}
}

The display of the midlet is in the following figure.


 

4.Low level UI API

The Canvas class is a base class for writing applications that need to handle low-level events and to issue graphics calls for drawing to the display.

Canvas uses coordinate system for placing graphical figures on the display. The display has the dimensions: width and height. Location 0,0 in the coordinates is in the upper left corner of the display, x value increases to the right and y value increases down.

We can use getHeight() and getWidth() methods of Displayable class to get the height and width in pixel of the display of the device.

Because the Canvas class is defined as abstract, you have to create a subclass of Canvas. Canvas class has abstract paint(Graphics g) method for using graphics. So you have to write paint(Graphics g) method into your canvas.

The Graphics class provides primitives for drawing lines, rectangles, arcs, text and images. Rectangles and arcs may also be filled with a solid color. Rectangles may also be specified with rounded corners. The Graphics class includes among others following methods:

  • drawArc(), draws the outline of a circular or elliptical arc
  • drawChar(),   draws the specified character using the current font and color
  • drawChars(), draws the specified characters using the current font and color
  • drawImage(), draws the specified image
  • drawLine(), draws a line between 2 coordinates
  • drawRect(), draws the specified rectangle
  • drawRoundRect(), draws the outline of the specified rounded corner rectangle
  • drawString(),  draws a String using the current font and color
  • fillArc(),  fills the specified arc with a current color
  • fillRect(),  fills the specified rectangle with a current color
  • setColor(), set the current color to the specified RGB values
  • setFont(), set the current font
  • setGrayScale(),  set the current grayscale to be used for all subsequent renderin operatios. The value must be in the range 0-255 ( 0 means black and 255 means white).

 

Example.
The underlying midlet Drawing1 sets into the display a Canvas instance, Canvas1. The Canvas1 class is below.

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

public class Drawing1 extends MIDlet {

  public void startApp () {
    Display.getDisplay (this).setCurrent (new Canvas1 ());
  }

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

The Canvas1 class shows firstly on the console the width and height of the display, clean the display and draw a line and a rectanular. Then it changes the color and draws a circle and finally it changes again color and fills a rectangular. See accurate method descriptions in the API documentation of the MIDP.

import javax.microedition.lcdui.*;

class Canvas1 extends Canvas {

  public void paint (Graphics g) {

     // shows the width and height of the display on console
     System.out.println("Width " + getWidth());
     System.out.println("Height " + getHeight());

     // clean the display
     g.setGrayScale (255);
     g.fillRect (0, 0, getWidth (), getHeight ());

     g.setGrayScale (0);
     g.drawLine (20, 33, 170, 61);
     g.drawRect(40, 65, 60, 40);

     g.setColor(255, 0, 255);
     g.drawArc(10,120,50,50,0,360);

     g.setColor(0, 255, 255);
     g.fillRect(130, 110, 30, 40);
  }
}

You see below what kind of figures the midlet has drawn.

The method setColor(int red, int green, int blue) of Graphics class changes the drawing and filling color in the following way.

Parameters of setColor() Color
setColor(255,0,0) red
setColor(0,255,0) green
setColor(0,0,255) blue
setColor(0,0,0) black
setColor(255,255,255) white
setColor(255,255,0) yellow

When drawing lines, rectangles and arcs, the line can be solid or dash line. Graphics class has setStrokeStyle() method for setting the style of the line. It's parameter can be Graphics.DOTTED or Graphics.SOLID.

 

 

Drawing text

The method drawString(String str, int x, int y, int anchor) of the Graphics class draws a string on the canvas:

  • parameter str is the string to be drawn
  • parameters x and y declare the position of the text.
  • the third parameter anchor is a point for positioning the text in the relation to the point (x,y). Its value must be zero (0) or one of the horizontal constans(LEFT, HCENTER, RIGHT) combined by using bit-wise or operator with one of the vertical constants (TOP, BASELINE, BOTTOM)

Example.
Canvas2.java">Canvas2 draws "Good morning" string into the position: x = 2 and y = 5. And then it draws the strings "ONE", "TWO" and "THREE" into the same location, whose position is: x = getWidth()/2 and y = getHeight()/2 (the middle point of the display). But every string has different anchor in relation to the drawing location.

import javax.microedition.lcdui.*;

class Canvas2 extends Canvas {

  public void paint (Graphics g) {
    g.setGrayScale (255);
    g.fillRect (0, 0, getWidth (), getHeight ());

    g.setGrayScale (0);
    g.drawString("Good morning!",2, 5, 0);

    g.drawString("ONE",getWidth ()/2, getHeight ()/2, Graphics.LEFT|Graphics.TOP);
    g.drawString("TWO",getWidth ()/2, getHeight ()/2, Graphics.RIGHT|Graphics.BOTTOM);
    g.drawString("THREE",getWidth ()/2, getHeight ()/2, Graphics.LEFT|Graphics.BASELINE);
  }
}

You can see in the picture below, how the strings are located on the display.

Drawing arcs

The Graphics class has drawArc() method for drawing arcs. The signature of the drawArc() method is following:

    public void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle)

where

  • x =  the x coordinate of the upper-left corner of the arc to be drawn
  • y = the y coordinate of the upper-left corner of the arc to be drawn
  • width = the width of the arc to be drawn
  • height = the height of the arc to be drawn
  • startAngle = the beginning angle (0 = at 3 o'clock)
  • arcAngle = the angular extent of the arc, relative to the start angle (360 = the whole circle)

 

Example.
Canvas3 draws vertical and horizontal dotted lines and divides the screen to 4 parts. Then different arcs are drawn in every part of the screen.

import javax.microedition.lcdui.*;
class Canvas3 extends Canvas {
  public void paint (Graphics g) {
     // clean the display
     g.setGrayScale (255);
     g.fillRect (0, 0, getWidth (), getHeight ());

     // draw the dotted lines
     g.setGrayScale (0);
     g.setStrokeStyle(Graphics.DOTTED);
     g.drawLine (getWidth()/2, 0, getWidth()/2, getHeight());
     g.drawLine (0, getHeight()/2, getWidth(), getHeight()/2);

     // draw the red arcs with solid lines
     g.setStrokeStyle(Graphics.SOLID);
     g.setColor(255, 0, 0);
     g.drawArc(20,40,80,80,0,240);
     g.drawArc(140,40,80,80,90,240);
     g.drawArc(30,160,60,110,0,360);
     g.fillArc(140,170,80,80,0,110);
  }
}

The display of the program is below:

Drawing rectangles

Graphics class has drawRect() and drawRoundRect() methods for drawing of rectangles:

   void drawRect(int x, int y, int width, int height)
   void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight)

Example.
Canvas4.java">Canvas4 draws four rectangles: a rectangle, a rectangle with rounded corners, a filled rectangle and a filled rectangle with rounded corners.

import javax.microedition.lcdui.*;
class Canvas4 extends Canvas {
  public void paint (Graphics g) {
     // clean the display
     g.setGrayScale (255);
     g.fillRect (0, 0, getWidth (), getHeight ());

     // draw the dotted lines
     g.setGrayScale (0);
     g.setStrokeStyle(Graphics.DOTTED);
     g.drawLine (getWidth()/2, 0, getWidth()/2, getHeight());
     g.drawLine (0, getHeight()/2, getWidth(), getHeight()/2);

     // draw rectangles and filled rectangles
     g.setStrokeStyle(Graphics.SOLID);
     g.setColor(0, 0, 255);
     g.drawRect(20,20,50,40);
     g.drawRoundRect(105,20,60,40, 20, 20);
     g.fillRect(20,100,50,40);
     g.setColor(0, 255, 0);
     g.fillRoundRect(100,100,60,40,15,15);
  }
}

The display of the Canvas4 is below.

 

Drawing images

For drawing images the Graphics class has a drawImage(Image image, int x, int y, int anchor) method. Parameter image is Image object, which has to create before drawing the image.

Images are either mutable or immutable depending upon how they are created. Immutable images are generally created by loading image data from resource bundles, from files, or from the network. They may not be modified once created.

Mutable images are created as blank images containing only white pixels. The application may render on a mutable image by calling getGraphics() of the Image object to obtain a Graphics object expressly for this purpose.

Example.
Canvas5 creates a immutable image and shows it. The constructor creates first a Image object from a image file, picx.png. The method paint() calls the drawImage() method of the Graphics ohject and draws the image on the display. Download picx.png and place it to res directory of the MIDP project.

import javax.microedition.lcdui.*;
class Canvas5 extends Canvas {

  Image image;
  public Canvas5()
  {
     try{
         image = Image.createImage("/picx.png");
     }catch(java.io.IOException e){
          System.out.println("** Error, creating image");
     }
  }
  public void paint (Graphics g) {
     // clean the display
     g.setGrayScale (255);
     g.fillRect (0, 0, getWidth (), getHeight ());

	 if(image != null)
	     g.drawImage(image, 20, 40, 0);
  }
}

The creation of a mutable image has the following phases:

  • allocate the image in the memory:
        Image image = Image.createImage(60, 50);
  • get the Graphics object for creating of the image content
        Graphics g = image.getGraphics();
  • create the content of the image using text, rectangles, arcs,  lines and colors
        g.drawRect(10, 20, image.getWidth(), image.getHeight();
  • show the image on the display
        public void paint (Graphics g) {
             ....
             g.drawImage(image, 10, 30, 0);

 

Example.
Canvas6 creates a mutable image and displays it.

import javax.microedition.lcdui.*;
class Canvas6 extends Canvas {

Image image;
public Canvas6()
{
  try{
    image = Image.createImage(60, 50);
    Graphics g = image.getGraphics();
    g.setColor(0, 0, 255);
    g.fillRect(0, 0, image.getWidth()-1, image.getHeight()-1);
    g.setColor(255, 0, 0);
    g.fillArc(24,6, 12, 36, 0, 360);
    g.fillArc(8,18, 44, 10, 0, 360);

  }catch(Exception e){
      System.out.println("** Error, creating image");
  }
}
public void paint (Graphics g) {
   // clean the display
   g.setGrayScale (255);
   g.fillRect (0, 0, getWidth (), getHeight ());

   if(image != null)
     g.drawImage(image, getWidth()/2, 10, Graphics.HCENTER|Graphics.TOP);
}
}

The display of the program is below.

 

Commands in the Canvas

Example.
XMidlet has a Canvas with the Exit Command.

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

public class XMidlet extends MIDlet
{
   private Display display;
   private XCanvas canvas;

   public XMidlet()
   {
      display = Display.getDisplay(this);
      canvas = new XCanvas(this);
   }
   public void startApp()
   {
      display.setCurrent(canvas);
   }
   public void pauseApp(){}
   public void destroyApp(boolean b){}
   public void exit()
   {
      destroyApp(false);
      notifyDestroyed();
   }
}

class XCanvas extends Canvas implements CommandListener
{
   private XMidlet midlet;
   private Command cmExit;

   public XCanvas(XMidlet midlet)
   {
      this.midlet = midlet;
      cmExit = new Command("Exit", Command.EXIT, 0);
      addCommand(cmExit);
      setCommandListener(this);
   }

   public void paint (Graphics g) {

      // clean the display
      g.setGrayScale (255);
      g.fillRect (0, 0, getWidth (), getHeight ());

      g.setGrayScale (0);
      g.drawLine (20, 33, 170, 61);
      g.drawRect(40, 65, 60, 40);

      g.setColor(255, 0, 255);
      g.drawArc(10,120,50,50,0,360);

      g.setColor(0, 255, 255);
      g.fillRect(130, 110, 30, 40);
   }
   public void commandAction(Command c, Displayable s)
   {
      if(c == cmExit)
      {
         midlet.exit();
      }
   }
}

Canvas class has keyPressed(int keyCode), keyReleased(int keyCode) and keyRepeated(int keyCode) methods, which are called, when the corresponding key event occurs. Parameter keyCode defines, what key was pressed or released.  MIDP defines the following key codes: KEY_NUM0, KEY_NUM1, KEY_NUM2, KEY_NUM3, KEY_NUM4, KEY_NUM5, KEY_NUM6, KEY_NUM7, KEY_NUM8, KEY_NUM9, KEY_STAR, KEY_POUND. These key codes correspond to keys on a standard keypad. Method keyRepeated() is called when a key is repeated held down, but the method may not be supported on all devices.

The method getKeyName(int keyCode) returns a name of the key code.

MIDP defines some constants for game action key codes: UP, DOWN, LEFT, RIGHT, FIRE, GAME_A,  GAME_B,  GAME_C,  GAME_D.

Example.
The following  YMidlet midlet has in the display  YCanvas, which reacts to "key pressed" and "key released"  events by means of the keyPressed()and   keyReleased()methods and shows the name of the event and the name of the key on the display.

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class YMidlet extends MIDlet
{
   private Display display;
   private YCanvas canvas;

   public YMidlet()
   {
      display = Display.getDisplay(this);
      canvas = new YCanvas(this);
   }
   public void startApp()
   {
      display.setCurrent(canvas);
   }
   public void pauseApp(){}
   public void destroyApp(boolean b){}
   public void exit()
   {
      destroyApp(false);
      notifyDestroyed();
   }
}
class YCanvas extends Canvas implements CommandListener
{
   private YMidlet midlet;
   private Command cmExit;
   private String text = null;

   public YCanvas(YMidlet midlet)
   {
      this.midlet = midlet;
      cmExit = new Command("Exit", Command.EXIT, 0);
      addCommand(cmExit);
      setCommandListener(this);
   }
   public void paint (Graphics g) {

      // clean the display
      g.setGrayScale (255);
      g.fillRect (0, 0, getWidth (), getHeight ());
      g.setGrayScale (0);
      g.setColor(0,0,255);
      g.drawLine (0, 10, getWidth(), 10);

      if(text != null)
	  {
          g.setColor(0, 0, 0);
	      g.drawString(text, 10, 30, 0);
	  }
   }
   protected void keyPressed(int keyCode)
   {
         text = "pressed " + getKeyName(keyCode);
         repaint();
   }
   protected void keyReleased(int keyCode)
   {
         text = "released " + getKeyName(keyCode);
         repaint();
   }
   public void commandAction(Command c, Displayable s)
   {
      if(c == cmExit)
      {
         midlet.exit();
      }
   }
}

5. Timer functions

MIDP includes for timer functions (scheduling) two classes: Timer and TimerTask classes.

The Timer class is for scheduling when a task will occur. The TimerTask class is for performing a task.

The Timer class has 6 scheduling methods and one terminating cancel() method:

  • void schedule(TimerTask task, long delay), 
  • void schedule(TimerTask task, Date time), 
  • void schedule(TimerTask task, Date firstTime, long period), 
  • void schedule(TimerTask task, long delay, long period), 
  • void scheduleAtFixedRate(TimerTask task, long delay, long period), 
  • void scheduleAtFixedRate(TimerTask task, Date firstTime, long period), 
  • void cancel()

which have the following parameters:

  • task is a task to be scheduled
  • delay is a delay in milliseconds before the task is to be executed
  • time is a time at which the task is to be executed
  • firstTime is the first time at which the task is to be executed
  • period is a time in milliseconds between successive task executions.

The schedule() methods with a periodically repeating task are fixed-delay type: the start of each task is based on the time since the previous task finished. The execution time of a task can increase for any reason (for example garbage collection). The scheduleAtFixedRate() methods are fixed-rate type: the start of each task is based on the time since the previous task started.

The cancel() method  terminates the timer and discards any currently scheduled tasks.

A task, that can be scheduled for one-time or repeated execution by a Timer object, has to code in a class that is extended from abstract TimerTask class. TimerTask class implements a Runnable interface and so it must have public void run() method, which contains the executed task.

Example.
Timer1 midlet has a Timer object for scheduling a task, which is programmed in the run() method of a TestTimerTask class. The midlet uses all 6 scheduling ways of the Timer class. Take the comments away from each schedule() method by turns.

//Example from the book:Core J2ME Technology, John W. Muchow
import java.util.*;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

public class Timer1 extends MIDlet implements CommandListener
{
  private Display display;
  private Form fmMain;
  private Command cmExit;
  private Command cmStop;      // Stop the timer
  private Timer tm;            // Timer
  private TestTimerTask tt;    // Task
  private int count = 0;       // How many times has task run

  public Timer1()
  {
    display = Display.getDisplay(this);
    fmMain = new Form("Timer Test");
    fmMain.append("waiting...\n");

    cmExit = new Command("Exit", Command.EXIT, 1);
    cmStop= new Command("Stop", Command.STOP, 2);
    fmMain.addCommand(cmExit);
    fmMain.addCommand(cmStop);
    fmMain.setCommandListener(this);


    // Create a timer that will go off in 5 seconds
    tm = new Timer();
    tt = new TestTimerTask();
    tm.schedule(tt,5000);


    // Create a timer that will go off in 5 seconds, repeating every 3 seconds
//    tm = new Timer();
//    tt = new TestTimerTask();
//    tm.schedule(tt,5000, 3000);

    // Create a timer that will go off in 5 seconds, repeating every 3 seconds
//    tm = new Timer();
//    tt = new TestTimerTask();
//    tm.scheduleAtFixedRate(tt,5000, 3000);

    // Create timer that starts at current date
//    tm = new Timer();
//    tt = new TestTimerTask();
//    tm.schedule(tt, new Date());

    // Create timer that starts at current date, repeating every 3 seconds
//    tm = new Timer();
//    tt = new TestTimerTask();
//    tm.schedule(tt, new Date(), 3000);

    // Create timer that starts at current date, repeating every 3 seconds
//    tm = new Timer();
//    tt = new TestTimerTask();
//    tm.scheduleAtFixedRate(tt, new Date(), 3000);
  }

  public void startApp ()
  {
    display.setCurrent(fmMain);
  }
  public void destroyApp (boolean unconditional) {}
  public void pauseApp () { }
  public void commandAction(Command c, Displayable d)
  {
    if (c == cmStop)
    {
      tm.cancel();
    }
    else if (c == cmExit)
    {
      destroyApp(false);
      notifyDestroyed();
    }
  }

  private class TestTimerTask extends TimerTask
  {
    public final void run()
    {
      fmMain.append("run count: " + ++count + "\n");
    }
  }
}

Animation.java, AnimationCanvas.java, AnimateTimerTask.java


6. The Game API

The Game API package provides a series of classes that enable the development of rich gaming content for wireless devices. The Game API classes are in the javax.microedition.lcdui.game package.

The Game API is comprised of five classes:

GameCanvas
This class is a subclass of LCDUI's Canvas and provides the basic 'screen' functionality for a game. In addition to the methods inherited from Canvas, this class also provides game-centric features such the ability to query the current state of the game keys and synchronous graphics flushing; these features simplify game development and improve performance.
Layer
The Layer class represents a visual element in a game such as a Sprite or a TiledLayer. This abstract class forms the basis for the Layer framework and provides basic attributes such as location, size, and visibility. A game can have many layers.
LayerManager
For games that employ several Layers, the LayerManager simplifies game development by automating the rendering process. It allows the developer set a view window that represents the user's view of the game. The LayerManager automatically renders the game's Layers to implement the desired view.
Sprite
A Sprite is basic animated Layer that can display one of several graphical frames. The frames are all of equal size and are provided by a single Image object. In addition to animating the frames sequentially, a custom sequence can also be set to animation the frames in an arbitrary manner. The Sprite class also provides various transformations (flip and rotation) and collision detection methods that simplify the implementation of a game's logic.
TiledLayer
This class enables a developer to create large areas of graphical content without the resource usage that a large Image object would require. It is a comprised of a grid of cells, and each cell can display one of several tiles that are provided by a single Image object. Cells can also be filled with animated tiles whose corresponding pixel data can be changed very rapidly; this feature is very useful for animating large groups of cells such as areas of water. 


7. Network connections

CLDC has the Generic Connection Framework for supporting input/output and networking in a generalized, extensible fashion.

The basic idea is to have one class, the Connector, that can create any kind of connection: file, http, datagram, etc. Connector class has the static open() method, which creates the connection and whose method call is following:

Connection Connector.open("protocol:address;parameters");

The open() method returns Connection object, which represents a general network connection. The parameter of the method is a string with an URL address. The URL address contains 3 part: a name of the protocol, some kind of network address and parameterss in the form: "name=value".

Examples of the  Connector.open() methods are below:

      Connector.open("http://www.company.com/somepath/document.doc");
      Connector.open("socket://127.166.8.16:9000");
      Connector.open("file:/foo.txt");

Connection

The Connection interface represents data communication connection generally. It has only a method, close(), which closes the connection. The opening of the connection was achieved with the Connector.open() method.

Many kind of interfaces, which represent different kind of communications,  are extened from Connection interface. See the figure below. HttpConnection is for HTTP connection and HttpsConnection for secure HTTP connection.

 

 

HttpConnection

The HttpConnection interface defines the necessary methods and constants for an HTTP connection.

HTTP is an Internet protocol, which functions according to the request-response principle. The parameters of a request must be set before sending of the request. The HTTP connection exists in one of three states:

  • Setup, in which state the midlet has no connection to a server and the request parameters can be set
  • Connected, in which state the midlet has connection to the server, request parameters have been sent and the response is expected
  • Closed, the final state, in which the HTTP connection as been terminated 

The following methods may be invoked only in the Setup state:

  • setRequestMethod()
  • setRequestProperty()

The transition from Setup to Connected is caused by any method that requires data to be sent to or received from the server. The following methods cause the transition to the Connected state, when the connection is in Setup state.

  • openInputStream() 
  • openDataInputStream() 
  • getLength() 
  • getType() 
  • getEncoding() 
  • getHeaderField() 
  • getResponseCode() 
  • getResponseMessage() 
  • getHeaderFieldInt() 
  • getHeaderFieldDate() 
  • getExpiration() 
  • getDate() 
  • getLastModified() 
  • getHeaderField() 
  • getHeaderFieldKey() 

The following methods may be invoked while the connection is in Setup or Connected state.

  • close() 
  • getRequestMethod() 
  • getRequestProperty() 
  • getURL() 
  • getProtocol() 
  • getHost() 
  • getFile() 
  • getRef() 
  • getPort() 
  • getQuery() 

 

It is recommended to launch a thread to handle the network connection. This prevents the main program stopping while  connecting and reading or writing data in a network. The task of the main program is to handle a user interface and its events.

Example.
The Conn midlet requests a docuX.txt file on the localhost server (http://localhost:8080/docuX.txt) and shows the content of the docuX.txt on the display. Edit docuX.txt text file and save it into the ROOT directory of Tomcat server. The midlet has a "Connect" command, which start a thread. And the thread connect to the server and read the text file.

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

public class Conn extends MIDlet implements CommandListener
{
  private String url = "http://localhost:8080/docuX.txt";
  private Display display;
  private TextBox text;
  private Command cmConnect;
  private Command cmExit;

   public Conn()
   {
     display = Display.getDisplay(this);
     text = new TextBox("Network connection", "", 100, TextField.ANY);
     cmConnect = new Command("Connect", Command.SCREEN, 1);
     cmExit = new Command("Exit", Command.EXIT, 1);
   }
   public void startApp()
   {
     text.addCommand(cmConnect);
     text.addCommand(cmExit);
     text.setCommandListener(this);
     display.setCurrent(text);
   }
   public void commandAction(Command c, Displayable s)
   {
      if(c == cmConnect)
      {
         Thread t = new Thread(){
            public void run(){
               connect();
            }
         };
         t.start();
      }
      else if(c == cmExit)
      {
         destroyApp(false);
         notifyDestroyed();
      }
   }
   private void connect()
   {
      HttpConnection httpConn = null;
      InputStream in = null;
      try
      {
          httpConn = (HttpConnection) Connector.open(url);
          in = httpConn.openInputStream();
          int length = (int) httpConn.getLength();
          byte data[] = new byte[length];
          in.read(data);
          String str = new String(data);
          text.setString(str);
          System.out.println("The content of docuX:\n" + str);
          in.close();
          httpConn.close();
      }catch(IOException ex){
          text.setString("** Error, connecting... : " + ex.getMessage());
      }
  }
   public void pauseApp(){}
   public void destroyApp(boolean b){}
}

 

Example.
A Conn2 is a technical midlet without a user interface. The midlet sends a HTTP request to the server, gets a HTTP response and shows HTTP technical information on the console. Because the midlet has no user interface, it doesn't need to start a thread.

/*--------------------------------------------------
*
* Send client request (method, header, body)
* Get server response (status, header, body)
*
* Example from the book:     Core J2ME Technology
* Copyright John W. Muchow   http://www.CoreJ2ME.com
* You are free to use/modify this source code.
*-------------------------------------------------*/
import javax.microedition.midlet.*;
import javax.microedition.io.*;
import java.io.*;
public class Conn2 extends MIDlet
{
  private String url = "http://localhost:8080/docuX.txt";
  public void startApp()
  {
    try{
      connect();
    }
    catch (Exception e)
    {
      System.out.println("*** Connecting error" + e.getMessage());
    }
  }
  private void connect() throws IOException
  {
    HttpConnection httpConn = null;
    InputStream iStrm = null;
    try
    {
      httpConn = (HttpConnection) Connector.open(url);
      httpConn.setRequestMethod(HttpConnection.GET);
      httpConn.setRequestProperty("User-Agent", "Profile/MIDP-2.0 Configuration/CLDC-1.1");

      System.out.println("url: " + url);
      System.out.println("-------------------------");

      System.out.println("Msg: " + httpConn.getResponseMessage());
      System.out.println("Code: " + httpConn.getResponseCode());

      if (httpConn.getResponseCode() == HttpConnection.HTTP_OK)
      {
        System.out.println("field 0: " + httpConn.getHeaderField(0));
        System.out.println("field 1: " + httpConn.getHeaderField(1));
        System.out.println("field 2: " + httpConn.getHeaderField(2));
        System.out.println("-------------------------");

        System.out.println("key 0: " + httpConn.getHeaderFieldKey(0));
        System.out.println("key 1 : " + httpConn.getHeaderFieldKey(1));
        System.out.println("key 2: " + httpConn.getHeaderFieldKey(2));
        System.out.println("-------------------------");

        System.out.println("content: " + httpConn.getHeaderField("content-type"));
        System.out.println("date: " + httpConn.getHeaderField("date"));
        System.out.println("last-modified: " + httpConn.getHeaderField("last-modified"));
        System.out.println("-------------------------");

        String str;
        iStrm = httpConn.openInputStream();
        int length = (int) httpConn.getLength();
        if (length != -1)
        {
          byte serverData[] = new byte[length];
          iStrm.read(serverData);
          str = new String(serverData);
        }
        else  // Length not available...
        {
          ByteArrayOutputStream bStrm = new ByteArrayOutputStream();
          int ch;
          while ((ch = iStrm.read()) != -1)
            bStrm.write(ch);

          str = new String(bStrm.toByteArray());
          bStrm.close();
        }
        System.out.println("The content of the file:\n " + str);
        System.out.println("Host: " + httpConn.getHost());
        System.out.println("Port: " + httpConn.getPort());
        System.out.println("Type: " + httpConn.getType());
      }
    }
    finally
    {
      if (iStrm != null)
        iStrm.close();
      if (httpConn != null)
        httpConn.close();
    }
  }
  public void pauseApp()
  { }
  public void destroyApp(boolean unconditional)
  { }
}

 

Servlet connection

Example.
ConnServlet is a simple servlet, which sends a HTTP response to  a HTTP request sended by GET method.. The response contains  some text and an increasing number. Conn3 is a midlet, which sends a HTTP request by GET method to the preceding servlet.

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;

public class ConnServlet extends HttpServlet
{
  private int number = 0;
  protected void doGet(HttpServletRequest req, HttpServletResponse res)
                       throws ServletException, IOException
  {
     res.setContentType("text/plain");
     PrintWriter out = res.getWriter();
     out.print("This a servlet \nand the number is " + ++number);
     out.close();
  }
}

The web descriptor of the preceding servlet, web.java, is below.

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
  <servlet>
  <servlet-name>servletX</servlet-name>
  <servlet-class>ConnServlet</servlet-class>  
  </servlet>
  <servlet-mapping>
    <servlet-name>servletX</servlet-name>
    <url-pattern>/servlet/example1</url-pattern>
  </servlet-mapping>
</web-app>

And Conn3 midlet is in the following program code.

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

public class Conn3 extends MIDlet implements CommandListener
{
  private Display display;
  private Form form;
  private Command cmConnect;
  private Command cmExit;
  private StringItem teksti;

  public Conn3()
  {
     display = Display.getDisplay(this);

     cmConnect = new Command("Connect", Command.SCREEN, 1);
     cmExit = new Command("Exit", Command.EXIT, 1);
     teksti = new StringItem(null, "If you want servlet connection, select Connect");
     form = new Form("Servlet connection");
     form.addCommand(cmExit);
     form.addCommand(cmConnect);
     form.append(teksti);
     form.setCommandListener(this);
  }
  public void startApp()
  {
     display.setCurrent(form);
  }
  public void pauseApp()
  { }
  public void destroyApp(boolean unconditional)
  { }
  public void commandAction(Command c, Displayable s)
  {
     if (c == cmConnect)
     {
       Thread t = new Thread(){
          public void run(){
            try{
               connect();
            } catch (Exception e){
               System.err.println("Msg: " + e.toString());
            }
         }
       };
       t.start();
     }
      else if (c == cmExit)
     {
       destroyApp(false);
       notifyDestroyed();
     }
  }
  private void connect() throws IOException
  {
     HttpConnection conn = null;
     InputStream input = null;
     String url = "http://localhost:8080/servlet/example1";
     try
     {
        conn = (HttpConnection) Connector.open(url);
        input = conn.openInputStream();
        if (conn.getResponseCode() == HttpConnection.HTTP_OK)
        {
           int length = (int) conn.getLength();
           String str;
           if (length != -1)
           {
              byte data[] = new byte[length];
              input.read(data);
              str = new String(data);
           }
           else  // no length of the message
           {
              ByteArrayOutputStream bStream = new ByteArrayOutputStream();
              int ch;
              while ((ch = input.read()) != -1)
                      bStream.write(ch);
              str = new String(bStream.toByteArray());
              bStream.close();
           }
           teksti.setText(str);
        } else
           teksti.setText(new String(conn.getResponseMessage()));
     }
     finally
     {
      if (input != null)
         input.close();
      if (conn != null)
         conn.close();
     }
  }
}

Example.
Conn4Servlet is a servlet, which gets in a GET request two parameters, userID and password, and sends a response. Conn4 is a midlet, which sends a GET request with two parameters , userID and password, and receives the response and shows it on the display.

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;

public class Conn4Servlet extends HttpServlet
{
  protected void doGet(HttpServletRequest req, HttpServletResponse res)
                       throws ServletException, IOException
  {
     res.setContentType("text/plain");
     PrintWriter out = res.getWriter();
     String userID = req.getParameter("userID");
     String password = req.getParameter("password");
     out.println(userID + ", Password is not valid");
     out.close();
  }
}

The Conn4 midlet is below.

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

public class Conn4 extends MIDlet implements CommandListener
{
  private Display display;
  private Form form;
  private Form form2;
  private TextField userID;
  private TextField password;
  private StringItem text;
  private Command cmConnect;
  private Command cmExit;

  public Conn4()
  {
     display = Display.getDisplay(this);
     cmConnect = new Command("Connect", Command.SCREEN, 1);
     cmExit = new Command("Exit", Command.EXIT, 1);
     userID = new TextField("User id:", "", 10, TextField.ANY);
     password = new TextField("Password:", "", 10, TextField.PASSWORD);
     form = new Form("Login");
     form.addCommand(cmExit);
     form.addCommand(cmConnect);
     form.append(userID);
     form.append(password);
     form.setCommandListener(this);
  }
  public void startApp()
  {
     display.setCurrent(form);
  }
  public void pauseApp()
  { }
  public void destroyApp(boolean unconditional)
  { }
  public void commandAction(Command c, Displayable s)
  {
     if (c == cmConnect)
     {
       Thread t = new Thread(){
          public void run(){
            try{
               connect();
            } catch (Exception e){
               System.err.println("Msg: " + e.toString());
            }
         }
       };
       t.start();
     }
      else if (c == cmExit)
     {
        destroyApp(false);
        notifyDestroyed();
     }
  }
  private void connect() throws IOException
  {
     HttpConnection conn = null;
     InputStream input = null;
     String url = "http://localhost:8080/servlet/example2?userID=" +
                   userID.getString() + "&password=" + password.getString();
     try
     {
        conn = (HttpConnection) Connector.open(url);
        input = conn.openInputStream();
        process(conn, input);
     }
     finally
     {
      if (input != null)
         input.close();
      if (conn != null)
         conn.close();
     }
  }

  private void process(HttpConnection conn, InputStream input) throws IOException
  {
     text = new StringItem("Login:", "");
     if (conn.getResponseCode() == HttpConnection.HTTP_OK)
     {
        int length = (int) conn.getLength();
        String str;
        if (length != -1)
        {
           byte data[] = new byte[length];
           input.read(data);
           str = new String(data);
        }
        else // no length returned
        {
           ByteArrayOutputStream bStream = new ByteArrayOutputStream();
           int ch;
           while ((ch = input.read()) != -1)
                    bStream.write(ch);
           str = new String(bStream.toByteArray());
           bStream.close();
        }
           text.setText(str);
     } else
        text.setText(new String(conn.getResponseMessage()));
        // show main window
        form2 = new Form("Main window");
        form2.addCommand(cmExit);
        form2.append(text);
        form2.setCommandListener(this);
        display.setCurrent(form2);
  }
}

Web descriptor for the servlet, web.xml, is following.

  <servlet>
    <servlet-name>servletY</servlet-name>
    <servlet-class>Conn4Servlet</servlet-class>  
  </servlet>
  <servlet-mapping>
    <servlet-name>servletY</servlet-name>
    <url-pattern>/servlet/example2</url-pattern>
  </servlet-mapping>

 

Example.
Conn5Servlet is a servlet, which receives HTTP request by POST method and sends a response. The request has two parameters,  userID and password. Conn5 is a midlet , which sends a POST request with two parameters , userID and password, and receives the response and shows it on the display.

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;

public class Conn5Servlet extends HttpServlet
{
  protected void doPost(HttpServletRequest req, HttpServletResponse res)
                       throws ServletException, IOException
  {
     res.setContentType("text/plain");
     PrintWriter out = res.getWriter();
     String userID = req.getParameter("userID");
     String password = req.getParameter("password");
     out.println(userID + ", Password is not valid");
     out.close();
  }
}

The Conn5 midlet is below.

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

public class Conn5 extends MIDlet implements CommandListener
{
  private Display display;
  private Form form;
  private Form form2;
  private TextField userID;
  private TextField password;
  private StringItem teksti;
  private Command cmConnect;
  private Command cmExit;

  public Conn5()
  {
     display = Display.getDisplay(this);
     cmConnect = new Command("Connect", Command.SCREEN, 1);
     cmExit = new Command("Exit", Command.EXIT, 1);
     userID = new TextField("User id:", "", 10, TextField.ANY);
     password = new TextField("Password:", "", 10, TextField.PASSWORD);
     form = new Form("Login");
     form.addCommand(cmExit);
     form.addCommand(cmConnect);
     form.append(userID);
     form.append(password);
     form.setCommandListener(this);
  }
  public void startApp()
  {
     display.setCurrent(form);
  }
  public void pauseApp(){ }
  public void destroyApp(boolean unconditional){ }
  public void commandAction(Command c, Displayable s)
  {
     if (c == cmConnect)
     {
        Thread t = new Thread(){
           public void run(){
             try{
                connect();
             } catch (Exception e){
                System.err.println("Msg: " + e.toString());
             }
           }
        };
        t.start();
     }
      else if (c == cmExit)
     {
        destroyApp(false);
        notifyDestroyed();
     }
  }
  private void connect() throws IOException
  {
     HttpConnection conn = null;
     OutputStream output = null;
     InputStream input = null;
     String url = "http://localhost:8080/servlet/example3";
     try
     {
        conn = (HttpConnection) Connector.open(url);
        conn.setRequestMethod(HttpConnection.POST);
        conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        conn.setRequestProperty("User-Agent", "Profile/MIDP-2.0 Configuration/CLDC-1.1");
        output = conn.openOutputStream();

        byte data[] = ("userID=" + userID.getString()).getBytes();
        output.write(data);
        data = ("&password=" + password.getString()).getBytes();
        output.write(data);
        output.close();

        input = conn.openInputStream();
        kasittely(conn, input);
     }
     finally
     {
      if (input != null)
         input.close();
      if (conn != null)
         conn.close();
     }
  }

  private void kasittely(HttpConnection conn, InputStream input) throws IOException
  {
     teksti = new StringItem("Login:", "");
     if (conn.getResponseCode() == HttpConnection.HTTP_OK)
     {
        int length = (int) conn.getLength();
        String str;
        if (length != -1)
        {
           byte data[] = new byte[length];
           input.read(data);
           str = new String(data);
        }
        else  // no length returned
        {
           ByteArrayOutputStream bStream = new ByteArrayOutputStream();
           int ch;
           while ((ch = input.read()) != -1)
                    bStream.write(ch);
           str = new String(bStream.toByteArray());
           bStream.close();
        }
           teksti.setText(str);
     } else
        teksti.setText(new String(conn.getResponseMessage()));
        // shows main window
        form2 = new Form("Main window");
        form2.addCommand(cmExit);
        form2.append(teksti);
        form2.setCommandListener(this);
        display.setCurrent(form2);
  }
}

Web descriptor for the servlet, web.xml, is following.

  
  <servlet>
    <servlet-name>servletZ</servlet-name>
    <servlet-class>Conn5Servlet</servlet-class>  
  </servlet>
  <servlet-mapping>
    <servlet-name>servletZ</servlet-name>
    <url-pattern>/servlet/example3</url-pattern>
  </servlet-mapping>


8. RMS - Record Management Systems

MIDP provides a mechanism for midlets to persistently store data and later retrieve it. This persistent storage mechanism, called the Record Management System (RMS), is modeled after a simple record-oriented datastorage.

The classes and interfaces of the RMS are in the javax.microedition.rms package. The most important class is RecordStore, which represents a record store. It's most important methods are:

  • openRecordStore(), opens (and possibly create) a record store
  • deleteRecordStore(), deletes a named record store
  • addRecord(), adds a new record to the record store
  • getRecord(), returns the data stored in the given record
  •  

Example.
The following Storage1 midlet creates a DB1 named record store. A user can enter some text and save it with Save command. The user can also retrieve the saved record by using Retrieve command.

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

public class Storage1 extends MIDlet implements CommandListener
{
  private Display display;
  private TextBox text;
  private Command cmSave;
  private Command cmRetrieve;
  private Command cmExit;
  private int n = 1;

  private RecordStore rs;

  public Storage1()
  {
     display = Display.getDisplay(this);
     cmSave = new Command("Save", Command.SCREEN, 1);
     cmRetrieve = new Command("Retrieve", Command.SCREEN, 1);
     cmExit = new Command("Exit", Command.EXIT, 1);
     text = new TextBox("Text", "", 44, TextField.ANY);
     text.addCommand(cmExit);
     text.addCommand(cmSave);
     text.addCommand(cmRetrieve);
  }
  public void startApp()
  {
     text.setCommandListener(this);
     display.setCurrent(text);
     try{
       rs = RecordStore.openRecordStore("DB1", true);
     }catch(Exception e){
       System.err.println("** Error: openRecordStore(): " + e.getMessage());
     }
  }
  public void pauseApp()
  { }
  public void destroyApp(boolean unconditional)
  { }
  public void commandAction(Command c, Displayable s)
  {
     if (c == cmSave)
     {
       try{
          String str = text.getString();
          byte[] record = str.getBytes();
          rs.addRecord(record, 0, str.length());
       }catch(Exception e){
         System.err.println("** Error: addRecord(): " + e.getMessage());
       }
     }
     else if (c == cmRetrieve)
     {
       try{
          byte[] data;
          data = rs.getRecord(n);
          String record = new String(data);
          text.setString(record);
          n++;
       }catch(Exception e){
          System.err.println("** Error: getRecord(): " + e.getMessage());
       }
    }
     else if (c == cmExit)
     {
        try{
           rs.closeRecordStore();
        }catch(Exception e){
           System.err.println("** Error: closeRecordStore(): " + e.getMessage());
        }
        destroyApp(false);
        notifyDestroyed();
     }
  }
}

Example.
The following Storage2 midlet use the record store created in the previous example. The midlet has a Retrieve command, which fetches records from the record store sequentially. The Exit command deletes the record store.

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

public class Storage2 extends MIDlet implements CommandListener
{
  private Display display;
  private TextBox text;
  private Command cmSave;
  private Command cmRetrieve;
  private Command cmExit;
  private int n = 1;

  private RecordStore rs;

  public Storage2()
  {
     display = Display.getDisplay(this);
     cmSave = new Command("Save", Command.SCREEN, 1);
     cmRetrieve = new Command("Retrieve", Command.SCREEN, 1);
     cmExit = new Command("Exit", Command.EXIT, 1);
     text = new TextBox("Text", "", 44, TextField.ANY);
     text.addCommand(cmExit);
     text.addCommand(cmRetrieve);
 }
  public void startApp()
  {
     text.setCommandListener(this);
     display.setCurrent(text);
     try{
        rs = RecordStore.openRecordStore("DB1", false);
     }catch(Exception e){
        System.err.println("** Error: openRecordStore(): " + e.getMessage());
    }

  }
  public void pauseApp()
  { }
  public void destroyApp(boolean unconditional)
  { }
  public void commandAction(Command c, Displayable s)
  {
     if (c == cmRetrieve)
     {
       try{
          byte[] data;
          data = rs.getRecord(n);
          String record = new String(data);
          text.setString(n + ". " + record);
          n++;
       }catch(InvalidRecordIDException e){
          text.setString("** no record **");
       }catch(Exception e){
          System.err.println("** Error: getRecord(): " + e.getMessage());
       }

     }
     else if (c == cmExit)
     {
       try{
          rs.closeRecordStore();
          RecordStore.deleteRecordStore("DB1");
       }catch(Exception e){
          System.err.println("** Error: deleteRecordStore(): " + e.getMessage());
       }
       destroyApp(false);
       notifyDestroyed();
     }
  }
}

 

 

References related to Java ME

docs.oracle.com/javase/tutorial/java/index.html.
http://www.developer.nokia.com/Resources/Library/Java/
http://docs.oracle.com/javame/config/cldc/ref-impl/midp2.0/jsr118/index....
http://j2megame.uw.hu/index.html
http://www.roseindia.net/software-tutorials/detail/22805
http://stackoverflow.com/questions/9959219/j2me-program-to-create-a-grid...
Multithreading in J2ME
http://www.oracle.com/technetwork/systems/index-155545.html

http://developer.nokia.com/Community/Wiki/Getting_System_properties_in_MIDP  (system properties for S40 devices)

http://developer.nokia.com/Community/Wiki/How_to_write_data_to_a_file_in_Java_ME (file related issues)

http://developer.nokia.com/Community/Wiki/How_to_list_root_file_systems_in_Java_ME

http://developer.nokia.com/Community/Wiki/Developing_a_2D_game_in_Java_ME_-_Part_1

http://www.informit.com/articles/article.aspx?p=375708

http://docs.oracle.com/javase/1.5.0/docs/guide/sound/programmer_guide/chapter7.html

http://docs.oracle.com/javase/1.5.0/docs/api/javax/sound/sampled/AudioInputStream.html

http://www.java-tips.org/java-se-tips/javax.sound/capturing-audio-with-java-sound-api.html

http://www.oracle.com/technetwork/articles/java/compress-1565076.html