Building a Blackberry app can turn out to be quite a challenge. Apparently RIM likes to treat app developers as explorers making their way through an unknown jungle. Luckily when you’ve travelled that path many times as we had, you get to be certain you’ll end up in the right place.

The place where imo RIM really gives developers a hard time is OS fragmentation and poorly documented API’s. My personal favorite is the very common note found in RIM javadoc stating that „this method is invoked by the underlying framework and might not work as expected“. Surprised? I was. So yes, we all know Blackberry development has its issues. But then again, which platform doesn’t?

There are many roads you can take when building a RIM app. It really depends on the requirements. A couple of times I came across a simple scenario where the goal is to generate a single application build to cover multiple OS versions and devices. Typically this means having a build able to run from 4.3+ and (ideally) up to 5.0. Advantages of a single build are obvious, especially if you’re deploying OTA from your own site and you’re not really keen on using a device detection service such as Wurfl. Obvious disadvantage is having a larger build size. Whether or not you can live with this really depends on your application.

If you’re deploying through AppWorld or if you really prefer multiple builds, you can always use Antenna (http://antenna.sourceforge.net), play with some preprocessor switches and you get the nontouch build for your Curve and a touch build for your Storm. But that’s not the way we’re going here.

When trying to make your app work on a wide span of API versions, the obvious thing is to make sure you don’t break your app on lower versions by using upper version API’s. For a big part of the Blackberry API this turns out not to be a problem. However, the UI is where you need to take a better look. Typically this concerns the Blackberry touch API, i.e. TouchEvent, TouchGesture, TouchScreen etc. and we’ll take them as an example.

Once you’ve written your code (e.g. MySuperButton) that does miracles both on your Curve and your Storm (even Storm1!) and decided you want your SSB, all you need is to structure your code properly and rely on dynamic loading. Create a base version of your component that works on <4.7 (MySuperButtonBase). Then inherit this in your subclass MySuperButtonTouch and reimplement touch specific stuff. At the point where the button actually gets created you’ll need to ask the device about its type (e.g. use net.rim.device.api.system.DeviceInfo) and then create the instance you need, i.e. base for <4.7 or touch for >=4.7.

Key point is not to reference or import your touch button anywhere except the place where it actually gets created. And when you do create it, you must do it in a special kind of way as shown in the example below. Keep in mind you’ll need both of your classes to conform to a common interface to make this work.

if (isNonTouchOS()) {
    button = new MySuperButtonBase();
} else {
    button = Class.forName("com.example.ui.MySuperTouchButton").newInstance();
}

Of course, all this is not enough if you still keep the touch class in your main application bundle. It will inevitably get loaded and your app will crash. To achieve our goal, all classes we want to dynamically load need to be placed in a separate module. This module gets bundled with our main application as a simple library and this is fully supported by RIM. When creating a touch instance like in the example above, it will get dynamically loaded from the bundled touch library. So the touch library actually gets loaded only when you need one of its types.

If you’ve built more then one Blackberry app, chances are you already built a common library you simply reuse in each new app. I for one am very happy to reuse our proven networking component, since I’m sure every Blackberry developer knows that networking is the 9. circle of RIM hell. Any other libraries you might have will also get bundled in the same way. So typically you’ll have a couple of projects in your setup like in the screenshot from my example workspace.

workspace_screenshot

When building any kind of application i prefer to make it as clean and automatic as possible so Ant (http://ant.apache.org/ ) is always my choice. Having a standalone Ant script also makes it easier to run your builds on e.g. Hudson (http://hudson-ci.org/) if you have the need for continuous integration. The awesome tool that brings Ant and Blackberry together is bb-ant-tools (http://bb-ant-tools.sourceforge.net/) which gives you support for anything you might need. Well almost anything.

When building our SSB, we can rely completely on bb-ant-tools to build our library modules and the main application module. You also able to easily extract COD siblings and update the jad file properly. Signing your app is also covered. However, we did run across an issue which I was unable to solve with bb-ant-tools alone.

Basically it’s the problem of linking our library modules to the main application. After we’ve built our main app and libraries in the usual manner, we get a jad file and a bunch of COD files for the main app, and also a separate jad+COD’s family for each library module. bb-ant-tools weren’t useful at solving this so I decided to write a simple Ant task to do the job of merging all other jad files into the main app jad.

The task is simple enough, since all you need to do is to place all your main and library COD’s together and update the main app JAD with information about all COD’s. JAD files typically contain three pieces of information about a COD file: URL (COD name), SHA1 signature and COD size. All the task really needs to do is take this information from individual library JAD files and merge them into the main app JAD file. Of course keeping the COD serial numbers in mind while doing this. Simple JAD snapshot below explains.

Here’s how a main app JAD files looks like if you have a single COD.
(sha and size are the same and shortened for illustration)

RIM-COD-URL: customerbasename-mainapp.cod
RIM-COD-SHA1: 75 98 d0 c9 ae 0d 52 81 3c
RIM-COD-Size: 61336

Lets say your library has two COD’s.

RIM-COD-URL: customerbasename-fiveminlib.cod
RIM-COD-SHA1: 75 98 d0 c9 ae 0d 52 81 3c
RIM-COD-Size: 61336
RIM-COD-URL-1: customerbasename-fiveminlib-1.cod
RIM-COD-SHA1-1: 75 98 d0 c9 ae 0d 52 81 3c
RIM-COD-Size-1: 61336

Goal is to end up with your main app JAD looking like this:

RIM-COD-URL: customerbasename-mainapp.cod
RIM-COD-SHA1: 75 98 d0 c9 ae 0d 52 81 3c
RIM-COD-Size: 61336
RIM-COD-URL-1: customerbasename-fiveminlib.cod
RIM-COD-SHA1-1: 75 98 d0 c9 ae 0d 52 81 3c
RIM-COD-Size-1: 61336
RIM-COD-URL-2: fcustomerbasename-fiveminlib-1.cod
RIM-COD-SHA1-2: 75 98 d0 c9 ae 0d 52 81 3c
RIM-COD-Size-2: 61336

And here we finally are, with our single simple build that works both on your Curve and your Storm. I’m open to the idea that I may have missed this use-case in bb-ant-tools so I’d like to get some feedback if that’s the case. I hope this turned out to be useful!

0 comments