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

Similar documents