Java Micro: High Level API

Das Konzept der High-Level-API ist nicht sehr komplex. Es gilt das Zusammenspiel von MIDlet, Display, Displayables und den Commands zu verstehen. Es erfolgt ein erster Überblick:

Will ein MIDlet etwas auf dem Bildschirm des Handys darstellen, muss es auf das Display zugreifen. Das Display ist eine J2ME-Klasse aus dem Package javax.microedition.lcdui. Dieses Display kapselt, nach guter objektorientierter Manier, die tatsächliche Hardware des Handys. Jedes MIDlet hat Zugriff auf genau ein Display. Es kann eine Referenz auf das Display durch folgenden Aufruf beziehen:

Display myDisplay = Display.getDisplay(this);

Ein Display ist in der Lage Displayables, also anzeigbare Dinge, zu präsentieren. Das Displayable ist ein Interface welches sich auch in der javax.microedition.lcdui Bibliothek befindet. Es gibt verschiedene Displayable, aber für die High-Level-Programmierung sind vor allem die Screens mit ihren den wichtigsten vier Subklassen: Form, TextBox, Alert und List. Anwendungen, die die High-Level-API nutzen setzen sich im Wesentlichen aus Objekten dieser Klassen zusammen.

Jedem Displayable können zusätlich Kommandos (Objekte der Klasse Command) zugeordnet werden. Commands übernehmen im wesentlichen die Aufgabe der Schnittstelle zwischen Benutzer und Programm. Es können jedem Screen beliebig viele Kommandos hinzugefügt werden, wobei normalerweise nur zwei direkt auf dem Bildschirm angezeigt werden. Für weitere Kommandos wird automatisch ein separates Menü erzeugt. Das Aussehen und die Position von den Kommandos werden alleine von dem Displayable bestimmt, den einzigen Einfluss, den das Command auf den Screen hat, ist das Label des Kommandos.

Es gibt folgende Kommandotypen:

Kommandotyp Beschreibung
OK positive Antwort an den Screen
EXIT beendet die Anwendung
CANCEL negative Antwort an den Screen
BACK navigiert zum vorherigen Screen
HELP anfrage auf einen Helpscreen
ITEM Auswahl eines expliziten Items auf dem Screen
SCREEN Bildschirmspezifische Kommandos
STOP unterbricht den momentanen Ablauf der Anwendung

Mit Hilfe der addCommand() Methode können Commands zu einer Textbox oder anderen Subklassen von Displayable hinzugefügt werden.

Um dem MiDlet möglich zu machen Commands zu empfangen benötigt man einen sogenannten CommandListener. Er ist die Schnittstelle zwischen den Kommandos und dem Displayable.

Das folgende MIDlet soll das Vorgehen an einem kleinen Beispiel erläutern:

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

 public class MyMIDlet extends MIDlet implements CommandListener {
   
   private TextBox box1;
   private TextBox box2;
   
   private static final Command CMD_OK = new Command("OK", Command.OK, 0);
   private static final Command CMD_BACK = new Command("Back", Command.BACK, 0);
   private static final Command CMD_EXIT = new Command("Exit", Command.EXIT, 0);
   
   /** erzeugt die TextBox 1 einmalig. Bei jedem folgenden Aufruf
    * wird Referenz auf die fertige Box geliefert */
   private TextBox getBox1() {
       if( box1 == null ) {
           // Textbox erzeugen
           box1 = new TextBox("Box1-Titel", "initialer Text Box1", 100, TextField.ANY);
           box1.addCommand(CMD_OK);
           box1.addCommand(CMD_EXIT);
           box1.setCommandListener(this);
       }
       return box1;
   }
   
   private TextBox getBox2() {
       if( box2 == null ) {
           // Textbox erzeugen
           box2 = new TextBox("Box2-Titel", "initialer Text Box2", 100, TextField.ANY);
           box2.addCommand(CMD_BACK);
           box2.addCommand(CMD_EXIT);
           box2.setCommandListener(this);
       }
       return box2;
   }
   
   public void commandAction(Command cmd, Displayable dsp) {
       if(dsp == box1) {
           if( cmd == CMD_OK) {
               Display.getDisplay(this).setCurrent(getBox2());
           }
       } else if (dsp == box2) {
           if( cmd == CMD_BACK ) {
               Display.getDisplay(this).setCurrent(getBox1());
           }
       }
       
       if( cmd == CMD_EXIT ) {
           Display.getDisplay(this).setCurrent(null);
           destroyApp(false);
           notifyDestroyed();
       }
   }   
   
   public void startApp() {
       Display.getDisplay(this).setCurrent(getBox1());
   }
   
   public void pauseApp() {
   }
   
   public void destroyApp(boolean unconditional) {
   }
}

MyMidlet implementiert im obigen Beispiel selber das Interface CommandListener - ein, bei kleinen Programmen, gängige Vorgehen. Innerhalb der Klasse werden zunächst drei Commandos definiert, jeweils eins vom Typ OK, EXIT und BACK. Es folgen zwei Methoden getBox1 und getBox2. Beide Methoden erzeugen jeweils beim ersten Aufruf eine neue Textbox. Bei jedem weiteren Aufruf liefern sie die Referenz auf die zuvor erzeugte Textbox.

Die Erzeugung der Textbox erfolgt einfach durch den Aufruf von

 new TextBox("Box1-Titel", "initialer Text Box1", 100, TextField.ANY);

Der erste Parameter gibt die Überschrift der Box an, der zweite setzt den initialen Text, der dritte definiert die Länge der Box und der letzte definiert die erlaubten Werte der Box (hier alle).

Mit dem Statement

box1.addCommand(CMD_OK);

wird ein Kommando an die Textbox gebunden. Das ist für jedes Displayable mit der Methode addCommand möglich. Im Beispielprogramm werden zwei Kommandos an die Textbox gebunden, das Kommando OK und das Kommando EXIT.

Mit dem Statement

box1.setCommandListener(this);

wird erklärt, dass der CommandListener für box1 das MIDlet selbst ist (this). Wird ein Kommando auf dieser Textbox ausgelöst, so wird die Bearbeitung des Kommandos durch das Midlet erfolgen.

Die Erzeugung der zweiten Textbox erfolgt analog in getBox2().

Wenn das MIDlet gestartet wird, wird nach dem Konstruktor die Methode startApp() aufgerufen. Im Beispielprogramm wird dort als aktueller Screen die Textbox 1 gesetzt. Das erfolgt durch folgenden Code:

  Display.getDisplay(this).setCurrent(getBox1());

Es wird die Methode getBox1() gerufen, die die Textbox erzeugt. Mittels Display.getDisplay(this) wird das Display des MIDlets ermittelt und durch setCurrent() wird die gerade erzeugte Textbox zum aktuellen Screen. Diesen zeigt der Display also nach dem Start der Anwendung an.

Dabei ist der initale Text der Box zu sehen und die beiden Kommandos, OK und EXIT sind sichtbar. Diese Kommandos werden meist durch Softbuttons auf dem Handy dargestellt. Wird eines der Kommandos aktiviert, so wird der CommandListener der Textbox aufgerufen. In diesem Beispiel ist das das MIDlet selbst. Es wird die Methode commandAction aufgerufen.

Der Methode werden zwei Parameter übergeben: das aufgerufenen Kommando und das Displayable auf dem das Kommando aufgerufen wurde. Im Beispielprogramm wird zunächst getestet, ob das Kommando auf box1 aktiviert wurde. War das der Fall wird getestet, ob das Kommando OK gewählt wurde. War das der Fall, wird die box2 aktiviert. Das erfolgt genauso, wie die box1 in startApp() erzeugt wurde.

Wurde ein Kommando auf box2 aufgerufen, wird getestet, ob das Kommando BACK gewählt wurde. Ist das der Fall, wird die box1 wieder aktiviert. Mittels OK auf box1 und BACK auf box2 kann hin und her geschaltet werden.

Im letzten Teil der Methode wird getestet, ob das EXIT-Kommando gerufen wurde. Dieser Test erfolgt unabhängig von der jeweiligen Textbox. Das ist nicht zwingend so. Man hätte den Test auch in die obigen if-blöcke schreiben können. Es sollte hier nur demonstriert werden, dass man auf Kommandos auch unabhängig davon reagieren kann, wo das Kommando aufgerufen wurde.

Wurde EXIT gewählt, so wird die Anwendung beendet.