ReportNG 1.1.2
ReportNG version 1.1.2 is available for download. ReportNG is an HTML/XML reporting plugin for TestNG.
There are only two small changes in this release. The first is a fix for an avoidable NullPointerException if the target directory does not exist. The second updates ReportNG to work with this change in TestNG 5.13.1. Thanks to Nalin for providing a patch for this issue.
Building Two Versions of the Same Android App
There are good reasons to want to build two versions of the same Android application. The most common scenario is to produce a free demo/reduced-functionality version of a non-free app. You could achieve this by maintaining two separate source trees but the duplication would make most developers wince. So the question is how to build two differing apps without duplicating the code and resources?
Building Android Apps with Custom Ant Scripts
The answer is Ant. Maybe it’s also possible with Eclipse. I doubt it but I don’t know and I don’t care to find out. As I mentioned previously, the Android Ant build system is fairly painless to use. If you want to customise it though you’ll have to do a fair bit of digging as it doesn’t appear to be documented anywhere. The first place to look is the <sdk_dir>/platforms/<target_dir>/templates/android_rules.xml file that is used by the build.xml that the Android tools generate for you. This will give you a good idea of the various stages of the build but if you want to experiment with the Android Ant tasks you’ll have to look at the source to see what attributes they support (making sure that the version you are looking at is the same as the version you are using). The AaptExecLoopTask is just a simple wrapper around the aapt tool but the ApkBuilderTask is non-trivial.
The outline of a minimal Ant build for an Android app looks something like this:
- Generate the R.java file from the resources using the the exec task and the aapt tool with the -J option.
- Compile all of the app source, including the class generated in step 1.
- Use the dx tool to convert the Java bytecode into a .dex (Dalvik executable) file.
- Use the aapt tool (either via the exec task or via the provided AaptExecLoopTask) to package the resources.
- Build the .apk package using the ApkBuilderTask.
- If you are building a release package rather than a debug package, sign the .apk file using the signjar task.
- Use exec to run the zipalign tool on the .apk file.
More advanced applications will involve additional steps, such as running the aidl tool.
Once you have the outline of your build in place, you can start to customise it using your standard issue Ant prowess.
Different Resources for Different Versions
In my scenario I don’t mind shipping all of the code with both versions of the application. The difference is just the initial Activity that each uses. It doesn’t add much bloat to the package and the code is useless without the full set of resources so there is no danger of somebody hacking the demo version into a fully functioning version. In other words, I don’t need to worry about excluding certain classes from one version or the other.
I do however only want to include a subset of the resources in the demo version. The way I have achieved this is to replace the default res directory with three directories: res-common, res-demo and res-full. I then use the Ant copy task to construct the res directory from the appropriate pair of directories prior to building.
Different Manifests
Because I want to invoke different activities, I need to define the AndroidManifest.xml differently for each version. My first idea was to just have two different files with different names but I discovered that the Android tools get upset if the file is not called AndroidManifest.xml, even if you explicitly specify which file to use. This just means that I have to copy the chosen manifest so that it has the correct name.
The biggest problem with building two versions from the same tree is resolving conflicts in the application package name. Each Android application must have a unique application package. This is specified in the manifest. You can just use the same package name for both versions but users will run into problems if they ever try to install both versions at the same time. They will likely end up not being able to use either. Despite the drawbacks, this method seems to be widely used judging by the number of apps in the Android Market that warn users to uninstall the demo version first.
So we’ll just change the package name in one of the manifests then? Yeah, that would be nice. The problem is that the package name specified in the manifest is the package into which the R class is generated. If the two versions of your application have their R classes in different packages then common classes will not compile for both versions.
Android 2.1 introduces the --custom-package option for the aapt tool which allows you to over-ride where R.java will be generated. So the idea is to set the application package differently in one of the manifests but then to use this option to make sure that R.java is still in the same place as in the other version. I tried this and it resolved my compile problems but there were resource problems at runtime. I didn’t fully investigate what was wrong because I found another approach that appears to work.
The aapt tool also has the --rename-manifest-package option. Leaving the application package the same in both manifests and then using this option at step 4 above, I was able to generate a working demo version and full version from the same source tree and have them both functional when installed at the same time.
The whole custom Ant build exercise was not nearly as straightforward as I would have liked, mostly due to lack of documentation, but it is at least a working solution to the problem. Another, probably more recommended, way of achieving something similar would be to use library projects.
Android Adventures
Late to get involved as ever, I’ve been developing with Android for the last couple of weeks. On the whole it has been a positive experience (thanks to Richard for pointing me in the right direction with my queries).
My first impression is “what the hell were Sun doing for the last decade?” Android shows what J2ME/JavaME could have been. A proper Java environment for mobile devices (the fact that it uses Dalvik is largely inconsequential). J2ME may have first arrived when mobile phones were far less capable than they are today but, like Java in general in the last few years, it never really progressed. Worse still, with its numerous device profiles and JSRs it betrayed the “Write Once, Run Anywhere” philosophy that is so fundamental to Java. With J2ME it’s more like “right once, wrong somewhere else”. You don’t really write Java at all, you write some horribly restricted, out-dated subset of it. That’s not to say that J2ME was not a success of sorts despite its numerous short-comings. I don’t have the figures to hand but I believe it’s true to say there are vastly more J2ME-enabled devices in circulation than iOS and Android devices combined.
Pain-Free Mobile Development
Android is a complete reboot of Java for mobile devices. No longer do you have to worry about which devices support floating-point arithmetic or how to do anything useful with an anaemic UI toolkit. No more making do with Vectors and without generics, or wondering what happened to half the useful classes and methods that you take for granted with JavaSE.
Of course, nothing’s perfect. The API documentation, while generally pretty good, is not quite up to Sun’s high standard, the UI toolkit is either slightly buggy or slightly unintuitive (probably both), and a couple of things I wanted to achieve were less straightforward than I might have hoped. These however are minor gripes. The resources framework seems to do a pretty good job of dealing with the differences in platform versions and screen sizes. As Sun no doubt learned from J2ME, there is a real risk of fragmentation when different manufacturers want to deliver different capabilities. So far it seems under control.
The documentation favours Eclipse throughout but fortunately it’s pretty painless to develop Android code without it. The Ant tools are fine and, if necessary, it seems flexible enough that I could move things around to employ more sophisticated builds. I’m not sure how easy it is to use TestNG in preference to JUnit when using the Android tools. At the very least it would be possible to just bypass the Android test project stuff and test your Java classes the way you normally would. Given that Cedric was heavily involved in Android it’s mildly surprising that TestNG support is not included out-of-the-box.
Android Market
Yesterday, after paying the $25 registration fee, I pushed my first two (pretty basic) apps to the Android Market. This is an area where Google has room for improvement. It’s all a bit simple at the moment. As I’m in the UK my prices are set in pounds. There is no way to specify different prices for different currencies, nor does the market automatically convert prices for users. That means that, as a user, you are presented with application prices in at least four different currencies (US dollars, Euros, Sterling and Yen) and have to do the necessary conversions yourself. I would like to be able to specify that if my application costs £1.99 in the UK, then it should be $2.99 in the US and €2.49 in the Eurozone.
The other thing you can’t do is respond to user comments. Somebody left a comment that my app did not work properly for them. Unfortunately they provided no details to enable me to track down the problem. Worse, they wrongly assumed that the functionality was simply missing and stated as much. As the only comment on the app so far, that will likely dissuade other people from buying.
The good thing about the Market is that you have the freedom to upload pretty much whatever you want and to have it immediately available to users. Unlike the iPhone, you are not subject to the whims of an inconsistently applied approval process.
My First Apps
So what did I make? My first app is a simple utility for performing a multi-stage fitness test (a.k.a “Beep Test” or “Bleep Test”). It’s a one-button UI that emits the necessary beeps at the appropriate intervals and displays status information such as current speed and cumulative distance.
My second app is an educational game called Flagpole. All you have to do is identify flags. You get one point for each correct answer and it’s game over when you get one wrong. It’s divided into challenges of increasing difficulty, so you might start with South America, for which there are only 14 flags to identify. Eventually you’d progress to “The Whole World”, which would require you to correctly identify 232 flags without making any mistakes.
I intend to release further, more sophisticated applications in the coming weeks. These apps are sold via Rectangular Software, which is the new home for my commercial software development activities (contract/freelance development and now applications). My open source projects remain here at uncommons.org.
“constrFields” runtime error message using HStringTemplate
This post is one for the Google spider so that if somebody else has this problem they can find the solution by searching (I haven’t found mention of it anywhere else on the web).
If you are using HStringTemplate (version 0.6.3 at least) in Haskell and your program is failing at runtime with the not-particularly-informative message "constrFields", you might wonder what the problem is. This message is generated by the SYB library used in the implementation of Text.StringTemplate.GenericStandard. The error is caused by attempting to access a constructor for a primitive type.
Why is HStringTemplate doing this? Looking at the HStringTemplate source we can see that it does not currently support generation of generic ToSElem instances for records that have fields of type Char. At the moment, the simplest solution to this problem is to change your Char fields into Strings.
Zeitgeist in the Wild – Auto-updated Football Headlines
Having started with stats.footballpredictions.net the other day, I am continuing with the novel idea of actually putting code I have written into action. If you are a regular reader here you may remember that some months ago I mentioned a library that I had written called Zeitgeist. Zeitgeist analyses a set of RSS feeds and groups articles by topic.
As a companion to the aforementioned stats.footballpredictions.net, I am now using Zeitgeist to track football news from various sites across the Internet. The result is news.footballpredictions.net. This is simply the Zeitgeist publisher application being invoked every 30 minutes by cron. The site should probably be considered a beta since occasionally the article groupings are unsatisfactory, but for the most part it’s a useful way of keeping up to date with the latest stories without having to monitor dozens of sites yourself.
Announcing stats.footballpredictions.net
A long time ago I wrote a brief round-up of the options for generating HTML output from Haskell. The reason I was looking into this at that time was because, as an exercise to learn more about programming in Haskell, I was attempting to replicate the functionality of my Football Statistics Applet (FSA) but with pure HTML output rather than a heavyweight interactive Java applet.
The result of this effort was a Haskell program I call Anorak, the vast majority of which I wrote quite a while ago (it’s not going to win any prizes for beautiful Haskell code). It processes FSA data files and, using HStringTemplate, generates static HTML pages containing league tables, form tables, sequences and more.
Having left Anorak dormant for months, yesterday I tidied up a few rough edges and created stats.footballpredictions.net. This online resource provides current and archive statistics for the main football leagues in England, including an all-time Premier League table that incorporates the result of every match played since 1992. I also intend to include all of the main Scottish divisions soon but the Scottish Premier League has a bizarre split structure that, though supported by FSA, is not yet supported by Anorak. Other European leagues (Serie A, La Liga, Bundesliga) will follow some time in the future.
Update: Anorak has been updated to deal with the SPL-style split format and the site has now been expanded to include the SPL and all divisions of the Scottish Football League.
ReportNG 1.1.1 – The Less Embarrassingly Bad Version
It seems that ReportNG 1.1 fared badly when it came into contact with the real world. It was a buggy piece of crap. If you upgraded and suffered IllegalStateExceptions or NullPointerExceptions, I’m sorry for wasting your time.
The new chronology page was the root of all the problems. The main one (symptom: IllegalStateException) was triggered when you used TestNG’s @AfterXXX annotations. My tests included only @BeforeXXX annotations so I didn’t detect the issue. I have improved the tests and fixed the cause.
Having fixed the stability issues I am left with a chronology page that has a couple of problems with the accuracy of the information it displays. These are due to invalid assumptions on my part about what the TestNG API would return (assumptions I should have tested more thoroughly). There may well be other ways to get TestNG to provide the information required to produce a worthwhile chronology but for now I have disabled it in version 1.1.1. Compared to 1.0 this version offers i18n and a fix for problems with Gradle. We’ll just forget that 1.1 ever happened.
ReportNG has moved to GitHub. The project website is at http://reportng.uncommons.org. The SVN repository and issue tracker at Java.net are no longer in use.
Moving Projects from Java.net to GitHub
How to move your project from Subversion on Java.net to Git on GitHub without losing the change history.
Cloning the Subversion Repository
The normal way to duplicate a Subversion repository with full history is to use the svnadmin dump and load commands. Unfortunately, most SVN hosting services, including Java.net, do not provide access to svnadmin commands or direct access to the file system.
Fortunately, there is another way to clone a repository, complete with all its history, that requires only read access to the repository: svnsync.
The first step is to create a local SVN repository into which you will mirror the remote Java.net repository.
svnadmin create myprojectBefore cloning the contents it is important that you add a pre-revprop-change hook to your new local repository. This is a script that must complete successfully (exit code 0) before any changes to revision properties are accepted. The easiest way to do this to add an empty script and make it executable.
echo '#!/bin/sh' > myproject/hooks/pre-revprop-change chmod +x myproject/hooks/pre-revprop/change
Bearing in mind that we want to preserve tags and branches too, not just the trunk, we can then mirror the top-level of the remote repository.
svnsync init file:///pathto/myproject https://myproject.dev.java.net/svn/myproject svnsync sync file:///pathto/myproject
This may take a while if the repository is large and/or your connection is slow.
Stripping Java.net Web Content from the Repository
Java.net uses the project SVN repository to manage the project website, with the files stored under trunk/www. When migrating from Java.net you probably don’t want to continue with this approach. If that’s the case then you’ll want to remove all traces of the www directory from the repository. The usual way of deleting a file – removing it from the working copy and then committing – will not purge its history so instead we use the svndumpfilter command.
First dump the mirrored repository:
svnadmin dump myproject > dump
We can the remove all traces of the www directory. Any commits that only touched files under www are now empty and are dropped completely. All remaining revisions are renumbered to avoid gaps in the sequence.
svndumpfilter --drop-empty-revs --renumber-revs exclude trunk/www < dump > filtered
The final step is to restore the filtered dump in place of our local repository.
rm -rf myproject svnadmin create myproject svnadmin load myproject < filtered
Migrating the Repository from SVN to Git
Now that the local SVN repository contains only what we wish to keep, we are ready to migrate it to Git. To achieve this I follow Paul Dowman’s instructions.
The first step is to import the SVN repository into a new Git repository.
git svn clone file:///pathto/reportng --no-metadata -A authors.txt -t tags -b branches -T trunk reportng-git
The authors.txt file maps SVN users to Git users. Your Java.net repository may have commits attributed to the users root and httpd. You should probably just map these to your own user name. There should be one entry for each committer:
root = Your Name <you@example.com> httpd = Your Name <you@example.com> you = Your Name <you@example.com> other = Someone Else <other@example.com>
Refer to Paul’s full instructions if you have branches and tags to maintain.
Pushing to GitHub
Create a new repository on GitHub and then add this as a remote for your local Git repository.
git remote add origin git@github.com:username/myproject.git
And then push:
git push origin master --tagsJob done.
ReportNG 1.1 – i18n, Gradle fix, chronological ordering
Over the last 6 weeks or so I seem to have taken an unintentional extended break from programming (and from posting here). It’s time to get back into the swing of things and top of my TODO list was putting the finishing touches to ReportNG 1.1 (ReportNG being an alternative HTML reporting plug-in for TestNG).
This new release fixes a problem people have been having using ReportNG with Gradle. It also adds internationalisation support. So now, as well as the default English text, there is also support for French and Portuguese. The Portuguese translation was contributed by Felipe Knorr Kuhn. The French text is just something I added as a proof of concept. It is likely to be offensively bad to a native French speaker and I welcome any corrections. I’d also appreciate any translations for other languages (just open an issue in the issue tracker and attach your translated version of this file).
The other major change is the addition of the “Chronology” page. This is something that exists in the default TestNG reports that I originally decided to leave out of ReportNG. I didn’t really have a use for it but several people have asked for something similar so I have added it.
ReportNG Conquers Google, No Longer Just a Typo
This time last year, if you typed “reportng” into Google, you would get this:

This was Google’s way of telling the world that my project was insignificant, that the only people who would type that particular search term were those without full control of their fingers.
The Subversion repository for ReportNG dates back to September 2006. I’ve been waiting some time for Google to acknowledge its existence:
I didn’t have to think too long over the name for ReportNG. Unexciting as it is, it was a fairly obvious due to its relation to TestNG. It also has a built-in barometer for success. When Google stops asking “Did you mean reporting?” I’ve made it.
Well it seems I’ve finally “made it” – whatever that means. It feels like a bit of an anti-climax but, for what it’s worth, Google now considers ReportNG to be something more than a careless mistake:


