Logo Computer scientist,
engineer, and educator
• Articles • Articles about computing • Articles about software development

My adventures with developing a Qt application for the BlackBerry PlayBook tablet

The recent fall in price of BlackBerry PlayBook tablets potentially makes these devices much more attractive to buyers — even if only as media players. Right now in the UK you can pick up a 64Gb unit for just over £100: a price that compares favourably with media players from Archos and Samsung. Of course, with the PlayBook you're getting a full tablet PC, with Web browser, camera, personal information manager, and support for 3rd-party applications.

The delative dearth of applications (compared to the number available for Android) is seen by many as the weak point in the BlackBerry tablet's ability to develop a decent market share. However, the reduction in price has roughly coincided with a number of developments of particular interest to potential application vendors. Most significantly, perhaps, is the recent introduction of Android emulation in the PlayBook OS. Some porting is still necessary but, potentially, vendors with existing Android applications might be encouraged to try their luck in the BlackBerry market.

However, for my purposes, of more interest is the fact that BlackBerry has released tools for compiling and deploying native-code applications (the Native Development Kit, NDK) for the PlayBook. We have to be a bit careful about the word 'native' in this context; many writers use the term 'native' to mean 'written specifically for the PlayBook', rather than ported from Android. I'm using the word native in that sense and the traditional sense of an application deployed as machine code. This new development is of interest because it offers something that Android does not offer — the ability to develop fully-featured, desktop-style applications, free of the limitations posed by the tightly controlled virtual machine and user interface of Android.

This freedom and flexibility come at a price, however. The BlackBerry NDK provides only raw, low-level platform services. What I mean by that is that the application sees a video framebuffer and a source of input events (keystrokes from the virtual keyboard, for example). Notably, there is no user interface library beyond very rudimentary window control. No widgets, no window manager, no kinetic scrolling, nothing. Whatever user interface features you want, you get to code yourself, down to the pixel level. It's a bit like developing for X on a Unix platform, without even a rudimentary toolkit.

This situation is less painful than it might be, because soon after the release of the NDK, substantial work was done on porting the Qt user interface platform to the PlayBook. Qt provides a very rich, inclusive library of user interface widgets and related services — I/O, text formatting, and networking, for example.

In this article, I will outline my efforts to develop a desktop-style file manager for the BlackBerry PlayBook, using Qt and the BlackBerry NDK. My reasons for doing this are partly for self-education, and partly because the PlayBook lacks such a thing itself. There is a rudimentary file browser, but it has no concept of a folder or directory. The browser, and all the built-in applications, flatten any directory structure that the user might create. In a small computer with 64Gb of storage, the inability even to create and browse folders, or to move files from one folder to another, is — it seems to me — a shocking omission.

I will also make some comparisons between developing for the PlayBook and developing for the Android platform.

Developing the file manager application hasn't been an entirely satisfactory experience, although I'm moderately happy with the results. My hope is that my experiences will be of some help to other people considering developing for the Blackberry platform, or even just interested in this kind of technology. I'm not going to be able to go into a whole lot of detail — the best I can do is point out particular areas where I had difficulty, and what I had to do to overcome those difficulties (where I could).

Setting up

BlackBerry supplies versions of the NDK for Linux and Windows platforms. For either platform, the NDK is a huge download. A large part of that download is the Mometics integrated development environment (IDE). I'm not a big fan of IDE tools in general, and I'm unsure whether the IDE can be used for development with Qt. If it can, the process does not seem to be well documented. What's more, it seems that most work in this area has been done on the Linux platform — presumably it is possible to use BlackBerry's Windows tools to produce Qt-based applications but, again, there's little documentation to support this.

Consequently, I'm working entirely with command-line tools and Makefiles on a Linux platform. That suits me fine — it's exactly what I'm used to, but I don't think it's the way BlackBerry intended their tools to be used, and there's little information from BlackBerry about working this way.

The NDK is available from the BlackBerry Native SDK Web site. There's a lot of information on the BlackBerry site about code signing, and the keys that you will need to get from BlackBerry to make applications available to other users. In fact, for most of the development process you don't need these keys. Instead, you can install a 'debug token' on the PlayBook, and package applications in debug mode. Information on doing this is provided on the Setting up the Native SDK page at the Qt Project Web site and, as it's a bit of a bear, I'll have more to say about it later.

To use Qt you're going to need the Qt libraries and header files. These are, or should be, independent of the development platform and, by now, perhaps they are available somewhere as precompiled binaries. However, provided the NDK is set up correctly, it's actually quite straightforward to build Qt from source. This process is also documented at the Qt project Web site: building Qt for BlackBerry.

The result of following all these instructions should be a BlackBerry-specific version of the GCC compiler tools, an IDE (which I haven't used, except for generating code signing certificates, as explained below), and a set of Qt libraries ready to be linked against your application.

Provided that the environment is set up correctly, you should be able to build applications specified by a standard Qt .pro (project) file. The .pro file is processed by the qmake utility to produce Makefiles, which can then be processed using GNU make in the usual way. Of course, you can write the Makefiles manaually, but the QMake approach automates the very ugly step of running the Qt Meta-Object Compiled (moc) in the various C++ classes. The .pro file won't do the packaging of the application into a deployable bundle, but (Blackberry-specific) instructions can be added to it to do that.

Things to watch out for

There isn't space to describe all the detailed steps needed to write an application for the PlayBook; I'm assuming that the reader as some knowledge of Qt, C++, and mobile application development in general.

Deployment format

The Playbook deployment format is a BAR (Blackberry ARchive?) file, conventionally with a name ending .bar. The BAR file is simply a ZIP archive containing a manifest file, the executable code, a deployment descriptor (previously called blackberry-tablet.xml; the preferred name now is bar-descriptor.xml), and any other resources the application needs. In a Qt application, those resources will include the Qt libraries themselves. The format of the BAR file looks superficially similar to that of a signed Java Archive, but I don't think it's similar enough that you could use common Java tools to create it.

BAR files can be signed or unsigned. An unsigned BAR can only be deployed on an emulator, or on a real tablet with a debug token installed. Because the debug token is identified in the BAR file, it is impossible (I believe) to distribute unsigned BAR files in a way that is useful to anybody except other developers with access to the NDK tools. They are of no use to end users. More on the knotty issue of code signing later.

Packaging the Qt libraries with the application presents the obvious disadvantage that they are likely to be larger than the application. The minimum additional size seems to be about 6Mb (compressed). The advantage is that you can, if necessary, modify and build Qt to suit your application. Discussions on the various developer forums suggests that such modifications are sometimes necessary — the Qt port to BlackBerry is not perfect, and does not suit every application. However, I did not find it necessary to make changes to the Qt libraries for my purposes.

In practice, the BAR file gets generated using the blackberry-nativepackager utility, part of the NDK. This utility has a whole bunch of obscure, poorly-documented command-line arguments. The only way to figure out what they all do seems to be to look at other peoples' projects, coupled with a fair amount of trial and error.

Everything the application needs has to be packaged into the BAR file. The structure of the BAR file maps onto the structure of the directories created when the application is installed, but in a non-obvious way. The example of making, say, an icon available as a PNG file illustrates this.

To pack the icon (or, indeed, anything) into the BAR file, you need to use a command-line argument of the form:

blackberry-nativepackager ...\
  -e path/to/icon.png res/icon.png
res/icon.png is where the PNG file will end up in the BAR archive. But if you look in the archive, you'll see that the location of icon.png is
native/res/icon.png
The native directory is implicit. On deployment, the whole of the native directory gets unpacked into a folder app/native, which is a subdirectory of the application's private installation directory. That installation directory will be the working directory of the application at run time. What this means is that, to load the icon file in you application, you need to do:
QIcon *icon = new QIcon ("app/native/res/icon.png");
And, most importantly, you need to avoid changing the application's working directory, otherwise it won't be able to find its resources. If you have to change the working directory, then it's possible to work out where the resources are installed by working upwards from $HOME and the down again, but it's a bit ugly. You can't specify the absolute path of any resource on the BlackBerry filesystem, because your application has no control over where it is installed.

What applies to icons and resources also applies to libraries. To pack the Qt library libQtCore.so.4, you need to use the command-line switch

  -e /path/to/libQtCore.so.4 lib/libQtCore.so.4
and this will put the library into the BAR file in the location
native/lib/libQtCore.so.4
and expand it into the PlayBook into the subdirectory
app/native/lib
of the current working directory. Note the implicit directory native again. Then you need to set LD_LIBRARY_PATH so that the application can find the library and you need to tell Qt where to load libraries that it loads dynamically. For the first task you can set LD_LIBRARY_PATH using the <env-var> element in bar-descriptor.xml. The format needs to be:
<env var="LD_LIBRARY_PATH" value="app/native/lib"/>
For the second task, in your application you can do:
QCoreApplication::addLibraryPath("app/native/lib");
Notice the non-obvious mapping between the directory names you use as arguments to blackberry-nativepackager, and the directory names you application needs to use; note again the essential use of relative pathnames for all these resources.

Working directory and $HOME

Just as on the Android platform, each application on the PlayBook has seperate user identity. This separate identity is used to segregate applications so that they cannot interfere with one another. Applications can share files in the shared media area (directory /accounts/1000/shared), which is the same directory that you see when mounting the PlayBook as a USB device. Even to use that directory requires a specific setting in the bar-descriptor.xml file,
<action>access_shared</action>
and the user will get warned about it when installing the application.

Because each application has separate user identity, the environment variable $HOME is constant only within the application. Each application will see a different version of $HOME. At startup, $HOME points to a directory that is readable and writable by the application, and is a reasonable place to store configuration files and the like.

BlackBerry's impoverished platform

In many areas, the BlackBerry PlayBook is a stable, mature platform. However, attempting to implement a file manager made me very aware, very quickly, how much is missing in the platform, compared even to Android, let alone to a desktop computer.

Most significantly for my purposes, applications cannot invoke one another, except to the very limited extent provided by the Navigator API (see below). There is no way to decide which application will handle a particular type of file, even if the file is of a type that the Navigator API recognizes (essentially media files, PDFs, and Docs2Go docuemnts). Even media files are limited to the types that the built-in media player can play. You can, for example, install an application that can play FLAC files, but you can't launch it from a file manager, or even the built-in file browser, because it's not something the media player can handle. Android supports a method of inter-process communication called 'intents'. This is very restrictive compared to what a desktop application would expect to be able to do, but even that meagre level of integration is missing in the PlayBook.

The PlayBook platform has very limited support for customization, either programatic or by end-user configuration. On Android, for example, it is possible to implement an alternative keyboard handler, or an alternative lock screen, or screensaver. None of this is possible on the PlayBook. The keyboard layout is particularly problematic for some applications — the built-in keyboard — which cannot be modified — has no arrow keys, no tab key, no 'end' or 'home'. Any application that requires these keys simply can't be implemented in an elegant way.

Consequently, in some areas, the PlayBook OS has the look of a beta product, or a work in progress. Some of its limitations can be worked around; many can't. I'm told that the BlackBerry 10 OS will address some of the limitations, but that's not much help for PlayBook developers, since we have no idea when, if any, this OS will be available for the PlayBook.

Navigator integration

The Navigator is the name that BlackBerry uses for the application launcher. I like the fact that the BlackBerry OS actually sees applications as processes, which the user can explicitly start and stop. The Android, OS makes it very inconvenient for a user to stop an application, either because it's misbehaving or just because the memory could be better used elsewhere. The application lifecycle is expected to be managed entirely by the platform. On my Android tablet, when I click the button to select between running applications, I see a huge list, some of which I haven't used for months. The BlackBerry approach is more desktop-like.

The BlackBerry launcher provides an 'X' button to close an application. However, with a Qt application, I've noticed that the application does not shut down cleanly when the X is tapped. In particular, the application's main event loop never ends. The means that a lot of the cleanup code that is normally executed when an application finishes will never get executed on the PlayBook. If an application needs to save its state, in order to restore it when it is next used, it will need to do it judiciously, during the life of the application, and not rely on getting informed when the it is being shut down. In effect, you have to code your application as if the user could do 'Ctrl-C' on it at any time, without warning.

Deploying to the PlayBook

The NDK supplies a command-line deployment utility, blackberry-deploy, which takes a .bar file as an argument. Both signed and unsigned applications can be deployed, but to deploy an unsigned application requires building the application in debug mode, and installing a debug token on the device, as explained previously.

blackberry-deploy works, in principle, over a wireless network or USB connection. However, I found that I was unable to get the USB method to work in Linux. My Linux workstation recognized that the tablet was plugged in, but was unable to find any driver for it. Wireless mode worked fine, but only so long as the PlayBook was prepared to listen for incoming network traffic. I suspect that the tablet tries aggressively to conserve power and, even when it is docked and powered, it shuts down the networking components when they are not in use. Therefore, sometimes it was necessary to wake up the networking system by, for example, running the tablet Web browser, before applications could be installed.

Deployment of an application with a minimum size of 6Mb is pretty slow — perhaps half a minute. This does make the process of making minor, iterative tweaks to the user interface pretty painful. Such tweaks are necessary, because it's rather hard to predict how the user interface will look and feel on the tablet, based only on experience with desktop programming for Qt.

Qt look-and-feel

By default, a Qt application running on the PlayBook looks like a desktop application in a very small screen. To be useable, as a minimum you'll need to increase the size of user interface elements like scrollbars, buttons, and menu items. This can be done declaratively using Qt stylesheets, which at least means that you don't have to do a lot of coding to control the appearance of the application. Judicious styling will give you a desktop-style user interface with fat-looking controls. It's workable, but not very sightly.

On the positive side, everything that you can do in a Qt user interface in a desktop application will work (after a fashion) on a Qt PlayBook application. You can create a progress dialog box, for example, and use it to show the progress of long-running operations. You don't need to do anything special to deal with long-running operations that you wouldn't have to do in a desktop application — so long as you continue to respond to user interface events, things will tick along nicely. Anybody who has had to deal with the nightmare of handling long-running operations in Android applications will surely appreciate how much less painful it is the Qt way.

On the negative side, a desktop-style interface doesn't necessarily suit finger-tapping tablet operation. If you create a QListWidget that is too long to fit on the screen then, by default, it will get a scrollbar. But tablet users aren't really used to working with scrollbars — they expect to be able to drag lists around by swiping a finger. There is no built in support for this kind of operation in the standard Qt widgets. To be tablet-like, you'll need to define your own user interface elements with the necessary additional logic, either by subclassing the basic Qt widgets, or by applying custom event filters to them. For example, it's relatively easy to implement kinetic scrolling by implementing an event filter that will turn click and drag gestures into the necessary scroller movements; examples of doing this can be found with a bit of Web searching.

Qt implementation issues

Slightly separate from the issue of Qt look-and-feel is the issue of how coding practice is inluenced by the way the Qt port to BlackBerry was implemented. Most significantly, the PlayBook has no window manager, and the Qt implementation has to work around this lack. This has two obvious consequences and, probably, some non-obvious ones that I have no yet discovered.

1. Windows and dialog boxes have no frames or captions, and cannot be moved or sized by the user. All instances of QDialog appear centered above their parent windows, and will stay there, since there's no way to move them. If you need a window or dialog that is user-moveable or user-sizeable, you'll need to implement the logic and the associated user interface elements yourself. Dialog boxes don't get a default 'close' button in the caption bar, since there is no a caption bar, so will always need to be supplied with a specific 'close' or 'cancel' button.

2. Only a maximized widget or window will be resized when the screen changes size or shape. If you set a fixed size, then that's what you'll get. Since there is no window manager, there is no way for a user to resize the window after creation. The screen will change shape when the tablet is rotated between portrait and landscape orientation; it will change size when the virtual keyboard rolls out. If you set a fixed-size main window, then the virtual keyboard will roll out over the top of it, obscuring any contents of the window. The solution is to show the application's main window using the showMaximized() function, rather than show(). This caught me out, because I can't think of a good reason ever to do this in a desktop application; but in the PlayBook it's more-or-less essential, as only maximized windows adjust to screen size.

Code signing and debug tokens

Only signed applications can be installed on real PlayBook tablets, and submitted to the BlackBerry AppWorld site for end users to download. Developers have to register with BlackBerry to get code signing keys, although I found that process quick and painless. Signing can be done by specifying particular arguments to the blackberry-nativepackager utility, or applied to a built BAR file using the utility blackberry-signer. However, the arguments you have to use to blackberry-nativepackager are different if you plan to sign the application, than if you don't; so providing a separate signing utility is not as helpful as it ought to be.

If you don't want to sign, you'll need to create a debug token, and install it on the PlayBook and build it into your applications.

I confess that I was unable to figure out how to generate the certificates that the signing utility needs, or the debug tokens, using command-line tools. The code signer looks for certificates in the directory $HOME/.rim, but the process for getting them there is not entirely clear. In the end, I used the IDE to generate the certificates for signing, and to create and install a debug token, because this process, at least, is well documented. This process only needs to be followed once; after that you can use the same certificates to sign all applications.

I was somewhat surprised to find that a particular release of an application can be signed only once. BlackBerry, presumably, keeps a record of very signing request it responds to. I presume that the intention is that you only sign the version that you plan to release to customers; for all other purposes you make do with debug tokens. The problem with this approach is that you can't distribute unsigned BAR files in such a way that anybody can use them — locking them to a specific debug token means that unsigned BARs are for personal use only. So you can't distribute early versions of your work to, say, friends and colleagues for pre-release testing, unless you sign the BAR.

You can get around the signing limitation by incrementing the version number of your application in the deployment descriptor every time you sign but, to be honest, it's a bit of a pain.

I imagine that BlackBerry has taken steps to limit the distribution of applications outside of the official AppWorld market to reduce software piracy. Looking at the experience of Android developers, it's hardly surprising that such a measure is necessary. However, their approach creates a deal of inconvenience for developers.

Comparison with Android

I was rather surprised — gobsmacked, as we say round my way — that you can't develop for the PlayBook in Java, except by targetting the Android emulator. The emulator works — in fact, it works surprisingly well; but it's slow to start up, and all emulated Android applications share one window in the launcher. There's no doubt that you're using a foreign application system. Moreover, the standard Android 'Home', 'Back', etc., buttons are emulated in rather peculiar ways, using particular finger swipes. This makes Android applications rather fiddly to use, until you get used to these oddities.

This lack of Java support is peculiar because earlier BlackBerry devices supported Java — J2ME, at least. Arguably, the typical J2ME implementation (usually the highly restrictive CLDC/MIDP variety) is not very suitable for a tablet computer. Still, the lack even of this level of Java support strikes me as rather peculiar.

It's never been very clear to me how BlackBerry sees applications being developed for the PlayBook. Until the NDK was released, the only (non-Android) way to develop applications was to use Adobe AIR — a technology really intended for embedding interactive content in Web pages. I can see the appeal of AIR to developers — it supports many different platforms with minimal code changes — but the idea of developing a really substantial application with AIR seems to me about as agreeable as walking on broken glass.

The fact that BlackBerry felt the need to release the NDK suggests that it isn't just me who feels this way. However, I rather suspect that the NDK is really intended for developers who want to port existing OpenGL games; for such developers, the lack of any user interface library is no problem, since the game will invariably include its own, based presumably on libraries implemented with OpenGL primitives.

All this means that for developers of applications other than games, there is no real equivalent of the Android Java-based development platform on the Blackberry, except the Android emulator itself. If I wanted to implement, say, a media player, an IRC client, a contact manager, an RSS feed browser, or any one of the thousands of other non-game applications available for Android, Qt is the only game in town. Unless, that is, I wanted to dive into the murky pool of AIR.

Since Qt on the PlayBook is my platform of choice (or, perhaps, of necessity), then a comparison with Java development on Android because necessary, however different these development approaches might seem.

The most obvious difference in development is the difference between C++ and Java. For my part, I find these two languages more-or-less equivalent in use. In fact, you can code in C++ for Android, but only in the form of libraries with specific interfaces to the Java code. You can't code a new user interface in C++ for Android, even should you want to. Working with C++ on the PlayBook means more than just a different programming language, it means a wholly different programming philosophy.

In my experience, the biggest difference between BlackBerry (Qt) development and Android development is that Android has a specific user interface model, and applications have to use it. That user interface model is pretty well-suited to tablet operation, and all the built-in user interface widgets support pinch, flick, and swipe gestures. If you want these things in your BlackBerry QT application, you have to code them youself. The Android interface elements by default have sizes appropriate for finger-poking, while Qt development requires a lot of tweaking to get an effective look-and-feel. You could, in principle, use the Qt-Quick progamming model with a Qt application. Qt-Quick is more declarative, and has its own language rather like JavaScript. The user interface model is far more tablet-like than raw Qt. But if you're going to go that way, I don't really see any advantage over Adobe AIR, and there are none of the advantages (cross-platform support, for example).

The finished result

Here are some more screenshots of the finished file manager in action.
The main file browser screen. Note that the scrollbar width and minimum height have had to be increased substantially from their defaults to make them useable. However, this list supports kinetic ('flick') scrolling, via a custom event filter, so there's no real need to use the scrollbar. The toolbar buttons and menu items are also substantially increased in size from their defaults. The white-on-black colour scheme looks more tablet-like, and perhaps uses slightly less battery capacity.
Search results page. The user interface uses separate tabs, as a desktop application might. However, the tab label height as a proportion of the screen size needs to be larger.
The text editor. Astonishingly, the PlayBook has no built-in support even for viewing text files. Fortunately, most of the editor logic already exists within the Qt libraries, so adding this feature to an application is relatively straightforward.
I won't be making my file manager available on the BlackBerry AppWorld site, because the administrators require far more personal information than I'm prepared to supply, just to give away my software for free. Anybody who is interested can download the application (click here). And side-load it using the DDPB utilities. A link to DDPB, and instructions for using it, are available here.
Copyright © 1994-2013 Kevin Boone. Updated Feb 08 2013