marc paradise

Blackberry and Netbeans – Localization Tutorial

by Marc on Feb.15, 2010, under Software Development

RIM provides us with a powerful API for developing Blackberry applications.  They’re making improvements in the ready availability of good documentation (slowly).  They really seem to be responding to both their community and the threat posed by iPhone and Android.  For all of that, though, their toolchain still sucks.

Presently, we have two supported options for developing Blackberry projects: use the RIM JDE (if you’ve tried to use it, you know that this isn’t an option at all); or use their Eclipse/JDE plugin.  Outside of that, you’re pretty much on your own.

I’m a long-time Netbeans fan — I’ve tried Eclipse multiple times, and I just don’t get along with it.  With a bit of headache and digging, I’ve been able to get most BB development tasks working in Netbeans.   Until this week…

In working on BBSSH, I realized that people may eventually want translations, so I set out to use the provided localization features of the Blackberry platform. (Also, all those raw GUI-related strings in my code were annoying me.) Unfortunately, because I don’t fall into the “JDE” or “Eclipse” categories mentioned above, I fell into the third: pretty much on my own.  In hopes of preventing the next person who attempts this from falling into the same category, I figured I would write up how I worked this.  Note that this isn’t necessarily the best or the only way – but it does work, and it does not add a lot of pain to the process.

This tutorial assumes you are familiar with Netbeans, and have some familiarity with the JDE. Read on for more. For the impatient, you can skip straight down to “3. The solution”.

1. Some Background (skip this if you’re familiar with how BB localization bundles work)

When you create a localization bundle in the JDE, it does some behind-the-scenes work that allow you to start using it right away.  Let’s say you created files named “MyApp.rrc” and “MyApp.rrh”.  Behind the scenes, JDE will create a file named MyAppResource.java, compile it, and add it as a resource to your project.   (Also important but less relevant here, it will also generate a binary file containing the actual string data.) The java file MyAppResource.java is a simple interface – here is an excerpt from BBSSH:

package net.uglydesign.bbssh.i18n;

public interface BBSSHResource {
 // Hash of: "net.uglydesign.bbssh.i18n.BBSSHResource".
 long BUNDLE_ID = 0xe8304654750e8634L;
 String BUNDLE_NAME = "net.uglydesign.bbssh.i18n.BBSSHR";

 int MENU_EDIT = 12;
 int INFO_SETTINGS_GENERATING_KEYPAIR = 35;
// snip
}

Those int values map to the string table, allowing you to look the value up at runtime using the appropriate ResourceBundle instance.   You would either reference this new interface directly, or implement it in your class to get direct access to the key values.  For example:

public final class SessionDetailScreen extends MainScreen implements BBSSHResource {
 private final SessionProperties prop;
 ResourceBundleFamily res = ResourceBundleFamily.getBundle(BUNDLE_ID, BUNDLE_NAME);
 // snip //
 private final String[] CONNECT_CHOICES = res.getStringArray(SESSION_DTL_LIST_CONNECT_CHOICES);
 // snip // 

 SessionDetailScreen(SessionProperties prop) {
     super(Screen.DEFAULT_CLOSE);
     this.prop = prop;
     if (prop.isNew()) {
         setTitle(res.getString(SESSION_DTL_TITLE_1));
     } else {
        setTitle(res.getString(SESSION_DTL_TITLE_2));
 }

The text in bold is  made available to your class when you implement the by the BBSSHResource interface. Implementing this interface is a convenience to save you a bit of typing. You could just as easily do this:

public final class SessionDetailScreen extends MainScreen {
 private final SessionProperties prop;
 ResourceBundleFamily res = ResourceBundleFamily.getBundle(BBSSHResource.BUNDLE_ID,
     BBSSHResource.BUNDLE_NAME);

// snip //private final String[] CONNECT_CHOICES =

res.getStringArray(BBSSHResource.SESSION_DTL_LIST_CONNECT_CHOICES);

2. The Problem

As long as you’re in the JDE or Eclipse environment, the creation of this interface is completely transparent to you.   Once you step outside of that realm, troubles begin.  As it turns out, the java interface file is created in a temporary folder, and is usually deleted shortly after it is created – giving it a lifespan of a few seconds in many cases.  The Eclipse plugin then performs some hidden internal magic to add the compiled version of that file to the Eclipse project, making it available for you to use.

I spent far too much time trying to find a way to get my Netbeans project to recognize this generated class, with no luck.  The details aren’t relevant here, but I lost about two days trying to force some the appropriate level of cooperation between RAPC and Netbeans before giving up.  My attempts yielded run-time errors or build-time errors, depending on what I was trying at a given moment.

Posting to the Blackberry development forums yielded people willing to help, but the suggestions provided did not seem to do this trick.  (Note that this could be my fault entirely, so no fault to the posters there )   Google trawling turned up a lot of references to someone who had solved this exact problem a couple of years ago — Jonathan Fisher.  Unfortunately, he has taken all of his Blackberry-related content off of his web site , so the net result was a bunch of dead links.

3. The Solution

This seemed to narrow it down to two remaining options: implement my own resource parser (possible, but pointless work – I shouldn’t have to when Blackberry already has a perfectly good one), or find a way to have a separate project that contains only localization resources.   The latter is the path that I took, and what I’ll be describing here.

Create a Resource-only project

First we need to use the JDE to create a project.  The only thing contained in this project will be our localization resources.  Note: at your discretion you may also add other resources such as graphics, but this is not covered here.

  1. Using the JDE, create a new workspace such as “YourProjectName” in a new folder named “JDE” under the project root.
    • The location you choose to create this workspace is ultimately up to you.  However, I would strongly recommend creating this project under a new folder located in your main project, such as in “/JDE” as described. It will generate a lot of clutter if you keep it at the project top level; while moving it to a new directory outside of your project folder just means that you will have to remember to check out an additional set of files before you can build/test.
    • Do not put any files from this new project anywhere under your Netbeans “YourProjectName/src” directory.  Doing so will cause further complications that I will not be addressing here. (I know this because I went that route first ;) )
  2. Using the JDE, create a new project within the workspace, called “YourProjectNameResources”
    • You should probably put this in the same folder you used for the workspace.
  3. Designate the project as a Library.
    • Right-click on the project name and choose Properties.
    • Click the Application tab
    • Change the project type from “CLDC Application” to “Library”.
    • You’ll probably also want to take this opportunity to set a version string, vendor, and description so that when someone sees this installed as a module on their BB, they will know what it’s for.
  4. In the JDE, create your resource header yourproject.rrh and resource content yourproject.rrc files.
    • When prompted for a package name after creating the RRH file,  make sure to update it.  For example, most of BBSSH’s content is under “net.uglydesign.bbssh”, so I specified “net.uglydesign.bbssh.i18n” for localization resources.  This is the package that your Resource interface class will be created under.
    • More details on how to create these files and their significance can be found in the official BB localization tutorial.
  5. Add some strings in the resource editor to get started.
  6. Build your project in the JDE by right-clicking the project name and choosing “build”
    • Ignore the warning about no main() function
    • Upon completion, you’ll now see a bunch of files in your “JDE” folder. The one that we care about is called yourproject.jar (or in my case, BBSSHResources.jar).

Add the JAR file to Netbeans.

Now we have to make sure Netbeans is aware of our new dependency, so we’ll add the jar file created by the previous step to this

  1. On the Projects tab, right-click on the Resources heading and choose “Add jar/zip…”
  2. Find your way to the .jar file created by the JDE — if you followed above, you should find this in /JDE/YourProjectNameResources.jar.

You’re done!

Netbeans takes care of the rest, ensuring that the new JAR file is included in the RAPC compilation.

Adding new strings is now very straightforward.  The only downside is that you’ll need to keep the JDE running in the background.  To add string resources:

  1. Alt-tab over to the JDE and add them via the resource editor.
  2. Build the resource project.
  3. Return to Netbeans and begin using the new resource constants immediately. Netbeans will (after a second or two) pick up the updates automatically.

4. Some Notes

That aside, there is room for improvement in what I detailed above….

  1. Thee generated resource .jar file also contains the COD file for the resource library; by extension this means that the actual binary resources are also getting packaged in your main application COD files.  This is redundant and takes up extra space.  I’ll post back on this when I update it properly (Likely sometime around when BBSSH is in public beta.)  I think the proper solution will be:
    • Modify project build.xml to clean the JAR file when creating a deployment: remove everything except the  interface class file.
    • Modify project build.xml to update the JAD and ALX files, indicating the new resources COD as a dependency.
  2. The JDE can be avoided by using RAPC directly to compile your RRH/RRC files into a COD. You can run this from any location, allowing you to remove the output clutter.  This would let you just create a new build target in build.xml, and do your resource builds from inside of Netbeans while you work.   The only drawback to that is that string editing is going to be painful if you’re not using a GUI resource editor.  It is possible (rrc/rrh are just text files after all), but after going that route myself I found it easier to just switch back and forth between the JDE and Netbeans for string editing. Maybe one day I’ll get around to a standalone editor – or maybe RIM will open source their Eclipse plugin which contains a good editor -  but for now this suffices.
  3. It has to be possible to have the main application COD reference the resource COD to provide title and description data. I haven’t looked into this yet, but I suspect this will require using a “rapc” configuration file specific to this project.

5. I’ll shut up now

I’ll continue to hope that one day RIM will realize that there really is a need to provide better tools for managing this.  Android and iPhone have great development toolchains, and Blackberry’s lack of one can only hurt it.   In the mean time, even though this is not ideal it suits me well and does the job. Hopefully it will do the same for you.

Please post a comment here to let me know if this helped you, or if you have other feedback, questions, or concerns.

package net.uglydesign.bbssh.i18n;

/**
*
*/
class ResourcePlaceholder {
ResourcePlaceholder() {    }
public static void main(String[] args) {}
}

:, ,

5 Comments for this entry

  • Alan

    Marc,

    Really interested in the completion of your ssh client for blackberry. It was on the first applications I looked for when I first purchased my blackberry.

    I also appreciate the comment on my website. It was the first non spam one I got and I actually learnt something, you can’t ask for more :)

  • Marc

    Glad to hear that it was helpful – I realized after I submitted that it probably came across as a bit pedantic, but I’m glad to see it was taken in the spirit intended. As far as spammers… they seem to have discovered my blog today, I’ve got 24 new spam comments in the last six hours. Ridiculous.

  • Everett Pickett

    I must admit I’m impressed by this posting. I love my Blackberry and < >

  • Warren Zeek

    Hello,
    Thanks for this awesome application. It is very useful in certain ways.

    Is there a way to change the orientation to landscape mode on BB Storm? My finger are too big to type in potrait mode.

    Thanks

    -W

  • Marc

    @Warren – that should happen whenever you change orientation. I can only test it in the emulator myself, but whenever I simulate rotating the BB onto its side, the screen correctly adjusts dimensions in SSH mode; and this should allow you to use the . (Telnet probably does not yet.)

    Also, I think you meant to post this to a bbssh article? This one is about Netbeans and Blackberry localization :)

Leave a Reply

Subscribe to updates via email: