Archive for March, 2007|Monthly archive page

Localized resource building with JSR 238: a simple custom ant task example

For today’s programming adventure, let’s tackle resource building!!!

Creating a series of jar files containing different sets of specialized resources is one of the basic reasons for setting up a build process with a tool such as Ant rather than just building with ktoolbar (as I discussed the other day). To put this in concrete terms, let’s look at a practical example that illustrates both how to write a simple Ant task and how to create resource files for the Mobile Internationalization API (JSR 238).

The Mobile Internationalization API provides a standard way to customize resources such as label strings and images and pack them efficiently into the jar file. As long as the resources are organized correctly, the API consults the platform behind the scenes to determine which set of resources should be used at any given moment. The trick is building the resource files and the correct resource directories. JSR 238 defines a special file format (.res) that allows you to pack a set of different resources together in a single, efficient binary file. As you might imagine, that means there’s a little work to be done to create the resource files — you can’t just create them by hand in a text editor as you might with a properties file.

Nokia has been kind enough to provide a reference implementation for this JSR that you can download here. The Nokia reference implementation provides both the tools to create the resource files and an emulator that allows you to test a MIDlet that uses JSR 238. All of these tools were written with the assumption that you’re using Windows — and the emulator won’t run on any other operating system — but the tools to build and test the resource files are pure Java, so you can use them on any system.

The Nokia reference implementation provides some complete sample programs as well to demonstrate how to call the resource building tools from within an Ant build file. You can see from looking at the MoonDemo that in fact that ResourceMaker tool can be integrated into an ant build as it is. Here’s the relevant snippet from the build.xml file:

<target name=”makeres” depends=”preverify”>
<java classname=”com.nokia.phone.ri.global.tools.ResourceMaker”
classpath=”${ri.home}/tools” >
<arg line=”src/res.xml src res MoonPhases en fi-FI da-DK hu-HU” />
</java>
</target>
Any java class can be called from within an Ant build file by using the “java” element (the “java” ant task) as seen here.

However, I wanted to get a better idea of how to write a custom Ant task, and this seemed like as good an application as any since the argument line is a little complicated and not terribly intuitive. So as an exercise, I wrote an Ant task that makes exactly the same call to the nokia ResourceMaker tool, but does it from a custom Ant task as follows:

<?xml version=”1.0″ encoding=”ISO-8859-1″?>

<!– A simple example ant task –>
<project name=”ResourceAntTask” default=”resources” basedir=”.”>

<!– define the task by binding it to the corresponding java code –>
<taskdef name=”buildres” classname=”net.frog_parrot.ant.BuildResources” classpath=”/home/carol/myAntTask/bin:/home/carol/JSR_238_RI_1_0/tools/ResourceMaker/bin/”/>
<!– define a custom type that is used by the task –>
<typedef name=”locale” classname=”net.frog_parrot.ant.StringElement” classpath=”/home/carol/myAntTask/bin”/>

<!– This build file’s one target calls the custom task –>
<target name=”resources”>
<buildres descriptor=”/home/carol/JSR_238_RI_1_0/demos/MoonDemo/src/res.xml” source=”/home/carol/JSR_238_RI_1_0/demos/MoonDemo/src/” destination=”.” name=”MoonPhases”>
<locale name=”en”/>
<locale name=”hu-HU”/>
</buildres>
</target>

</project>
The above is a complete build file, which would normally be named build.xml.

To create the ant task, I need to write the class BuildResources.java which extends org.apache.tools.ant.Task (see the Apache Ant JavaDoc for details on the various classes available).Here’s the code:

Continue reading

Advertisements

A Little Maze Algorithm

Way back on my Amazon reviews post, I promised I’d post an explanation of the algorithm I used to generate the random mazes for the maze game in my book.

maze.png

Unfortunately, I haven’t had time to get around to it until just now, but better late than never!!!

So, here’s how it works:

Think of the pathways through the maze as being a graph (in the Mathematical sense) where a point where two pathways join or a point where you might turn is a vertex, and then the pathways connecting the vertices are edges. It’s clear that for a maze, you want your graph to be one connected tree, in other words a graph with no cycles. As long as the entry point and the exit point are part of one connected tree, there will be exactly one path from the beginning to the end.

To apply this idea and create the maze, the first step is to use the screen and graphics dimensions to determine the size of your grid of vertices (how many squares across and how many down). In this implementation, I start by dividing the entire playing field into equal-sized squares which form part of the maze pathways if colored white, and part of the maze wall if colored black. There’s a lattice of squares that I know should be black and a lattice that I know should be white, and the trick is to figure out which colors to give to the wild-card squares.

maze_algorithm.png

Here I’ve colored gray all of the squares whose color should be decided by the algorithm (note that this screen never appears in the final game). In graph terms, the white squares are the vertices, and the gray squares are the squares that might potentially be edges by being added to the maze pathway and turned white. You can see from this that the number of rows and number of columns both need to be odd numbers.

The algorithm works by picking one of the white squares at random from the middle of the grid and growing the tree from there by picking undecided (gray) squares and turning them white. Throughout the algorithm, you maintain a list of all of the white squares (vertices) that are not yet connected to the maze, but are only one gray square away from being linked in. At each round of the algorithm, you use the randomizer to pick one square from the list and attach it to the maze (by turning a gray square white, hence adding an edge to the graph). Then just keep going until there are no white squares left that aren’t connected to the maze pathway graph, and color the remaining gray squares black.

By only adding edges to connect vertices that weren’t already connected to the graph, you can see that you’ll never get a cycle. And by growing the graph from one central point, you can be sure that all of the vertices will be connected to the same component. So in the end, for every two white squares in the maze there’s exactly one path that leads from one to the other, notably there’s a unique path from the entry square to the exit square.

For fun, I wrote a MIDlet that illustrates the maze algorithm in action. You can donwload it from my game page: it’s the one with the enticing title “Illustration of maze algorithm.”

Remember that all of the source code from the examples in my book (including the complete maze example) is available for download on the publisher’s site Apress.com. The exact page for my book is here. (The source code download is in the left sidebar under “book extras”.)

Building a J2ME project with Ant

For a basic MIDlet, the Wireless Toolkit’s ktoolbar application is pretty convenient. When you run it and click on “new project” it provides a GUI where you can enter the information that goes into the Jad and manifest files, then it creates the Jad and manifest files for you as well as creating directories where you can place the source code and the resources. Then all you need to do is select project > package > create package, and it builds the MIDlet for you including a Jar file and a Jad file that you can run on the emulator or run on an actual device. It will even create an obfuscated version for you — all you have to do is download proguard.jar and drop it into the WTK’s bin directory for the project > package > create obfuscated package to work.

However, as soon as you want to do anything fancy with your build at all (such as add extra steps for style checking, preprocesing, custom resource building, etc.) it’s a good idea to set up your build process to use Ant.

The nice thing about Ant is that it’s easy to use and it’s easy to extend it to do essentially anything you want. The build process is controlled through XML files which group sets of commands as “targets.” The commands themselves (ant tasks) are just calls to Java classes, so if there’s no existing command to perform some task that you’d like to have in your build process, you can write your own ant task to do it.

A MIDP project has some standard steps (compile, preverify, build the Jad file, write the corresponding Jar), and as you might imagine, other people have already written Ant tasks for all of this. So after installing Ant, the next step for a MIDP project is to download and install Antenna.

All you really need to do to install antenna is to download the jar file and drop it into your ant lib directory. Then the Antenna Home overview page gives you all the details about what ant tasks are available and what are all of the corresponding properties and attributes to set. Personally I like to start with at least one working demo or sample, so I downloaded the zip file containing the sources and samples, and decided to try the “games” example.

The “games” example copies the source files from one of the standard WTK demos (the “Games” demo) and builds it in a separate directory using Antenna. To run it, you just go into the games sample directory and type “ant”. If you look at the build.xml file, you’ll see pretty quickly that if you change the value of the “midlet.name” property from “Games” to the name of any other project (subdirectory of your WTK/apps directory), you can use this same build file to build another project.

There were a couple of minor changes needed to get it to work. As indicated on the Antenna home page, I had to set my wtk.home property to the actual path of my WTK directory (in my case it was “/home/carol/jme/WTK2.2″). Plus I added a line to tell ant where to find all of the antenna tasks, again as explained on the antenna home page:

<taskdef resource=”antenna.properties” classpath=”full path to antenna jar”/>

There was one strange glitch though. On my first try, it gave me this cryptic error message:

[wtkbuild] Compiling 8 source files to /home/carol/jme/ant/build/classes
[wtkbuild] javac: target release 1.1 conflicts with default source release 1.5

BUILD FAILED
/home/carol/jme/ant/build/build.xml:39: Compile failed; see the compiler error output for details.

This message is annoying because it’s clear there’s some sort of version number conflict regarding the compilation step “javac”. But version of what? I thought maybe my JAVA_HOME variable was messed up again or maybe there was a problem with the classpath or some other environment variable, but since my J2ME Polish project compiled okay (using javac and Ant) I figured it must be something antenna-specific. So like any good troubleshooter at a loss for leads, I googled the error message. Perhaps googling this same error message led you here. 😉 If so, you’re in luck because I tracked it down.

Google yielded a page that mentioned that this error appears when you use Ant’s Javac task and set the target without setting the source. I’m still not entirely sure what these version numbers relate to, but I did recall that the Antenna home page mentioned that the Antenna WtkBuild task extends the Javac task and sets the target to 1.1. In fact, if you look in the WtkBuild.java source code that you’ve downloaded from Antenna, it’s pretty easy to find the line where it does it. It looks like this: setTarget(“1.1”);

Now, you can add a call to setSource in the code and then rebuild and rejar the Antenna code, but — as you might guess — you can also just set this value in the build.xml file in the command where you call the “wtkbuild” task. I’m not sure what the optimal values for source and target are in this case, but through a little trial and error I found some that worked:

<wtkbuild srcdir=”${midlet.home}/src” destdir=”classes” preverify=”false” source=”1.3″ target=”1.1″/>

or

<wtkbuild srcdir=”${midlet.home}/src” destdir=”classes” preverify=”false” source=”1.5″ target=”1.5″/>

Some other values I tested yielded other amusing error messages such as the following:

[wtkbuild] javac: invalid source release: 1.1

For my next adventure I will write my own Ant task!!! Stay tuned!!! 😀