J2ME Polish
J2ME Polish 2.4 Documentation
Enough Software

Cooking Tips and How-tos

Building How-Tos

How to Use Several Source Folders

You can use several source folders by defining the "source"-attribute of the <build> element in the "build.xml" file. Just separate the folders with colons or semicolons:

<build
	fullscreen="menu"
	usePolishGui="true"
	sourceDir="source/src:../extensions/source/src"
>

In the above example the "source/src" folder of the current project and the "source/src" folder of the "extensions" project are included. The notation is OS-independent by the way. So you can separate different source-paths with either a colon ':' or a semicolon ';' and you can separate folders with a slash '/' or a backslash '\'.

You can also use the nested <sources> element for including source-directories based on conditions. In this example the directory "source/test" is only included when the Ant-property "test" is true:

<build
	fullscreen="menu"
	usePolishGui="true"
>
	<sources>
		<source dir="source/src" />
		<source dir="source/test" if="test" />
	</sources>
...

How to Integrate Third Party APIs

Sometimes a third party API is needed in a project. You have to distinguish between APIs which are available as source code, and APIs which are available in binary-only form. Another case are APIs which are already pre-installed on specific devices. Depending on the type of the API different actions are required for integrating the API. Please do not forget to add the library to the classpath of your project within your IDE. This is, however, out of the scope of this how-to.

How to Integrate a Source Code Third Party API

When a third party API is available in source code, you can integrate it by modifying the "sourceDir" attribute of the <build> element in the "build.xml" file. Consider the case where your normal application code is placed in the "source/src" directory and the source code of the third party API in the "source/thirdparty" folder. You can now add the third party API by setting the "sourcDir" attribute to "source/src:source/thirdparty":

<build
	imageLoadStrategy="background"
	fullscreen="menu"
	usePolishGui="true"
	resDir="resources2"
	sourceDir="source/src:source/thirdparty"
>

The notation is OS-independent by the way. So you can separate different source-paths with either a colon ':' or a semicolon ';' and you can separate folders with a slash '/' or a backslash '\'.

How to Integrate a Binary Third Party API

When a third party API is only available in binary form, they can be integrated with the "binaryLibraries" attribute of the <build> element in the "build.xml" file. This attribute can point to jar- or zip-files or to a directory containing third party libraries (either jar-files, zip-files or class-files). Several libraries can be separated by colons ':' or semicolons ';'. When the libraries are situated in the "import" folder, only the name of the libraries need to be given (instead of specifying the full path).

In the following example the binary library "tinyline" is integrated. The corresponding library file "tinylinegzip.zip" is situated in the "import" folder:

<build
	imageLoadStrategy="background"
	fullscreen="menu"
	usePolishGui="true"
	resDir="resources2"
	binaryLibraries="tinylinegzip.zip"
>

In this example all libraries which are situated in the "thirdparty" folder are integrated:

<build
	imageLoadStrategy="background"
	fullscreen="menu"
	usePolishGui="true"
	resDir="resources2"
	binaryLibraries="thirdparty"
>

The notation is OS-independent by the way. So you can separate different source-paths with either a colon ':' or a semicolon ';' and you can separate folders with a slash '/' or a backslash '\'.

How to Integrate a Device API

Many devices provide additional APIs, which are pre-installed on the devices. A popular example is Nokia's UI-API which provides additional graphic and sound functions. When a device supports a specific API, this is noted with the "JavaPackage" capability of that device in the "devices.xml" file (this file is visible only when you have chosen to install the "external device database" during the installation of J2ME Polish).

Assuming that you want to use API "phonebook", the corresponding library file "phonebook.jar" or "phonebook.zip" just needs to be copied into the "import" folder (in the J2ME Polish installation directory or in your project root directory). It will then be used automatically for the devices which support the "phonebook" API.

You can modify the "apis.xml" file (this is again only visible when you have chosen to install the "external device database") for specifying different library-names, paths or aliases.

How to Use Several Obfuscators Combined

You can combine several obfuscators just by adding several <obfuscator> elements to your "build.xml" file. Please note that combining RetroGuard and ProGuard actually results in bigger classes than when ProGuard is used alone.

Here you can find more information about integrating other obfuscators.

How to Minimize the Memory Footprint

There are several possibilities for minimizing the memory-footprint of J2ME Polish:

polish.skipArgumentCheck and polish.debugVerbose

Define the preprocessing-symbol "polish.skipArgumentCheck", by setting the "symbols" attribute of the <build>-element in the "build.xml" file. When this symbol is defined, no method-arguments will be checked by the J2ME Polish GUI. This is usually fine when the application is stable. You should also skip the checking of arguments in the application by testing the "polish.skipArgumentCheck"-symbol in the application code:

public void doSomething( int index ) {
  //#ifndef polish.skipArgumentCheck
	// check the argument only when the "polish.skipArgumentCheck" is not defined:
	if (index < 0 || index > this.maxIndex ) {
	  //#ifdef polish.debugVerbose
		throw new IllegalArgumentException("Invalid index [" + index "].");
	  //#else
		//# throw new IllegalArgumentException();
	  //#endif
	}
  //#endif
}

The above example also uses the "polish.debugVerbose" symbol for determining if a meaningful exception should be thrown. By giving verbose information only in cases when it is requested, some memory can be saved, too. You can set and unset the "polish.debugVerbose" symbol by modifying the "verbose" attribute of the <debug>-element.

Image Load Strategy

When you use the J2ME Polish GUI, select the "foreground" image loading strategy for removing the overhead of loading images in a background thread. The "imageLoadStrategy" attribute of the <build> element can either be "foreground" or "background".

Optimizing the "polish.css" File

When you use the J2ME Polish GUI, you should not use default-values in your "resources/polish.css" file. Forms and Lists do not use a table layout by default, for example. In that case you should not set the "columns"-attribute to "1", since this is the default behavior anyhow. It is better not to use the "columns" attribute at all in this case.

Another optimization is to define often used backgrounds, fonts and borders in the appropriate section of the "resources/polish.css" file. In that case you can just refer to the instances:

backgrounds {
	myBackground {
		type: round-rect;
		color: gray;
		arc: 15;
		border-color: black;
		border-width: 2;
	}
}
title {
	background: myBackground;
	/** skipping other attributes **/
}
focused {
	background: myBackground;
	/** skipping other attributes **/
}

A third optimization is not to use dynamic styles. This requires the usage of the #style-directive in the application code.

Using Optimal Resources

Use the resource assembling of J2ME Polish for using only those resources which are actually required by the application. For example it does not make sense to add MIDI-soundfiles for devices which do not support such files. Better put them into the "resources/midi" folder.

It is also not good to use high-color images for handsets which do not support such images. Better create optimized versions of such images. This saves memory and has the additional bonus that you do not need to depend on the dithering of the device, which often results into awkward graphics. So put 4096-colors images into the "resources/BitsPerImage.12" folder and 65k-colors images into the "resources/BitsPerImage.16+" folder.

When you use the J2ME Polish GUI you can also use device-optimized designs.

Use Preprocessing

With preprocessing you can make amazing adjustments to specific devices without wasting memory and without losing the portability of an application.

Consider for example this "SplashScreen" solution, which shows a startup logo. This screen should be derived from Nokia's FullScreenCanvas when this class is available. In a classic solution you would need to test if Nokia's API is available and to load a Nokia-specific version of the SplashScreen class:

public class MyMidlet extends MIDlet {
	[...]
	public void showSplashScreen() {
		Displayable splashScreen;
		try {
			// check if this is a Nokia-device:
			splashScreen = Class.forName("MyNokiaSplashScreen").newInstance();
		} catch (Exception e) {
			// no Nokia API is available, load the classic splash screen:
			splashScreen = new MySplashScreen();
		}
		this.display.set( screen );
	}
}

public class MySplashScreen extends Canvas {
	public void paint( Graphics g) {
		[...]
	}
}

public class MyNokiaSplashScreen extends com.nokia.mid.ui.FullCanvas {
	public void paint( Graphics g) {
		[...]
	}
}

With the preprocessing capabilities and the integrated device database of J2ME Polish there is an easier and much more memory efficient solution available:

public class MySplashScreen 
//#if polish.api.nokia-ui
	extends com.nokia.mid.ui.FullCanvas
//#else
	//# extends Canvas
//#endif
{
	public void paint( Graphics g) {
		[...]
	}
}

Another example is the playback of sound. In a classical environment you would need to check the supported formats at runtime and then decide which one should be used. Using preprocessing and the device database this is much easier and no checks during the runtime are necessary:

public void playMusic() {
	Player player;
	//#if polish.audio.mpeg
		player = Manager.createPlayer( Class.getResourceAsStream("title.mp3"), "audio/mpeg" );
		player.start();
	//#elif polish.audio.amr
		player = Manager.createPlayer( Class.getResourceAsStream("title.amr"), "audio/amr" );
		player.start();
	//#elif polish.audio.wav
		player = Manager.createPlayer( Class.getResourceAsStream("title.wav"), "audio/wav" );
		player.start();
	//#elif polish.audio.midi
		player = Manager.createPlayer( Class.getResourceAsStream("title.midi"), "audio/midi" );
		player.start();
	//#else
		//# return;
	//#endif
}

With the help of preprocessing you can shift the runtime checks to the compile phase.

Remove Debug Code

When the application should be shipped any debug code should be removed from the project. The easiest way is to use the #debug and #mdebug preprocessing directives. The debugging can then be controlled with the <debug>-element in the "build.xml" file.

General Optimization Tips

Some other useful tips for minimizing the memory footprint of an application are also available:

Do not use pure Object Orientated Programming. OOP is great, but it has some drawbacks, notably the runtime and memory implications. Try to minimize the usage of classes and interfaces. Try to use preprocessing whenever it makes sense. Check if you really need methods for accessing variables. Sometimes it is better is better to declare them protected or even public and to access them directly.

If you have text which is displayed only seldom, consider to move them into a properties file.

How to Sign MIDlets with J2ME Polish

Signing MIDlets can be automated using the <java>-subelement of the <build>-element.

IMPORTANT: please note that you cannot use normal code signing certificates on most devices, since the required root certificates are missing. Your best bet to sign an application is with the (commercial) help of the Java Verified initiative.
On some devices you can import your own certificates.
Another option is to let your application certify by a vendor or a carrier.

Keys can be generated using the Java-keytool, e.g.:

> keytool -genkey -alias SignMIDlet -keystore midlets.ks -keyalg RSA

For testing purposes no certificate needs to be purchased and imported. Such MIDlets cannot be installed on real devices, however.

When an appropriate certificate was purchased and imported into the keystore named "midlets.ks" with the key "SignMIDlet", the following two -elements need to be added to the -element:

<java jar="${wtk.home}/bin/JadTool.jar" 
      	fork="true" 
      	failonerror="true" 
    	if="polish.midp2" 
	unless="test"
	message="Adding signature for device ${polish.identifier}"
	>
	<arg line="-addjarsig"/>
	<arg line="-keypass ${password}"/>
	<arg line="-alias SignMIDlet"/>
	<arg line="-keystore midlets.ks"/>
	<arg line="-inputjad dist/${polish.jadName}"/>
	<arg line="-outputjad dist/${polish.jadName}"/>
	<arg line="-jarfile dist/${polish.jarName}"/>
</java>	
<java jar="${wtk.home}/bin/JadTool.jar" 
	fork="true" 
	failonerror="true" 
	if="polish.midp2" 
	unless="test"
	message="Adding certificate for device ${polish.identifier}"
	>
	<arg line="-addcert"/>
	<arg line="-alias SignMIDlet"/>
	<arg line="-keystore midlets.ks"/>
	<arg line="-inputjad dist/${polish.jadName}"/>
	<arg line="-outputjad dist/${polish.jadName}"/>
</java>	

In the above example the signing is skipped when the test-mode is active or when the current device does not support the MIDP/2.0 standard. It is assumed that the "midlets.ks" keystore is situated in the same directory as the "build.xml" file.

Please note that the password needs to be specified as a property. This can be done within the "build.xml" file or alternatively (for the more security conscious folks) on the command-line with the -Dpassword=[value] option:

> ant -Dpassword=secret

In Mac OS X Wireless Toolkit the "JadTool.jar" is not available. It can be installed together with J2ME Polish. In that case the path to the JadTool needs to be changed to "${polish.home}/bin/JadTool.jar" in the above example.

GUI How-Tos

How to Use Tables

A table can be used for any any Form, List or ChoiceGroup. The table is activated by setting the "columns" attribute and optionally the "columns-width" attribute in the "resources/polish.css" file:

form {
	padding: 5;
	background-color: yellow;
	columns: 2;
	columns-width: 40, 100;
}

In the above example the dynamic style "form" is used for designing all Form screens. Form elements will be added from left to right and from top to bottom of the table. The left column will be 40 pixels wide, whereas the right column will use 100 pixels.

How to Apply the J2ME Polish GUI for Existing Applications

If an existing application should be "polished up" you should insert #style preprocessing directives within the application to allow a fine grained design:

//#style mainScreen
List mainScreen = new List( "Main Menu", List.IMPLICIT );

//#style mainScreenItem
mainScreen.append( "Start Game", null );

You need to use static styles then in the "polish.css" file. Static styles can have almost any alphanumerical name and need to start with a dot:

.mainScreen {
	padding: 5;
	background-color: yellow;
	columns: 2;
	columns-width: 40, 100;
}
.mainScreenItem {
	background-color: black;
	font-color: white;
	icon-image: url( main%INDEX%.png );
}

In the last step you should adjust your designs for different handsets. If you want to make adjustments for the Sony-Ericsson P900 for example, you need to create the file "resources/Sony-Ericsson/P900/polish.css". In this file you can change any settings which you have done in the basic "resources/polish.css" file. Remember that you only need to specify attributes which are different, this makes subsequent changes easier.

How to Apply Different Designs to One Application

You can alter the appearance of an application easily by using different resources like images, sound files and design-definitions. You can use one application source code for creating several different applications with this technique. The "dir"-attribute of the <resources> element in the "build.xml" file defaults to the "resources" folder, but you can change this to any other folder. Alternatively you can also set the "resDir"-attribute of the <build> element, when no <resources> element is used.

Best practice is to create one Ant-<target> for each end-application in the "build.xml" file. In each target the <j2mepolish> task is copied and changes are made to the "dir"-attribute of the <resources> element and to the "workDir"-attributes of the <build> element:

<target name="girlgame" >
	<j2mepolish>
		<info
		 jarName="${polish.vendor}-${polish.name}-girl.jar" 
		[...] />
		<deviceRequirements > [...]
		<build
		 workDir="build/girl"
		 [...]
			<resources
		 		dir="resources/girl"
			/>
		 >
		[...] 
		</build>
	</j2mepolish>
</target>
<target name="boygame" >
	<j2mepolish>
		<info
		 jarName="${polish.vendor}-${polish.name}-boy.jar" 
		[...] />
		<deviceRequirements > [...]
		<build
		 resDir="resources/boy"
		 workDir="build/boy"
		 [...]
		 >
		<resources
			dir="resources/boy"
		/>
		[...] 
		<variable name="player-width" value="12" >
		<variable name="player-height" value="12" >
		</build>
	</j2mepolish>
</target>

You can even define or alter <variables> to make further adjustments with the help of preprocessing. You could define sprite-dimensions for example each or some of the <j2mepolish> tasks:

<variable name="player-width" value="12" >
<variable name="player-height" value="12" >

These variables then can be used within the application with the use of preprocessing:

//#ifdef player-width:defined
	//#= int width = ${player-width};
//#else
	int width = 10;
//#endif
//#ifdef player-height:defined
	//#= int height = ${player-height};
//#else
	int height = 10;
//#endif
Sprite player = new Sprite( playerImage, width, height );

How to Change the Labels of Standard-Commands and Menu-Labels

The labels of the standard menu-commands can be changed by setting variables either in the build.xml file or within the localization-messages.txt file.

This example changes the "Cancel" command to "Abbruch" (German for cancel):

<variables>
	<variable name="polish.command.cancel" value="Abbruch"/>
</variables>

Please refer to the localization documentation for more information.

How to Enable or Disable the Usage of the GUI for a Specific Device

2ME Polish's GUI is deactivated by default for some older devices like the first version of Nokia Series 40 models.

You can override this behavior by setting the "supportsPolishGui"-attribute of the device in question in the "devices.xml" file, which is located in installation folder of J2ME Polish. When the file is missing, re-run the installation and choose to install the "external device database" as well.

Open devices.xml and search the device in question. Now set the "supportsPolishGui"-attribute: It needs to be true, when the device should support J2ME Polish's GUI.

<device
	supportsPolishGui="false" >
	<identifier>Nokia/Series40</identifier>
	<!-- and so on -->
</device>

You can also override the settings in the device-database by setting the "usePolishGui"-attribute of the <build> element to "always". In that case the GUI will be used for all devices, regardless of the settings in the device database.

Trouble Shooting

Using Subfolders for Resources

Subfolders for resources are not supported for two simple reasons:

  1. They are unnecessary and waste space in the application JAR.
  2. The automatic resource assembling of J2ME Polish is based on using subfolders.

Compile Error

If you have a compile error within the J2ME Polish package or a compile error which seems to be erroneous, please try a clean build: remove the "build" folder or call the "ant clean" before building again.

Preverify Error

If you have a preverify error, please try a clean build: remove the "build" folder or call the "ant clean" before building again.

back to top