index of game jar jad
Transcription
index of game jar jad
Titelthema To see or not to see Mobile Anwendungen mit J2ME Polish Thomas Kraft GUI-APIs für die Java 2 Microediton gibt es einige, J2ME Polish sticht aus der Masse durch ein integriertes Build-Konzept nebst Gerätedatenbank und der Möglichkeit, Standard-J2ME-Anwendungen mittels CSS zu entwerfen, heraus. Stand der Dinge Der J2ME-Standard bietet eine komfortable und seit der MIDP/2.0-Version auch mächtige Unterstützung bei der Programmierung von Benutzeroberflächen mit Form, CustomItem und Co. Diese so genannte Highlevel-GUI hat allerdings entscheidende Nachteile: Die Darstellung ist vom Gerätehersteller abhängig, kann – mit Ausnahme des CustomItems auf MIDP/2.0-Handys – nicht beeinflusst werden und variiert von Gerät zu Gerät. Der Lösungsansatz Und los! J2ME Polish führt eine Wrapper-API ein, die sich zwischen Anwendung und Geräte-API einfügt und weitgehende Design-Möglichkeiten bietet. Hintergründe, Ränder, Fonts und so weiter können gesetzt und Menüs können animiert werden. Aus Sicht der Anwendung kann die komplette Highlevel-GUI-API von MIDP/2.0 genutzt werden, übrigens auch auf MIDP/1.0-Handys, die so in den Genuss von CustomItems, POPUP-ChoiceGroups und so weiter kommen. Diese Wrapper-API wird durch den Build-Prozess von J2ME Polish in die Anwendung eingewoben und dabei automatisch für das jeweilige Zielgerät optimiert. Typische Optimierungen umfassen die Umgehung von Fehlern und Besonderheiten eines Zielgeräts, aber auch die Ausnutzung von spezifischen APIs des Zielgeräts. So kann beispielsweise der Fullscreen-Modus nicht nur auf MIDP/2.0-, sondern auch auf MIDP/1.0-Handys mit Nokias UI-API aktiviert werden. Der Build-Prozess basiert auf Ant und kann daher in jede Entwicklungsumgebung eingebunden werden oder auch von der Kommandozeile genutzt werden. J2ME Polish bietet hier sehr umfangreiche Möglichkeiten, deren Vorstellung den Rahmen dieses Artikels sprengen würde. An dieser Stelle sei daher nur gesagt, dass alle typischen Anforderungen wie Builds für mehrere Zielgeräte, Lokalisierung der Anwendung oder das automatische Auswählen von geeigneten Bildern und anderen Ressourcen beherrscht werden. Das Design der Anwendung wird über eine oder mehrere Text-Dateien bestimmt, die sich außerhalb des Programmcodes befinden. Als Design-Sprache wird eine stark am Webstandard angelehnte CSS-Variante genutzt, die auf die Besonderheiten der Java-Handys eingeht. Durch die Unabhängigkeit der Design-Einstellungen vom eigentlichen Programm können auch leicht verschiedene Designs einer Anwendung erstellt werden, ohne dass der Programmcode geändert werden muss. Genug der theoretischen Möglichkeiten, jetzt wird Hand angelegt. Wenn noch kein Wireless Toolkit vorhanden ist, laden wir es von http://java.sun.com/j2me und installieren es nach ${wtk. home}, das ein beliebiger Ort auf unserem System ist. Den Nokia-Emulator für Series 60-Geräte holen wir von http://forum. nokia.com und installieren ihn nach ${nokia.home}. Nun folgt J2ME Polish, das wir von http://www.j2mepolish.org runterladen. Wir installieren es nach ${polish.home}. Nun legen wir in unserer Lieblingsentwicklungsumgebung ein neues Projekt an und erweitern den Classpath des Projekts um die MIDP/2.0 API, die sich in ${polish.home}/import/midp2.jar findet. Listing 1 zeigt ein einfaches Programm, das ein Auswahl-Menü mittels einer impliziten List erstellt und anzeigt. Das geben wir nun in unserem Projekt als com.company.j2me.MenuMidlet ein, dabei wird die Nutzung des Ordners source/src für die Quelldateien empfohlen. Später lässt sich das Projekt dann zum Beispiel leichter um Testklassen erweitern, die dann in source/test abgelegt werden können. Der Code von Listing 1 sollte keine unüberwindliche Hürde für den Leser darstellen. Wie bauen wir jetzt das Programm? Listing 2 zeigt das Build-Skript für Ant, mit dem wir unsere Anwendung erstellen und das wir jetzt im Projekt-Verzeichnis als build. xml eingeben. Bitte passen Sie dazu die Ant-Properties wtk.home, nokia.home und polish.home Ihrem System entsprechend an. In Listing 2 definieren wir zunächst den <j2mepolish>-Task, damit wir ihn im einzigen Ant-Target nutzen können. Der Task selbst ist unterteilt in die vier Bereiche <info>, <deviceRequirements>, <build> und <emulator>. Im <info>-Bereich definieren wir einige grundsätzliche Eigenschaften unserer Anwendung, die indirekt die JAD- und MANIFEST-Attribute beeinflussen. Interessant ist die Nutzung der Properties ${polish.vendor} und ${polish.name} im jarName-Attribut, ohne dass diese Attribute irgendwo definiert sind. J2ME Polish setzt diese Properties während des Builds für jedes Zielgerät: aus ${polish.vendor} wird der Name des Handy-Herstellers und 10 JavaSPEKTRUM 2/2005 package com.company.j2me; Titelthema import javax.microedition.lcdui.*; import javax.microedition.midlet.MIDlet; import javax.microedition.midlet.MIDletStateChangeException; public class MenuMidlet extends MIDlet implements CommandListener { private final List mainScreen; private final Command startCommand; private final Command quitCommand; public MenuMidlet() { super(); this.mainScreen = new List("Synyx", List.IMPLICIT); this.mainScreen.append("Start game", null); this.mainScreen.append("Load game", null); this.mainScreen.append("Highscore", null); this.mainScreen.append("Quit", null); this.startCommand = new Command("Start", Command.SCREEN, 1); this.quitCommand = new Command("Exit", Command.SCREEN, 2); this.mainScreen.addCommand( this.startCommand ); this.mainScreen.addCommand( this.quitCommand ); this.mainScreen.setCommandListener(this); } protected void startApp() throws MIDletStateChangeException { Display.getDisplay(this).setCurrent( this.mainScreen ); } protected void pauseApp() { // ignore } protected void destroyApp(boolean unconditional) throws MIDletStateChangeException { // just quit } public void commandAction(Command cmd, Displayable screen){ if (cmd == List.SELECT_COMMAND) { int selectedItem = this.mainScreen.getSelectedIndex(); switch (selectedItem) { case 0: startGame(); break; case 1: loadGame(); break; case 2: showHighscore(); break; default: notifyDestroyed(); } } else if (cmd == this.startCommand) { startGame(); } else if (cmd == this.quitCommand) { notifyDestroyed(); } } <project name="enough-j2mepolish-example" default="j2mepolish"> <property name="wtk.home" value="C:\WTK2.2" /> <property name="nokia.home" value="C:\Nokia" /> <property name="polish.home" value="C:\Programme\J2ME-Polish" /> <taskdef name="j2mepolish" classname="de.enough.polish.ant.PolishTask" classpath="${polish.home}/import/enough-j2mepolish-build.jar:${polish. home}/import/jdom.jar:${polish.home}/import/proguard.jar" /> <target name="j2mepolish" > <j2mepolish> <info license="GPL" name="Menu App" version="1.2.3" description="Ein einfaches Menü" vendorName="Company GmbH" icon="icon.png" jarName="${polish.vendor}-${polish.name}-menu.jar" /> <deviceRequirements> <requirement name="Identifier" value= "Nokia/Series60, Nokia/Series60Midp2, Generic/midp2, Generic/midp1" /> </deviceRequirements> <build usePolishGui="false"> <midlet name="Example" class="com.company.j2me.MenuMidlet" /> <obfuscator name="ProGuard" /> </build> <emulator /> </j2mepolish> </target> </project> Listing 2: Das Build-Skript baut die Anwendung Der <build>-Bereich steuert den eigentlichen Build-Vorgang. Im Minimal-Fall genügt die Bekanntgabe der MIDlet-Klasse durch das <midlet>-Attribut, in unserem Fall binden wir außerdem den ProGuard Obfuscator ein, der die Anwendung nach dem Kompilieren wesentlich verkleinert. Zudem deak- private void showHighscore() { System.out.println("show highscore"); } private void loadGame() { System.out.println("load game"); } private void startGame() { System.out.println("start game"); } } Listing 1: Wir bauen uns ein Hauptmenü aus ${polish.name} der Name des Handys. Wenn wir also mit Listing 2 eine Anwendung für das Siemens SX1 erstellen, wird die erstellte JAR-Datei Siemens-SX1-menu.jar heißen. Der <deviceRequirements>-Abschnitt bestimmt, für welche Geräte die Anwendung gebaut wird. In Listing 2 zählen wir einfach die Zielgeräte auf, alternativ kann man auch die gewünschten Fähigkeiten der Zielgeräte nennen, wie beispielsweise „Muss den MIDP/2.0-Standard und die WMAPI unterstützen“. http://www.javaspektrum.de Abb. 1: Die Anwendung im nativen Design 11 Titelthema tivieren wir zunächst die J2ME Polish GUI durch Setzen von usePolishGui=“false“. Schließlich sorgt der <emulator>-Abschnitt für den Start des Emulators für jede erstellte Anwendung. Wenn wir das Skript nun in unserer Entwicklungsumgebung ausführen, indem wir die build.xml-Datei rechtsklicken und dann je nach Entwicklungsumgebung „Run Ant“, „Execute“ oder ähnliches bestimmen, werden die entsprechenden Emulatoren gestartet. Der Nokia-Emulator zeigt dann die Anwendung wie in Abbildung 1. Die Anwendungen werden übrigens im dist-Ordner gespeichert. package com.company.j2me; import javax.microedition.lcdui.*; import javax.microedition.midlet.MIDlet; import javax.microedition.midlet.MIDletStateChangeException; public class MenuMidlet extends MIDlet implements CommandListener { private final List mainScreen; private final Command startCommand; private final Command quitCommand; Das Design public MenuMidlet() { super(); //#style mainScreen this.mainScreen = new List("Synyx", List.IMPLICIT); //#style mainScreenItem this.mainScreen.append("Start game", null); //#style mainScreenItem this.mainScreen.append("Load game", null); //#style mainScreenItem this.mainScreen.append("Highscore", null); //#style mainScreenItem this.mainScreen.append("Quit", null); this.startCommand = new Command("Start", Command.SCREEN, 1); this.quitCommand = new Command("Exit", Command.SCREEN, 2); this.mainScreen.addCommand( this.startCommand ); this.mainScreen.addCommand( this.quitCommand ); this.mainScreen.setCommandListener(this); } Auch wenn die hersteller-spezifische Darstellung im Falle Nokias als durchaus funktionell gelten kann, so ist sie doch kaum als Verkaufsargument geeignet – weder für Spiele noch für Business-Anwendungen. Um die J2ME Polish GUI zu nutzen, müssen wir einige Änderungen an der build.xml und dem Programm vornehmen. Außerdem müssen wir das Design in einer polish.css-Datei festlegen. Zunächst aktivieren wir daher die GUI, indem wir das usePolishGui-Attribut des <build>-Elements auf true setzen. Außerdem aktivieren wir den fullscreen-Modus und teilen J2ME Polish gleichzeitig mit, dass wir Commands einsetzen, indem wir das fullscreen-Attribut auf menu setzen: <build usePolishGui=“true“ fullscreen=“menu“ > protected void startApp() throws MIDletStateChangeException { Display.getDisplay(this).setCurrent( this.mainScreen ); } Nun setzen wir im Quelltext vor jedem GUI-Element eine #style-Preprocessing-Direktive, sodass wir das Listing 3 erhalten. Damit weisen wir dem darauf folgenden Element den in der #style-Direktiven benannten CSS-Stil zu. Andere Änderungen am Programm sind nicht notwendig. Die CSS-Stile müssen wir nun in der Datei resources/polish.css definieren. Listing 4 zeigt ein mögliches Design. Zuerst definieren wir in dem colors-Abschnitt alle Farben, die wir in den einzelnen Stilen einsetzen. Obwohl dieser Abschnitt nicht unbedingt vorhanden sein muss, erleichtert er spätere Anpassungen sehr. Dem colors-Abschnitt schließen sich die Definitionen der verschiedenen Stile an. Jeder Stil bestimmt das Design eines oder mehrere GUI-Elemente. Unabhängig von dem jeweiligen Element können Hintergründe (background), Ränder (border), die Anordnung des Elements (layout) sowie Abstände (margin und padding) zu anderen Elementen definiert werden. Die allermeisten GUI-Elemente unterstützen zudem Schrift-Einstellungen (font). Je nach GUI-Element können zudem zusätzliche Einstellungen vorgenommen werden. Der erste Stil ist .mainScreen, mit dem die Liste angepasst wird. Im Wesentlichen setzen wir hier eine Hintergrund-Farbe und protected void pauseApp() { // ignore } protected void destroyApp(boolean unconditional) throws MIDletStateChangeException { // just quit } public void commandAction(Command cmd, Displayable screen){ if (cmd == List.SELECT_COMMAND) { int selectedItem = this.mainScreen.getSelectedIndex(); switch (selectedItem) { case 0: startGame(); break; case 1: loadGame(); break; case 2: showHighscore(); break; default: notifyDestroyed(); } } else if (cmd == this.startCommand) { startGame(); } else if (cmd == this.quitCommand) { notifyDestroyed(); } } Alternativen private void showHighscore() { System.out.println("show highscore"); } kAWT: Personal Java und J2ME GUI, GPL (GNU General Public License) und kommerziell, kawt.de Synclast UI API: J2ME GUI, GPL und kommerziell, private void loadGame() { System.out.println("load game"); } www.synclast.com/ui_api.jsp JTGL: Java und J2ME GUI, LGPL (GNU Lesser General Public License) und kommerziell, www.jtgl.org antenna: Build-Tool für J2ME, LGPL, antenna.sourceforge.net private void startGame() { System.out.println("start game"); } } Listing 3: Stile werden mit der #style-Direktiven festgelegt 12 JavaSPEKTRUM 2/2005 Titelthema colors { pink: rgb(248,39,186); darkpink: rgb(185,26,138); lightgray: #C9C9C9; } menubar-color: darkpink; font-color: white; font-style: bold; } .mainScreen { padding: 5; padding-left: 15; padding-right: 15; background { type: pulsating; start-color: white; end-color: pink; steps: 30; repeat: false; back-and-forth: false; } layout: horizontal-expand | horizontal-center | vertical-center; } Listing 4: Design der Anwendung in polsih.css legen mit dem columns-Attribut fest, dass die Listenelemente in zwei Spalten aufgereiht werden sollen. Der .mainScreenItem-Stil sorgt für das Erscheinungsbild der Listenelemente. Solchen Elementen können wir mit dem iconimage-Attribut auch Bilder zuweisen: icon-image: url( item%INDEX%.png ); Dabei wird der eingesetzte %IMAGE%-Wert automatisch auf die Position des Elements umgerechnet, das erste Element erhält das Bild item0.png, das zweite item1.png und so weiter. Es folgen die Standard-Stile title, focused und menu. Diese Stile müssen nicht explizit zugewiesen werden und sind für die Darstellung des Titels, des gegenwärtig selektierten Elements und der Menü-Bar zuständig. Wenn wir nun wieder J2ME Polish starten, erhalten wir ein völlig anderes Erscheinungsbild derselben Anwendung wie Abbildung 2 zeigt. Dadurch, dass wir die Anwendung außerhalb des Programmcodes designen können, lassen sich schnell Änderungen vornehmen, wie die Abbildungen 3 und 4 demonstrieren. In Abbildung 4 sehen wir außerdem die Nutzung eines BitmapFonts. Normalerweise sind die Fonts unter J2ME auf System, Proportional und Monospace beschränkt, oft sind alle Schriftarten sogar identisch. J2ME Polish enthält einen Editor, mit dem aus beliebigen True Type Fonts Bitmap-Fonts erstellt werden können. Diese können wiederum über das CSS-Attribut font-bitmap in den Stilen benutzt werden. .mainScreenItem { margin: 2; padding: 3; padding-left: 10; padding-right: 5; padding-horizontal: 10; background: none; font-color: white; font-style: bold; font-size: small; layout: left; icon-image: url( item%INDEX%.png ); icon-image-align: left; } title { padding: 2; margin-top: 0; margin-bottom: 5; margin-left: 0; margin-right: 0; font-face: proportional; font-size: large; font-style: bold; font-color: white; background-color: darkpink; border: none; layout: horizontal-center | horizontal-expand; Steckbrief von J2ME Polish } focused { padding: 3; padding-left: 10; padding-right: 5; padding-horizontal: 10; background-type: round-rect; background-arc: 8; background-color: pink; border { type: round-rect; arc: 8; color: yellow; width: 2; } font { style: bold; color: black; size: small; } layout: expand | left; after: url(dot.png); } menu { margin-left: 2; padding: 2; 14 Editionen: GPL (für Opensource-Produkte), Einzellizenz (199,- gültig für eine J2ME-Anwendung), Laufzeitlizenz (199,- gültig für beliebig viele Anwendungen, aber insgesamt max. 100 Anwendungs-Installationen), Enterprise-Lizenz (2990,- gültig für beliebig viele J2ME-Anwendungen). Zusätzlich muss für jeden Entwickler ein „Developer Seat“ für 99,- erworben werden. Betriebssysteme: Windows, Linux, OS X Voraussetzungen: Java Wireless Toolkit, Ant Build-Prozess: Preprocessing, Device-Optimierung, Geräte-Datenbank, Compile, Preverify, Obfuscation, Jar und Jad GUI: Design per CSS, gezielte Einbindung von Ressourcen für bestimmte Geräte oder Geräte-Gruppen, 100 % kompatibel zum MIDP-Standard Game-Engine: macht die MIDP/2.0 Game-API für MIDP/1.0-Geräte nutzbar Lokalisierung: Eine Anwendung kann leicht für beliebig viele Sprachen erstellt werden JavaSPEKTRUM 2/2005 Titelthema Abb. 2: Die aufpolierte Darstellung Abb. 3: Ein Design mit Bitmap-Fonts Abb. 4: Ein Alternativ-Design Fazit Mit J2ME Polish lassen sich schnell und leicht professionelle Benutzeroberflächen erstellen, ohne dass dabei Änderungen am Quellcode des Programms notwendig werden. Durch die Kompatibilität zum MIDP-Standard können auch bestehende Anwendungen schnell designed und angepasst werden. Durch Anlehnung an den CSS-Standard können Webdesigner J2MEAnwendungen anpassen, ohne dabei auf den Entwickler angewiesen zu sein. Dieser Komfort hat natürlich einen Preis, der in der Form von größer gewordenen Anwendungen daherkommt, in unserem Fall immerhin etwa 20 KB ohne die Grafiken. Auch mag der eigene Build-Prozess zunächst etwas befremdlich wirken, aber dieser macht J2ME Polish erst so mächtig und flexibel. Ant-Nutzer werden sich auf Anhieb zurecht finden, während sich andere Entwickler erst einmal an die vielen Möglichkeiten gewöhnen müssen. http://www.javaspektrum.de Thomas Kraft ist Gesellschafter und Mitbegründer der Firma Synyx oHG in Karlsruhe, die sich auf Entwicklungen im Java-Bereich spezialisiert hat. Thomas Kraft entwickelt seit 1999 im OpensourceBereich und hat sich damit im Januar 2002 mit ehemaligen Mitstudenten selbstständig gemacht. E-Mail: thomas.kraft@synyx.de. Weitere Informationsquellen und Online-Ressourcen http://www.j2mepolish.org http://www.sigs-datacom.de/sd/publications/ js/2005/02/index.htm 15