How-To: Signing Your BlackBerry Application Before Deployment

A concerned reader asked me about how to sign his BlackBerry application. In this post I will try to provide you with information on the following topics:

  • Why the need to sign your BlackBerry code
  • Registering and obtaining signature keys
  • Signing your application

Why You Need to Sign Your Code

The concept of “controlled” API’s has existed since BlackBerry 3.6 as a way for Research In Motion (RIM) to track the use of some API’s for security and export control reasons. In practical terms, this means that in order to run an application on a handheld, you need to register and sign the application. Signing of applications is not required to run applications using the BlackBerry device simulator.

The BlackBerry API is divided into five groups. The first group includes all standard Java API’s from MIDP and CLDC and some BlackBerry-specific API’s. This group is open for all developers, and applications that use only these open API’s require no signatures. The remaining four groups are all controlled API’s: RIM Runtime API’s, some BlackBerry API’s, RIM Cryptography and Certicom Cryptography.

Registering and Obtaining Signature Keys

The registration process serves to verify the developer’s identity. It involves downloading and filling out a registration form that you need to fax to RIM. There’s also a one-time processing fee associated with it. RIM will send you a set of signature keys after the registration form and fee are received.

Signing Your Application

Once you receive the signature keys from RIM, you need to install them on your development environment. The detailed instructions on how to do this can be found in the BlackBerry Java Developer Guide, Volume 2 – Advanced Topics. I recommend that you study this procedure, since installing the keys incorrectly will cause the signing process to fail.

Signing the application is very easy once the keys are installed. You need to manually start the Signature Tool from the Build menu in the JDE:

The tool displays a list of necessary signatures:

When you press the Request button, the Signature Tool submits a hash of the application to RIM’s signing authority. The signing authority automatically returns the required signature, that is automatically appended to the application. The application can be loaded onto a device after this step.

Note that RIM does not receive a copy of your application, only a hash of the file(s). This allows them to determine the author of the application by matching the hash of the application against records of the hash kept by the signing authorities.

Where to Find More Information

You can find more information on this topic in the BlackBerry Java Developer Guide, Volume 2 – Advanced Topics.

End-To-End BlackBerry Application (Part 5)

This is the fifth part of my end-to-end BlackBerry application walk-through. In this article I will go over the following subjects:

  • Using resource files for localizing text strings without coding changes
  • Setting an application icon on the Ribbon
  • Home Screen’s command list icons
  • Trimming the cached articles list
  • Encoding HTTP request data
  • Application “About” dialog
  • Alerting the user when a long-running operation is taking place

Using Resource Files for Localizing Text Strings

Although an in-depth discussion about resource files is beyond the scope of this post (a good place to see more information on this subject is the BlackBerry Java Development Environment Fundamentals Guide, which you can obtain from the BlackBerry developers site),  I will tell you that each application needs a resource header file, a resource contents file for the root (global) locale and a resource content file for each specific locale it will support.

The resource header file defines descriptive keys for each localized string. Resource content files map descriptive keys to values for the global and specific locales.

Resources for a given locale end up being stored in a ResourceBundle object. A ResourceBundleFamily object groups the resources for an application as a collection of ResourceBundle objects. This is the mechanism an application uses to switch languages depending on the user’s locale.

For our application, I created the resource header file (KnowledgeBase.rrh) and a resource contents file for the root locale (KnowledgeBase.rrc). Based on these files, the BlackBerry IDE will create at compile time a resource interface, KnowledgeBaseResource, that we can use to gain access to the localized strings. The resource interface has the same name as the resource header file with the word Resource appended.

To access our localized resources through the application’s resource bundle, we first need to obtain a reference to our resource bundle:


title=”Click for expanding..”>Java-Code: ResourceBundle
private ResourceBundle resources = ResourceBundle.getBundle(KnowledgeBaseResource.BUNDLE_ID,
            KnowledgeBaseResource.BUNDLE_NAME);

Now we’re ready to retrieve a localized string like so


title=”Click for expanding..”>Java-Code: Retrieve a localized string
String screenTitle = resources.getString(KnowledgeBaseResource.TTL_HOME_SCRN);

Like I said at the beginning of this section, there’s much more to resources than what I’ve covered here. You should plan on learning more and I would suggest you start by checking out the BlackBerry Java Development Environment Fundamentals Guide, available on the BlackBerry developers site.

Setting an Application Icon

It’s time now to replace the default application icon with something nicer. To set the application icon through the BlackBerry JDE, add the image that will serve as the application icon to the Project and bring up its properties:

In the File Properties applet, select “Use as application icon”:

And when we run the application, we see the new application icon:

Note that although this procedure allows you to set the application icon, it does not allow you to change the image when the application is selected or unselected within the Ribbon.  I will describe how to achieve this behavior in a future article.

Home Screen’s Command List Icons

Originally,  the three commands on the Home Screen were preceded by the same icon, a green star:

I’ve made some changes to the HomeScreen so that now, each command is preceded by an icon that reflects the command’s function:

I achieved this by modifying the code in the MyObjectListField Class within the Home Screen. In a nutshell, MyObjectListField now has three private bitmaps, one per command, and when it’s time to draw the list row, the appropriate bitmap is drawn before the command. This is how the code looks:


title=”Click for expanding..”>Java-Code: MyObjectListField
private class MyObjectListField extends ObjectListField {

        private Bitmap searchIcon = Bitmap.getBitmapResource(resources.getString(KnowledgeBaseResource.IMG_SEARCH));
        private Bitmap tagsIcon = Bitmap.getBitmapResource(resources.getString(KnowledgeBaseResource.IMG_TAGS_LIST));
        private Bitmap recentIcon = Bitmap.getBitmapResource(resources.getString(KnowledgeBaseResource.IMG_VIEW_RECENT));
        private Bitmap icon;          

        // We are going to take care of drawing the item.
        public void drawListRow(ListField listField, Graphics graphics,
                int index, int y, int width) {

            if ( mainMenuItems[index] == mnuSearchTitles) {
                icon = searchIcon;
            }
            if ( mainMenuItems[index] == mnuBrowseTags) {
                icon = tagsIcon;
            }
            if ( mainMenuItems[index] == mnuViewRecent) {
                icon = recentIcon;
            }   

            if (null != icon) {
                int offsetY = (this.getRowHeight() - icon.getHeight())/2;
                graphics.drawBitmap(1,y + offsetY, icon.getWidth(),
                        icon.getHeight(),icon,0,0);
                graphics.drawText(mainMenuItems[index],
                    icon.getWidth() + 2, y, DrawStyle.ELLIPSIS, width - icon.getWidth() + 2);
            } else {
                graphics.drawText("- " + mainMenuItems[index], 0,
                    y, DrawStyle.ELLIPSIS, width - graphics.getFont().getAdvance("- "));
            }

        }
}

Trimming the Cached Articles List

Based on the requirements I set, our application should maintain an in-memory cache with the most recently viewed articles.

The application’s DataStore Class is already capable of handling the storage and retrieval of the cached articles via the setCachedArticles() and getCachedArticles() methods. We also have a way for the user to set the maximum number of cached articles there can be.

What we’re missing is the mechanism to, once a user opens an article, add such article to the cache and prune the cache so the number of articles does not exceed the maximum the user defined. A good place to implement such mechanism is the Article Screen. Let’s add some code that will take care of the possible scenarios:

  1. The cache is empty
  2. The cache has some articles, but it still has room
  3. The cache is full
  4. The article we’re viewing is already cached

When the cache is empty, we only need to add the currently viewed article:


title=”Click for expanding..”>Java-Code: The cache is empty
// Handle the case when there's nothing cached.
if (null == cachedItems || cachedItems.length == 0) {

	cachedItems = new Article[]{article};
	DataStore.setCachedArticles(cachedItems);
	return;

}

When the cache is not empty but still has room, we only need to insert the current article at the top of the list:


title=”Click for expanding..”>Java-Code: The cache is not empty, but still has room
// Handle the case when we need to add one more article to the list.
Article[] newList = new Article[cachedItems.length + 1];

// Insert the old items in the new list.
for (int i = 1; i <= cachedItems.length; i++) {

	// We're shifting the articles too, to leave room at the top of the list
	// for the article we're currently viewing.
	newList[i] = cachedItems[i - 1];

}

// Now, put the article we're viewing at the top of the list.
newList[0] = article;

DataStore.setCachedArticles(newList);

When the cache is full, we have to make room for the for the current article:


title=”Click for expanding..”>Java-Code: Make room for the for the currently viewed item
// Handle the case when the cached need to be trimmed.
Article[] newList = new Article[maxAllowed];
// Insert all the items, except the oldest, in the new list.
for (int i = 1; i < maxAllowed; i++) {

	// We're shifting the articles too, to leave room at the top of the list
	// for the article we're currently viewing.
	newList[i] = cachedItems[i - 1];

} 

// Now, put the article we're viewing at the top of the list.
newList[0] = article;

DataStore.setCachedArticles(newList);

When the article we’re viewing is already cached we just bail out:


title=”Click for expanding..”>Java-Code: The article we’re viewing is already cached
// Bail if the article we're viewing is already cached.
for (int i = 0; i < cachedItems.length; i++) {
	if (article.id.equalsIgnoreCase(cachedItems[i].id)) {
		return;
	}
}

Looks like we took care of all the scenarios, doesn’t it? Well, not quite yet. What happens if the cache has N number of articles and the user, through the Options Screen, changes the maximum number of articles the cache can store to something less than N? To handle this situation we need to add some code to the Options Screen:


title=”Click for expanding..”>Java-Code: trimCachedArticlesList()
private void trimCachedArticlesList() {

        Article[] cached = DataStore.getCachedArticles();

        if (null == cached || cached.length == 0) {
            return;
        }

        int maxAllowed = DataStore.getMaxCachedArticles();

        if (cached.length &lt;= maxAllowed) {
            return;
        }

        Article[] newList = new Article[maxAllowed];

        for (int i = 0; i < maxAllowed; i++) {
            newList[i] = cached[i];
        }

        DataStore.setCachedArticles(newList);

}

And now I think we’re in good shape. If I forgot some detail I’m sure you will let me know. :)

Encoding HTTP Request Data

On the subject of forgetting details, back when I added the HTTP handling code, the routine that took care of creating the HTTP request data looked like this:


title=”Click for expanding..”>Java-Code: createRequestString()
public static String createRequestString(final String[] keys, final String[] values) {

        StringBuffer requestContents = new StringBuffer(&quot;&quot;);
        if (keys != null) {
              for (int i = 0; i < keys.length; i++) {
                 requestContents.append(keys[i] + "=" +  values[i] + &quot;&amp;&quot;);
              }
        }
        // Terminate the request with a valid sequence.
        requestContents.append("0=0\r\n";);    

        return requestContents.toString();
}

Everything seems fine with this code until you start wondering what would happen if any actual values (any of the values[i]) in the request data contained reserved characters like “;”, “/”, “?”, “:”, “=”, “&”. And it can become as serious as it became for me last week when a production application started “randomly” failing because of this encoding issue.

What we need here is to make sure that our request data is correctly encoded so our server-side application can make sense of the request.

Working to fix my last week’s emergency, I stumbled upon net.rim.blackberry.api.browser.URLEncodedPostData. URLEncodedPostData is precisely a class that encodes form data using URL-encoding. Let’s use it to take care of our encoding issues:


title=”Click for expanding..”>Java-Code: createRequestString()
public static byte[] createPostData(final String[] keys, final String[] values) {

        URLEncodedPostData postData = new URLEncodedPostData(URLEncodedPostData.DEFAULT_CHARSET, true);

        if (keys != null) {
             for (int i = 0; i < keys.length; i++) {
                 postData.append( keys[i], values[i]);
             }
         }

         return postData.getBytes();
}

Application “About” Dialog

I thought of the “About” dialog as a nice touch for our application. It is triggered by the “About” menu that I just added to the Home Screen.

Of interest here is the use of ApplicationDescriptor to obtain the application name and the version number:


title=”Click for expanding..”>Java-Code: ApplicationDescriptor usage
private MenuItem aboutMenu = new MenuItem(resources.getString(KnowledgeBaseResource.MNU_ABOUT),150,10) {
       public void run() {
           String crNotice = resources.getString(KnowledgeBaseResource.LBL_ABOUT);
           ApplicationDescriptor descriptor = ApplicationDescriptor.currentApplicationDescriptor();
           String appVersion = descriptor.getName() + " " + descriptor.getVersion();
           Dialog.alert(appVersion + "\n" + crNotice);
       }
};

Alerting Users When Long-Running Operations Take Place

Some of the features of our application, i.e. searching for articles, can potentially involve long execution times. It’s important that we don’t frustrate our users by starting a long-running operation without giving them some visual clue indicating that our program is actually working and they might need to wait some time for an operation to complete.

Some developers prefer to use screens as status indicators, but a simple dialog does just fine.

This is how it’s done:


title=”Click for expanding..”>Java-Code: Status dialog
Bitmap icon = Bitmap.getBitmapResource(resources.getString(KnowledgeBaseResource.IMG_DOWNLOAD));
statusDlg = new Dialog(resources.getString(KnowledgeBaseResource.LBL_DOWNLOADING),null,null,0,icon); 

private void sendHttpRequest(String[] keys, String[] values) {

       String url = DataStore.getAppServerUrl();
       // Make sure we can create an http request.
       // If the app. server URL has not been set, we cannot make any http requests.
        if (null == url || url.length() == 0) {
            Dialog.alert(resources.getString(KnowledgeBaseResource.ERR_INVALID_APP_SERVER_URL));
            return;
        }

        statusDlg.show();

	.
	.
	.
}

public void processResponse(final int HTTPResponseCode, final String data) {
        UiApplication.getUiApplication().invokeLater(new Runnable() {
            public void run()
            {
                statusDlg.close();

	.
	.
	.
}

What’s Next

Having covered the above important details, we still need to write the server-side code to handle incoming HTTP requests, retrieve information from the database and send responses back to the application on the BlackBerry device.

Downloads

Download the source code for this article: KnowledgeBaseBB-7-06-08.zip

How to Build a Real-World BlackBerry Application (Part 4)

For the past three posts I’ve been walking you through the creation of an end-to-end BlackBerry application that will serve as a mobile front-end to my Knowledge Base sample web application.

In the third part of this series I finished the areas of the application that store and retrieve data from the device’s memory. Together with storing data on the device, the ability to use the network is vital for most applications. Today I will be showing you how the application will communicate with its server-side service.

But first let’s do a little refactoring.

The Options Class is now the DataStore Class

Yes, after working with the Options Class for a while I decided that, since it not only deals with application settings, a better name for it would be DataStore. “DataStore” explains better the intent of the class.

Making HTTP requests

There is a plethora of information regarding HTTP connections. I will leave most of it out of this article and focus only on what’s strictly needed for our application to be able to send HTTP requests and consume HTTP responses.

Two things I should mention are the javax.microedition.io.HttpConnection Interface, which defines the necessary methods and constants for an HTTP connection, and javax.microedition.io.Connector, the Factory Class for creating connections

For my networking tasks I have reused and adapted some code that I obtained from the existing BlackBerry sample code online. The bulk of the HTTP handling code will conform to contracts defined in two separate interfaces HTTPTransport and HTTPTransportListener.

HTTPTransport Interface and the KbHTTPTransport Class

HTTPTransport is an interface that defines the methods for creating HTTP requests.


title=”Click for expanding..”>Java-Code: HTTPTransport
001/**
002 * Defines the methods to send HTTP requests.
003 */
004public interface HTTPTransport {
005
006    public void send(final String requestMethod,
007        final String URL, final String requestData);
008    public void send(final String requestMethod,
009        final String URL, final String requestData,
010        final String[] headerKeys, final String[] headerValues);
011    public void setHTTPTransportListener(HTTPTransportListener t);
012    public void removeHTTPTransportListener();
013
014}

KbHTTPTransport is a helper class which can make HTTP requests by implementing the methods defined in HTTPTransport. KbHTTPTransport will notify an attached HTTPTransportListener with the response to the request. HTTPTransportListener is an interface that defines the methods a class must have in order to process the response from an HTTP request.

Implementing HTTPTransportListener inside the Articles Screen

So far, the only place in the application where there’s a need to send HTTP requests is the Articles Screen. Implementing HTTPTransportListener enables our Articles Screen to process HTTP responses:


title=”Click for expanding..”>Java-Code: HTTPTransportListener implementation
001
002 class ArticlesScreen extends MainScreen implements HTTPTransportListener {
003
004	.
005	.
006	.
007
008    public void processResponse(final int HTTPResponseCode, final String data) {
009        UiApplication.getUiApplication().invokeLater(new Runnable() {
010            public void run()
011            {
012                switch (HTTPResponseCode) {
013
014                    case (KbHTTPTransport.NOT_IN_COVERAGE):
015                        Dialog.alert("Not in coverage.");
016                        break;
017                    case HttpConnection.HTTP_OK:
018                        parseResponseData(data);
019                        break;
020                    // TODO: Check all the http error codes you are interested in.
021                    // for example HttpConnection.HTTP_FORBIDDEN
022                    default:
023                    Dialog.alert("There was an error with the request.");
024                    break;
025
026                    }
027            }
028        });
029
030    }
031 

Choosing a transmission format

From the multiple formats for transmitting serialized data over the net, namely xml, binary, etc, I decided to send and receive the data in the form of strings, where the contents of a response are a custom-formatted string that represents a list of articles.

A formatted list of articles would look like this

id^~^title^~^dateCreated^~^author^~^tag1,tag2,...^~^contents~^~

where the sequence “^~^” separates the fields of an article, and the sequence “~^~” separates one article from the next.

Notice how this is a pretty simple format that is both easy to use and light in terms of the number characters transmitted (think about how verbose XML is).

parseResponseData() is where we de-serialize the response string and create a list of Article instances


title=”Click for expanding..”>Java-Code: parseResponseData
001
002    private void parseResponseData(String data) {
003
004        // Parse out each article from the string data
005        // Format: id^~^title^~^dateCreated^~^author^~^
006        //tag1,tag2,...^~^contents~^~<NEXT RECORD>
007
008        Vector articlesVector = new Vector();
009        int index = 0;
010        int length = data.length();
011        while (index != -1 && index < length - 1){
012
013            if (index == 0) index = -1;
014
015            Article article = new Article();
016
017            article.id = data.substring(++index ,
018                    index = data.indexOf(FIELD_SEPARATOR, index));
019            index += 3;
020            article.title = data.substring(index ,
021                    index = data.indexOf(FIELD_SEPARATOR, index));
022            index += 3;
023            article.dateCreated = data.substring(index,
024                    index = data.indexOf(FIELD_SEPARATOR, index));
025            index += 3;
026            article.author = data.substring(index,
027                    index = data.indexOf(FIELD_SEPARATOR, index));
028            index += 3;
029            String tags = data.substring(index,
030                    index = data.indexOf(FIELD_SEPARATOR, index));
031            article.tags  = StringUtilities.stringToWords(tags);
032            index += 3;
033            article.contents = data.substring(index,
034                    index = data.indexOf(RECORD_SEPARATOR, index));
035            index += 2;
036            articlesVector.addElement(article);
037        }
038
039        articles = new Article[articlesVector.size()];
040        articlesVector.copyInto(articles);
041        articlesList.set(articles);
042    }
043 

Testing the networking code

At this point in time I need to be able to test my networking code without the presence of the server side code (it doesn’t exist yet). In order to achieve this I have built an implementation of HTTPTransport, MockHTTPTransport, which creates different kinds of responses that simulate the scenarios that could occur when working with HTTP requests – timeouts, failed authentication, etc.


title=”Click for expanding..”>Java-Code: MockHTTPTransport
001
002 /**
003 * Helper to test the network functionality in the Articles Screen without
004 * having a server side application.
005 */
006 class MockHTTPTransport implements HTTPTransport {
007
008    private HTTPTransportListener listener = null;
009
010    MockHTTPTransport() {    }
011
012    public void setHTTPTransportListener(HTTPTransportListener t){
013        listener = t;
014    }
015
016    public void removeHTTPTransportListener(){
017        listener = null;
018    }
019
020    public void send(final String requestMethod, final String URL,
021        final String requestData){
022        send(requestMethod, URL, requestData, null, null);;
023    }
024
025    public void send(final String requestMethod, final String URL,
026        final String requestData, final String[] headerKeys,
027        final String[] headerValues) {
028
029        // Since this is just for testing purposes, 
030        // in here we will return a list or articles, 
031        // as if we had just gotten them via an http request.
032        createArticlesListResponse();
033
034    }
035 


title=”Click for expanding..”>Java-Code: createArticlesListResponse()
001
002    private void createArticlesListResponse() {
003        // Create the articles.
004        Article[] articles = new Article[15];
005        Article article;
006        for (int i = 0; i < 15; i++) {
007          article = new Article();
008          article.id = String.valueOf(i);
009          article.title = "Dummy article " + Integer.toString(i);
010          article.author = "ramonj";
011          article.contents = "This is a test article";
012          article.tags = new String[] {"tag 1", "tag 2", "tag 3"};
013          article.dateCreated = "01/01/2008";
014          articles[i] = article;
015        }
016        String FIELD_SEPARATOR = "^~^";
017        String RECORD_SEPARATOR = "~^~";
018        //Create the the simulated response data 
019        //with the information from the articles.
020        StringBuffer response = new StringBuffer();
021        for (int i = 0; i < articles.length; i++) {
022            article = articles[i];
023            StringBuffer tags = new StringBuffer();
024            for (int j = 0; j < article.tags.length; j++) {
025                tags.append(article.tags[j] + ",");
026            }
027            // Remove the last ","
028            tags.deleteCharAt(tags.length() - 1);
029            // Format: id^~^title^~^dateCreated^~^author^~^
030            //tag1,tag2,...^~^contents~^~<NEXT RECORD>
031            response.append(article.id + FIELD_SEPARATOR +
032                article.title + FIELD_SEPARATOR +
033                article.dateCreated + FIELD_SEPARATOR + article.author +
034                FIELD_SEPARATOR + tags + FIELD_SEPARATOR + article.contents +
035                RECORD_SEPARATOR);
036        }
037        int httpResponseCode  = HttpConnection.HTTP_OK;
038        // Introduce a delay to simulate latency.
039        try {
040            Thread.sleep(1500);
041        } catch (InterruptedException ex) {}
042        listener.processResponse(httpResponseCode,response.toString());
043    }
044
045 

What’s next

The next article of this series will be dedicated to the server side of the application. On the server side I will put together the code to handle incoming HTTP requests, retrieving information from the database and sending responses back to the application on the BlackBerry device.

Downloads

Download the source code for this article: KnowledgeBaseBB-6-24-08.zip

How to Build a Real-World BlackBerry Application (Part 3)

This is the third part of a series of articles where I am walking you through the creation of an end-to-end BlackBerry application that will serve as a mobile front-end to my Knowledge Base sample web application.

In my previous article of this series I finished building the screens that serve as the application’s user interface. I also added some test code in order to test the interface against some basic usage scenarios.

In this article I will cover the subject of how to store and retrieve data from the device’s flash memory. This is a very important subject since most applications have no value without the ability to preserve some state across device resets.

What data do we need to save?

  1. The URL of our application server
  2. A list of recently viewed articles
  3. The maximum number of recently viewed articles the above list should contain

Items 1 and 3 are application settings and their storage and retrieval will occur within the context of the Options Screen

The list of recently viewed articles will be built as the user opens articles. It will be committed to memory upon application shutdown.

Storing Data Using the Persistent Store

The BlackBerry API provides for persisting information across device resets through the Persistent Store (PersistenStore Class). Persistent objects (PersistentObject Class) are objects whose contents can persist across device resets. These objects (in the form of key-value pairs) can be committed to the persistent store and later retrieved via the key. Here’s a sample usage of the persistent store taken from the BlackBerry API documentation

Options Class

The Options Class encapsulates all the code related with storing and retrieving the data we need to persist across device resets. The class constructor will be in charge of retrieving our application’s persistent object from the persistent store like so

The constructor is private in order to reinforce a singleton behavior that will prevent the existence of multiple instances of our application’s store being worked with at the same time.

The number 0xf6354ee14c6cc857 is a hash of “KnowledgeBase”. You can obtain this hash by selecting the package name at the top of the file, in this case “KnowledgeBase”, right-clicking and choosing the [Convert “KnowledgeBase” To Long] menu item.

The object that I chose to serve as container for the application state that needs to be persisted and that in turn will be contained by the Persistent Object instance that we will commit to the persistent store is a LongHashtableCollection, which is a Hashtable collection using long integers as keys.

Here’s a diagram that will help you visualize how our data will be stored in memory

I created a couple of private methods set(long key, Object value) and get(long key) that will directly deal with setting and getting the contents of the persistent store

Each distinct piece of data (application setting, etc.) to commit to the store will be identified by a unique key

And based on these pieces of data, these are the methods that consumers of the Options Class can use

Options Screen

Within the Options Screen, displaying and saving the application settings is pretty straightforward. These operations are handled by displayOptions() and saveOptions()

Note how saveOptions()does a simple validation of the data before committing it to memory via our Options Class.

Articles Screen

Let’s modify the test code within the ActiclesScreen class’s constructor to take advantage of our Options class ability to save and retrieve a list of recently viewed articles. Before, our test code just created a list of dummy articles in order to display them on the screen

Now, let’s check if there are any articles cached and if not, create our dummy articles and commit them to the device’s memory

The last item for this article is a very important one and has to do with the fact that any objects that we’d like to commit to the Persistent Store have to implement the net.rim.device.api.util.Persistable interface. Since we are storing instances of the Article Class as a way to persist a list of recently viewed articles across device resets, the Article Class must explicitly implement this interface. Here’s the code

What’s next

Well, this is it for now. In the next article of this series I will add the networking code. This will pretty much take care of the device-side code and set the stage for moving to the server side. On the server side, I will put together the pieces that will handle the communications with the device.

Downloads

Download the source code for this article: KnowledgeBaseBB-6-04-08

How to Build a Real-World BlackBerry Application (Part 2)

In the first article of this series I started walking you through the creation of an end-to-end BlackBerry application that will serve as a mobile front-end to my Knowledge Base sample web application.

The requirements for the mobile application are pretty simple

  1. Searching a collection of articles stored in a knowledge base repository,
    • By title
    • By tags
  2. View an article. The article’s visible attributes are
    • Title
    • Body
    • Tags, as a way to connect the article to specific topics
    • Author’s name
    • Date published

And my building blocks look like this

Implementation

Previously I finished the Application Class and the Home Screen

I will continue now with the rest of the screens.

Tags Screen

The Tags Screen displays a list of the existing tags in the database. Beside each tag there will be a count of the articles the tag applies to.

Search Screen

This screen will allow our users to initiate an articles search by typing one or more words belonging to the article’s title.

The searchArticles function is present in both the Tags Screen and the Search Screen and so far it only pushes the Articles Screen to the top of the stack. Later I will add the code that will request my server-side handler to issue the database query and return any results.

Articles Screen

The Articles Screen shows a list of articles that satisfy the criteria entered on the Search Screen. It can also show a list of recently viewed articles. Clicking on any listed article will bring the Article Screen to the top of the stack.

As I’m still missing the network routines, I created a few dummy articles in order to test the look and feel of the Articles Screen.

The Article Class is listed below. Note that I’m not paying a lot of attention to encapsulation, since the usage of this class will be restricted to only a few places in the application.

Article Screen

The Article Screen shows the viewable attributes of the article that was selected on the Articles Screen. This is where the user get’s to read the article. This is another place where I use the Article Class shown above.

Options Screen

Finally, the Options Screen allows the user to change the application settings. In terms of settings, so far I can only think of the URL our application will connect to in order to talk to its server counterpart and the number of references to recently viewed articles to keep cached on the device.

What’s next

In the next article of this series I will add the networking code, as well as the code to save and retrieve the application settings. After this, I will move to the server side and take care of the pieces that will handle the communications with the device.

Downloads

Download the source code for this article: KnowledgeBaseBB-5-20-08

How to Build a Real-World BlackBerry Application

Quite a few readers have requested more information about development for BlackBerry devices. In this series of posts I will walk you through the creation of an end-to-end application that will be a BlackBerry version of the web application I talk about in these articles: End-to-end ExtJS application (Part 1) and End-to-end ExtJS application (Part 2).

In case you haven’t read the articles, the web application I built is a very simple Knowledge Base System. These are the basic usage scenarios I had established for it

  1. Browsing a collection of articles stored in a knowledge base repository
  2. Creation, edition or deletion of articles (any user can view, create, edit and delete any articles),
  3. View an article. The article’s visible attributes are
    • Title
    • Body
    • Tags, as a way to connect the article to specific topics
    • Author’s name
    • Date published

Requirements

For the BlackBerry application, I will skip the creation, edition and deletion of articles and focus on browsing and viewing existing articles. So, my first take at the usage scenarios produces this list

  1. Searching a collection of articles stored in a knowledge base repository,
    • By title,
    • By tags
  2. View an article. The article’s visible attributes are
    • Title
    • Body
    • Tags, as a way to connect the article to specific topics
    • Author’s name
    • Date published

Building Blocks

Besides the BlackBerry application, I will use a .NET http handler on the server side, to channel all communications between the device and the articles database.

User Interface

I’ve found that when I enter the construction phase on a project of this kind, it always helps me if I have an idea of how the user interface is going to look. Keeping my “product owner” hat on, I am going to help my coder alter ego by putting together a few rough UI prototypes.

First comes the Home Screen. This will be the main screen of the application and I expect it to be a door into the different search features that will be available as well as the application settings.

Now to the Search Screen. This screen will allow our users to initiate an articles search by typing one or more words belonging to the article’s title.

The Browse Tags Screen will display a list of the existing tags in the database. Beside each tag there will be a count of the articles the tag applies to.

The Results Screen will show a list of articles that satisfy the criteria entered on the Search Screen. It will also allow our users to click on any listed article in order to view it.

The Article Screen will show the viewable attributes of the article that was selected on the Results Screen. This is where the user get’s to read the article.

The Options Screen will allow the user to change the application settings. In terms of settings, so far I can only think of the url our application will connect to in order to talk to its server counterpart, and the number of references to recently viewed articles to keep cached on the device.

Implementation

It looks like I can switch to “coder” mode and get started writing our device-side code. I will first take care of creating a stripped-down version of the application that does nothing but display the main user interface elements. This will allow me to validate my UI prototypes and serve as a foundation I can build upon later when I have to add the networking routines and the code that will take care of loading and saving the application settings. In this post I will create the Application Class and the Home Screen. I will tackle the rest of the screens in my next article.

The Development Environmet

The IDE I will be using is the BlackBerry JDE version 4.3.0. You can download the IDE as well as its documentation from the BlackBerry developers website.

The Application Class

Let’s begin with the Application Class. This class will be the entry point into our application and will be in charge of creating the Home Screen.

Worth highlighting is the constructor of the Class, which is where I create an instance of the Home Screen and push it to the display stack.

Home Screen

The Home Screen displays a list of search options.

One interesting detail here is that I’m extending the ObjectListField Class in order to be able to add a small icon to each of the search options.

The navigationClick method is where I’m going to determine what search option will be displayed.

What’s next

This is it for now. In my next article of this series, I will build the rest of the screens and lay the foundation for adding the networking code as well as the code to save a retrieve the application settings. Once I cover the device-side code, I will move to the server side and take care of the pieces that will handle the communications with the device.

Downloads

Download the source code for this article: KnowledgeBaseBB-4-23-08