Programmierung mit dem J2ME MIDP
von Karl Banke
Das Java "Mobile Information Device Profile", MIDP, ist die Ausprägung von Suns
Programmierumgebung Java, die zur Erstellung von mobilen und vernetzten
Java Anwendungen auf kleinen portablen Geräten verwendet findet.
Zielplattform sind dabei insbesondere 3G Mobiltelefone, die über eine
begrenzte Bandbreite, geringe Prozessorleistung und Monochrom- oder
Farbdisplays geringer Auflösung verfügen. Aber auch Kassenterminals oder
2-Weg Pager Systeme kommen als Zielplatformen in Frage.
Dabei stellt MIDP basierend auf der CLDC (Connected Limited
Device Configuration) Spezifikation Bibliotheken
zur Verfügung. Als einer der großen Vorteile von Java im PC- und
Server Bereich gilt bekanntlich die weitgehende Plattformunabhängigkeit der
erstellten Software. Im Folgenden soll u.a. untersucht
werden, ob und inwieweit dies auch für MIDP Anwendungen gilt.
Mein Name ist MIDlet
Ähnlich zu Applets - Java Bytecode, der aus dem Inter- oder Intranet geladen
und im Webbrowser ausgeführt wird - definiert die MIDP sog.
MIDlets. Diese werden von der MIDP Implementierung verwaltet
und bilden den Einstiegspunkt für die Programmierung. Im Unterschied zu
"normalen" Java Applikationen ist es nicht möglich, ein Programm mit
einer main Routine zu starten. Vielmehr wird die Applikation von der
Applikationsmanagementsoftware - im folgenden kurz Framework genannt -
verwaltet.
Midlets werden in jar-Archiven ausgeliefert, die die erforderlichen
Klassen und Konfigurationsparameter
enthalten. Beim Start eines MIDlets wird vom Framework die
Methode startApp() aufgerufen, in der die Initialisierung der Applikation
durchgeführt wird. Das Framework kann ein MIDlet durch Aufruf von
pauseApp() temporär stoppen, z.B. wenn eingehende Telefonanrufe beantwortet
werden müssen. Schließlich kann das MIDlet durch den Aufruf der destroyApp()
Methode vom Framework zerstört werden. Wird es explizit aus dem Programmcode
beendet, so wird die Methode notifyDestroyed() verwendet, um das Framework
vom Beenden des MIDlets zu benachrichtigen.
Das CLDC, auf dem das MIDP basiert, hat einige wesentliche Einschränkungen,
die es von einer Java 2 Standard Edition (J2SE) basierten Java Umgebung unterscheiden.
So gibt
es z.B. keine Thread-Gruppen und keine Methode Object.finalize().
Die Menge der verfügbaren nativen Funktionen ist abgeschlossen.
Das bedeutet u.a., das Bibliotheken die auf gerätespezifische Low Level
Funktionalitäten zugreifen vom Hersteller des Geräts selbst bereitgestellt
werden müssen. Der Java Reflection Mechanismus - die Abfrage von Typinformationen
zur Laufzeit - steht im CLDC nicht zur Verfügung.
Aus Sicherheitsgründen dürfen auch keine selbstgeschriebenen Classloader
verwendet werden.
Während sich diese Einschränkungen im Alltag als relativ
unspektakulär erweisen, gibt es ein fehlendes Feature, das sicherlich von
vielen Entwicklern schmerzlich vermisst wird.
Der CLDC fehlt nämlich - mit Hinweis auf Performance Überlegungen -
jegliche Unterstützung für Fließkommaoperationen. Da eine Vielzahl von
denkbaren Anwendungen, wie z.B. Taschenrechner, Bezahlsysteme,
Messdatenanzeige usw. mit Fließkommazahlen arbeiten ist es zumindest
erstaunlich, dass nicht zumindest eine Klassenbibliothek im Lieferumfang
enthalten ist, um solche Operationen vereinheitlicht durchzuführen. Das
jedes Projekt für solche grundlegenden Operation wieder ein eigenes
Süppchen kochen soll, ist eigentlich nicht einzusehen.
Die Bibliotheken
Um plattformunabhängig programmieren zu können, sind natürlich entsprechend
übergreifende Klassenbibliotheken notwendig. Hierzu liefert das MIDP die
Bibliotheken javax.microedition.lcdui, javax.microedition.io und
javax.microedition.rms.
Sie dienen zur Erstellung grafischer Benutzeroberflächen, der Ein- und Ausgabe
von Daten über Netzwerkverbindungen und zur persistenten Datenspeicherung
auf dem mobilen Gerät selbst.
Oberflächen
Das Paradigma zur Verwendung grafischer Oberflächen sieht vor, dass immer
genau ein Objekt vom Typ Displayable angezeigt wird. Dabei können
jedem Objekt eine beliebige Anzahl an Commands hinzugefügt werden.
Ereignisse an der Benutzeroberfläche werden mit Listener-Klassen behandelt. Dabei
hat jedes Objekt - im Unterschied zu J2SE - höchstens einen Listener.
In der Oberfläche wird zwischen "High Level" und "Low Level" API
unterschieden. High Level bezeichnet dabei Komponenten zur Definition und
Behandlung von Formularen.
Die Anzahl der High Level Komponenten ist aufgrund der geringen Displaygröße
äußerst beschränkt. Es stehen im Prinzip nur Auswahlliste, Textfeld und
Pegeleinstellung zur Verfügung. Diese können zu relativ komplexen Formularen
groupiert werden. Ein High Level Formular kann mit einem Ticker zur fortlaufenden
Informationsanzeige versehen werden.
Die Low Level API umfasst im wesentlichen ein Canvas Element, auf das
direkt gezeichnet werden kann. Dabei unterstützt das MIDP zwar
prinzipiell Farbdisplays. Leider werden aber weder Alpha Blending noch
Farbmischung, geschweige denn verschiedene Grafik Layer angeboten.
Dies ist bei der Programmierung grafischer Anzeigen
allgemein und natürlich insbesondere bei der Erstellung
von Spielen recht hinderlich.
Verbindungen
Allgemein werden Objekte vom Typ Connections verwendet,
um Netzwerkverbindungen darzustellen. Eine Connection kann im Client- oder
Server-Mode aktiv sein, so dass ein Gerät auch eingehende Verbindungen
akzeptieren kann, z.B. mittels Bluetooth oder Infrarot Schnittstelle von
anderen mobilen Geräten. Es werden Stream Connections und
Datagram Connections unterschieden. Zur Verbindung auf zentrale Server kommt
sicherlich der HttpConnection besondere Bedeutung zu. Diese steht auch in
nicht IP Netzen, wie WAP, stets zur Verfügung.
Persistenz
Ein schönes Feature ist, dass jedes MIDlet verschiedene Stores anlegen
kann, um sog. Records zu speichern. Dies ermöglichst eine Datenhaltung,
z.B. von Adressen, Passwörtern, Benutzereinstellungen und High Score Listen.
Auch hier ist es mit der Abstraktion nicht allzuweit her. Einzelne Records
werden als Bytefeld abgespeichert und über eine laufende Nummer, die recordId
identifiziert. Basierend auf den bestehenden Bibliotheken lassen sich aber
durchaus abstraktere Komponenten, wie Adressdatenbank, Highscore Listen,
Preference API u.ä. erstellen.
Was noch fehlt
Leider bietet das MIDP keine einheitliche Spezifikation für einen Zugriff
auf Telefoniefunktionen. Damit ist eines der attraktivsten Anwendungsfelder
zunächst nicht zugänglich. Hier haben wohl Sicherheitsüberlegungen eine
Rolle gespielt. Wer kann sonst sicher sein, dass sich hinter dem netten
Spielchen nicht ein perfider 0190 Dialer verbirgt.
Auch die Tatsache, dass das MIDP eben nicht nur für Mobiltelefone,
sondern auch für andere schmalbanding vernetzte Geräte eingesetzt werden soll,
hat hier sicherlich eine gewisse Rolle gespielt.
Auch ist es schade, dass das MIDP keinerlei Zugriff auf Soundfähigkeiten
der Geräte zulässt. Leider fehlt damit nicht nur die Möglichkeit
zur Untermalung von Spielen. Es ist nicht einmal möglich, einfache akustische
Signale vom Schlage eines System.beep() zu erzeugen.
Was schon geht
Trotz der hier formulierten Kritik ist es durchaus möglich auf Basis eines
kleinsten gemeinsamen Nenners recht attraktive Applikationen für das MIDP
zu entwickeln. Dies zeigt auch eine große Zahl von MIDlets, die online
verfügbar sind. Die folgenden Screenshots der Emulatoren von Nokia und
Javasoft zeigen ein relativ einfaches Beispiel für ein Geschicklichkeitsspiel
inklusive einer Highscoreverwaltung, die auf dem Records Mechanismus basiert.
Die zugehörige Jar Datei und der Applikation Deskriptor
können heruntergeladen werden.
Zusammenfassend kann man sagen, dass das MIDP eine interessante Plattform
bietet, um kleinere Applikationen für mobile Geräte zu erstellen. Dem Anspruch
der Plattformunabhängigkeit wird man allerdings nur schwer gerecht werden
können. Erfordern doch Anpassungen an unterschiedliche Displays schon einen
erheblichen programmatischen Aufwand, der sich natürlich auch in entsprechend
größeren Anwendungen niederschlägt. Wahrscheinlicher ist aus Sicht des Autors,
dass Entwicklungen dediziert für Geräte eines bestimmten Herstellers
durchgeführt werden. Hier stehen dann auch viele der Funktionalitäten
zur Verfügung, die wir in der Spezifikation schmerzlich vermisst hatten.
Dennoch bietet Java hier den Vorteil, dass sich Entwickler zumindest einer
gemeinsamen Basisplattform bedienen können. Ein Unternehmen, das Spiele
entwickelt, muss zwar immer noch Versionen für unterschiedliche Geräte
ausliefern. Die Softwareentwicklung selbst gestaltet sich aber - u.U. auch
durch den Einsatz entsprechender Frameworks - effektiver. Auch ist es
vorteilhaft, dass Java sich hier als allgemeine Programmiersprache für mobile
Geräte definiert und nicht dediziert als ein Framework zur Spiele Erstellung
oder zur Telefonie.
Ausblick
Viele der hier aufgeführten Defizite der MIDP 1.0 werden in der Version 2.0
behoben sein. So bietet die Version 2.0, die sich seit dem 18. April 2002 im
Public Review befindet, u.a. Unterstützung für transparente PNG Bilder,
Sound und für sichere Netzwerkverbindungen. Insbesondere Spieleprogrammierer
werden sich über Sprites und die Unterstützung mehrerer Layer auf dem
Display freuen.
Optional werden MIDI Formate,
der Zugriff auf vorhandene serielle Schnittstellen und
die Möglichkeit verschiedener Push Formate unterstützt.
Literatur
- CLDC and the K Virtual Machine. Spezifikation und Referenzimplementierung für die CLDC.
- Mobile Information Device Profile. Spezifikation und Downloads zu MIDP.
- JSR 135 Mobile Media API. Spezifikation einer Multimedia API für CLDC und CDC J2ME Configurations
- JSR 178 Mobile Game API. Definition einer Spiele API als optionales Paket für MIDP
- JSR 118
Mobile Information Device Profile 2.0.
- Midlet.org bietet einige schöne Midlets an.
Karl Banke
2004-01-06