21.01 Java Micro Edition – Ein Einstieg
Sie haben bereits im Kapitel 01.02 Einsatzgebiete von Java etwas über die Java Micro Edition (Java ME) erfahren. In den nachfolgenden Kapiteln werden Sie lernen, wie Sie Anwendungen und Spiele für Mobile Endgeräte entwickeln.
Grundsätzliches
Kleine mobile Begleiter wie bspw. Handys sind selbstverständlich nicht so Leistungsstark wie Ihr Rechner zuhause oder an Ihrem Arbeitsplatz. Deshalb kommen in der Java Micro Edition andere (wenn auch teilweise sehr ähnliche) Klassen zum Einsatz als bei der Desktop oder Webentwicklung mit Java. Folglich benötigen Sie auch ein anderes Software Development Kit (SDK). Dieses werden wir später gemeinsam herunterladen und auf Ihrem Rechner konfigurieren.
Generell besitzt ein mobiles Endgerät eine Standardsammlung an Klassen, welche von der KVM interpretiert werden.
Die KVM stellt dabei den kleinen Bruder der JVM (Java Virtual Machine) dar und ist für das Ausführen Ihres Java Codes auf mobilen Geräten zuständig.
Welche Klassen standardmäßig zur Verfügung stehen hängt vom jeweiligen Gerät ab. So unterscheidet man zuerst zwischen CLDC (Connected Limited Device Configuration) und CDC (Connected Device Configuration). Die CLDC wird von eher schwächeren Geräten wie bspw. Handys unterstützt. Daher auch das Limited im Namen. Anders sieht es bei der CDC aus. Diese ist für alle Geräte mit mehr Leistung und Ressourcen gedacht. Momentan ist es noch so, dass in den meisten Fällen nur die CLDC unterstützt wird. Dies wird sich auch in absehbarer Zukunft nicht ändern. Deshalb beschränken sich dieses und die nachfolgenden Kapiteln vorerst komplett auf die CLDC.
Die CLDC (und auch die CDC) spezifizieren zudem die Mindestanforderungen an ein Gerät. Diese können Sie hier nachlesen: CLDC 1.1, CLDC 1.0, CDC 1.1. Da die meisten Handys heutzutage CLDC 1.1 unterstützen, wird diese Konfiguration in den nachfolgenden Kapiteln verwendet. API-Dokumentation.
Den Konfigurationen untergeordnet existieren Profile. Diese Profile stellen die eigentlichen Bibliotheken mit Klassen dar, die Sie auf dem Gerät einsetzen können. Hier gibt es für die CLDC das MIDP (Mobile Information Device Profile) in der Version 1.0 (wird nur noch von bereits lange veralteten Handys eingesetzt), 2.0 (der aktuelle Standard auf mobilen Endgeräten) und 2.1 (wird nur von den wenigsten Geräten unterstützt). Auch diese Profile stellen zusätzlich Mindestanforderungen an das Endgerät. Diese betreffen bspw. die minimale Displayauflösung. Die jeweiligen Spezifikationen finden Sie hier: MIDP 1.0, MIDP 2.0. In den nachfolgenden Kapiteln werden Sie mit MIDP 2.0 arbeiten. API Dokumentation.
Weitere Funktionalitäten
Zugegeben, die Klassen und Funktionen, die das MIDP zur Verfügung stellt, sind sehr beschränkt. Jedoch erst durch eben diese kompakte Klassensammlung wird es möglich, eine Vielzahl an Geräten mit einem einzigen Standard abzudecken. Die meisten Plattformen unterstützen jedoch auch Funktionen in Form von optionalen JSRs, die über den Standard hinaus gehen. Hierzu gehören bspw. erweiterte Anzeigemöglichkeiten, Bluetooth-Funktionen und die Möglichkeit eines Zugriffs auf das Dateisystem des Handys. Eine Übersicht aller JSRs (inkl. den Standard-ME JSRs) finden Sie hier. Natürlich sollten Sie vorher überprüfen, ob das Zielgerät auch die entsprechende JSR unterstützt.
Java ME SDK/WTK
Wie bereits erwähnt, benötigen Sie ein anderes SDK (Software Development Kit) bzw. WTK (Wireless Toolkit) und können nicht mit dem Standard Kit von sun für gewöhnliche Java Anwendungen (JDK) arbeiten. Auf der Seite von sun finden Sie eine Übersicht der Verfügbaren Development Kits. In diesem Kapitel verwende ich die Version 3.0.
Die Version des Development Kits hat erst einmal nichts mit der verwendeten CLDC oder dem MIDP zu tun.
Nachdem Sie das SDK heruntergeladen haben, müssen Sie es selbstverständlich installieren. Dabei müssen in der Regel keine Besonderheiten beachtet werden.
Hello World
Mal wieder beginnt Ihr erstes Programm in einer neuen Technologie mit den Worten „Hello World“. Starten Sie hierzu das soeben installierte Development Kit. Sie sollten eine Oberfläche auf NetBeans-Basis sehen.
Selbstverständlich sind Sie nicht an diese Standard-Entwicklungsumgebung gebunden. Pulsar ist bspw. eine IDE zur Java Micro Edition Entwicklung auf Basis von Eclipse. Wenn Sie sich jedoch nicht von Ihrer aktuellen Eclipse-Version trennen möchten, können Sie sie mit dem Mobile Tools for Java (MTJ)-Plugin ME fähig machen.
Klicken Sie im Container Projects mit der rechten Maustaste. Im daraufhin erscheinenden Kontextmenü wählen Sie den Eintrag New Project. Es erscheint ein Wizard.
Als Projekt selektieren Sie MIDP Application und klicken auf Next. Im nächsten Dialog vergeben Sie als Project Name HelloMEWorld. Gleichzeitig setzen Sie das Projekt als Hauptprojekt (Set as Main Project), verzichten aber auf die Generierung eines Hello MIDlets. Ein MIDlet ist die Einstiegsklasse für jedes Java ME Programm und ist somit mit der Klasse vergleichbar, die in einer Desktop-Applikation die Main-Methode enthält.
Nach einem Klick auf Next setzen Sie die Emulator Platform auf CLDC Java(TM) Platform Micro Edition SDK 3.0, Device auf DefaultCldcPhone1, Device Configuration auf CLDC-1.1 und Device Profile auf MIDP-2.0. Dieser Dialog ist notwendig, um den gewünschten Emulator auszuwählen. Denn da Ihr Programm auf einem gewöhnlichen Rechner und nicht auf einem mobilen Endgerät entwickelt wird, können Sie die Anwendung auch nicht wie ein gewöhnliches Java Programm auf Ihrem Rechner testen. Deshalb benötigen Sie einen Emulator, der ein Handy oder ähnliches auf Ihrem Rechner simuliert, um Ihre Applikation auf einem gewöhnlichem PC zu testen.
Bestätigen Sie nun abschließend mit Finish. Es wird ein neues Projekt im Project Container auf der linken Seite angelegt. Nun müssen Sie ein neues Midlet anlegen. Hierzu klicken Sie mit der rechten Maustaste auf das Projekt und wählen New => Midlet aus.
Anschließend erscheint wieder ein Dialog. Wählen Sie als MIDlet Name Hello World Midlet (so heißt Ihr Programm später). Der MIDP Class Name sollte dann HelloWorldMidlet lauten. Unter MIDlet Icon könnten Sie ein Anwendungslogo definieren. Dies ist aber erst einmal nicht wichtig und bleibt leer. Bevor Sie auf Finish klicken, tragen Sie noch ein Package ein: de.jbb.hello.
In Ihrem HelloWorldMidlet
wurde folgender Standardcode erzeugt:
package de.jbb.hello; import javax.microedition.midlet.*; /** * @author Stefan Kiesel */ public class HelloWorldMidlet extends MIDlet { public void startApp() { } public void pauseApp() { } public void destroyApp(boolean unconditional) { } }
Die Startklasse jeder mobilen Applikation muss von der Klasse javax.microedition.midlet.MIDlet
erben. Diese abstrakte Klasse schreibt vor, dass die Methoden startApp()
, pauseApp()
und destroyApp(boolean unconditional)
implementiert werden. Werfen wir einen kurzen Blick auf die Aufgaben dieser Methoden.
startApp()
Wird beim Start der Applikation und nach dem Durchlauf des Konstruktors aufgerufen. Hier sollten Sie Ihre Anwendung (je nach zu ladender Menge ggf. in einem extra Thread) initialisieren. Stellen Sie aber sicher (bspw. durch einen boolean
als Flag), dass die Initialisierung nur ein einziges Mal ausgeführt wird. Denn diese Methode wird ein weiteres Mal aufgerufen, wenn die Anwendung aus dem Status pausiert wieder erweckt wird. In diesem Fall ist es üblich die Standardanzeige zu reaktivieren. Nach Ablauf der Methode hat das Midlet den Status aktiv – sofern keine MIDletStateChangeException
geworfen wurde, welche signalisiert, dass das Midlet zum jetzigen Zeitpunkt nicht starten kann.
pauseApp()
Diese Methode wird vom Mobiltelefon (und nicht von Ihnen selbst) aufgerufen, wenn die Applikation pausiert werden soll. Das geschieht bspw. wenn ein Anruf am Handy ankommt. In diesem Fall sollten alle Ressourcen freigegeben, und keine weiteren Vorgänge ausgeführt werden. Anschließend hat die Anwendung den Status pausiert (zuvor zwingend aktiv).
destroyApp(boolean unconditional)
Nachdem diese Methode aufgerufen und ausgeführt wurde, wird das Midlet beendet. Es gilt also alle Ressourcen freizugeben und ggf. zu persistierende Dinge abzuspeichern. Falls der boolean unconditional
auf false
steht, dürfen Sie in dieser Methode eine MIDletStateChangeException
werfen. Dies signalisiert der aufrufenden Methode, dass das Midlet noch nicht beendet werden möchte, und man es doch zu einem späteren Zeitpunkt noch einmal versuchen möge. Steht der boolean
jedoch auf true
, so muss die Anwendung auf jeden Fall beendet werden. destroyApp(boolean unconditional)
kann sowohl aus dem pausierten, wie auch aus dem aktiven Status aufgerufen werden.
Nach oder als letzter Schritt des Aufrufs von destroyApp
, muss noch die Methode notifyDestroyed
aufgerufen werden. Diese informiert den Softwaremanager des Geräts, dass die Anwendung beendet wurde.
Um unser HelloWorldMidlet
zu vervollständigen, müssen wir auf noch weitere vier Klassen und ein Interface zugreifen.
javax.microedition.lcdui.Displayable
Die KlasseDisplayable
ist die Basisklasse für alle Klassen, die direkt auf dem Display des Handys dargestellt werden können. In diesem Kapitel werden wir nicht direkt auf sie zugreifen, sie wird jedoch einer Interface-Methode übergeben.javax.microedition.lcdui.Display
Diese Klasse ist die Schnittstelle zum Handydisplay. ÜberDisplay.getDisplay(MIDlet)
holen Sie sich die aktuelle Anzeige alsDisplay
-Variable. Dieser können Sie dann Klassen setzen, die anzeigbar sind. Sprich vonDisplayable
erben. Das überdisplay.setCurrent(Displayable disp)
gesetzte Objekt wird auf dem Handydisplay dargestellt.javax.microedition.lcdui.Form
EineForm
erbt vonDisplayable
und kann somit auf einem Display angezeigt werden. Ihr können bspw. Texte (form.append(String str)
) oder andere Komponenten zur Anzeige hinzugefügt werden.javax.microedition.lcdui.Command
MitCommands
können Menüpunkte auf einerDisplayable
-Klasse über den Befehldisplayable.addCommand(Command cmd)
hinzugefügt werden.javax.microedition.lcdui.CommandListener
Das InterfaceCommandListener
dient dazu, um auf die Betätigung einesCommands
durch den User zu reagieren. Er kann einerDisplayable
-Klasse über den Aufrufdisplayable.setCommandListener(CommandListener cmdL)
hinzugefügt werden.
Mit diesem Wissen sollte es für Sie keine Probleme darstellen, den vollständigen und kommentierten Quelltext zu verstehen:
package de.jbb.hello; import javax.microedition.lcdui.Command; import javax.microedition.lcdui.CommandListener; import javax.microedition.lcdui.Display; import javax.microedition.lcdui.Displayable; import javax.microedition.lcdui.Form; import javax.microedition.midlet.MIDlet; /** * @author Stefan Kiesel */ public class HelloWorldMidlet extends MIDlet implements CommandListener { // Flag, damit die Applikation nur ein einziges Mal initialisiert wird private boolean firstTime = true; // Das Display private Display disp; // Displayable Form zur Darstellung auf dem Bildschirm private Form helloView; // Command zum Beenden der Applikation private Command exit; public void startApp() { // Nur initialisieren, falls die Methode das erste Mal aufgerufen wurde if (firstTime) { // Display holen disp = Display.getDisplay(this); // Command mit folgenden Attributen erzeugen: // 1.) Anzeigetext = "Beenden" // 2.) "Kategorie", unter der dieser Command eingeordnet wird // 3.) Priorisierung, an welcher Position der Command angezeigt werden soll exit = new Command("Beenden", Command.EXIT, 1); // Erzeugung einer neuen Form mit dem Titel "My First JME App" helloView = new Form("My First JME App"); // Text "Hello Mobile World!" dem Form hinzufügen helloView.append("Hello Mobile World!"); // Exit-Command der Form hinzufügen helloView.addCommand(exit); // CommandListener setzen helloView.setCommandListener(this); // Auf false setzen, damit dieser Code nur einmalig ausgeführt wird firstTime = false; } // Als aktuelle Anzeige die Form "helloView" verwenden disp.setCurrent(helloView); } // Diese Methode wird vom Interface CommandListener vorgeschrieben und // jedesmal aufgerufen, wenn der User ein Command betätigt // Command c => Betätigtes Command // Displayable d => Displayable, auf der das Command liegt public void commandAction(Command c, Displayable d) { // Wenn auf das Command "exit" geklickt wurde, wird die Anwendung beendet if (c == exit) { destroyApp(false); } } public void destroyApp(boolean unconditional) { notifyDestroyed(); } // In diesem Fall nicht benötigt public void pauseApp() {} }
Sie können das Midlet nun bauen, indem Sie im Menü der Entwicklungsumgebung auf Run => Build Main Project (F11). Anschließend können Sie Ihr Programm im Emulator begutachten. Klicken Sie hierzu im Menü auf Run => Run Main Project (F6). Es öffnet sich ein Emulator, in dem Ihr Programm ausgeführt wird.
Um Ihr erstes Midlet auf Ihrem Handy zu starten, kopieren Sie die erzeugte JAR (und ggf. auch JAD) Datei auf Ihr Handy.
Eine JAD ist so etwas wie das Manifest, welches auch noch einmal direkt in Ihrer erzeugten JAR-Datei zu finden ist. Näheres finden Sie im nächsten Kapitel.
Sie finden diese Dateien in Ihrem Projektverzeichnis im Ordner dist (bspw. C:\Dokumente und Einstellungen\java-blog-buch\Eigene Dateien\JavaMESDKProjects\HelloMEWorld\dist) unter dem Namen HelloMEWorld.jar und HelloMEWorld.jad. Nachdem Sie die Daten auf Ihr Handy kopiert haben, können Sie sie gewöhnlich installieren und ausführen.
Tipps zur Java ME Programmierung
Bei der Entwicklung von Anwendungen für mobile Geräte ist es (aufgrund der begrenzten Ressourcen) notwendig, möglichst wenig Arbeitsspeicher und Prozessorleistung zu beanspruchen. Auch sollte Ihr Programm insgesamt (inkl. Klassen, Bildern, Sounds, …) nicht übermäßig groß werden. Sonst kann es passieren, dass viele Handys mit ihrem Programm (aufgrund der Größe) nicht umgehen können. Deshalb können Sie auch nicht davon ausgehen, dass eine Anwendung auf einem Gerät problemlos funktioniert, nur weil sie dies auf einem anderen Handy tut. Aber am Anfang werden Ihre Programme in der Regel ohnehin nicht wesentlich größer als 50KB sein. Mit einer solchen Größe werden die gängigsten Handys problemlos unterstützt. Es ist ohnehin ratsam (vor allem bei der professionellen Entwicklung mit Java ME) Ihre Anwendung in mehreren Versionen (für unterschiedliche Auflösungen und auf Feinheiten einzelner Endgeräte/Endgerätegruppen abgestimmt) zu veröffentlichen. Optimal wäre es, wenn Sie bereits zuvor Erfahrungen in der Programmierung mit Java machen konnten. Dies wird in den nachfolgenden Kapiteln auch vorausgesetzt, welche sich zuerst einmal mit der Theorie der Java ME Entwicklung befassen werden.