October 22, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Building a Simple BlackBerry Application Interface

  • August 14, 2008
  • By Jeff Langr
  • Send Email »
  • More Articles »

Listing 2: TestApp.

package com.langrsoft.app;

import net.rim.device.api.system.*;
import net.rim.device.api.ui.*;
import net.rim.device.api.ui.component.*;
import net.rim.device.api.ui.container.*;
import com.langrsoft.bbtest.*;

public class TestApp extends MainScreen
   implements ResultListener {
   private ListField list = new ListField();
   private TestListFieldModel model = new TestListFieldModel();

   public TestApp(final MicroTestGroup group) {
      list.setCallback(model);

      add(list);

      group.setListener(this);
      new Thread(new Runnable() {
         public void run() {
            group.execute();
         }
      }).start();
   }

   public void ran(final MicroTest test) {
      UiApplication.getUiApplication().invokeLater(new Runnable() {
         public void run() {
            list.insert(0);
            model.insert(test);
         }
      });
   }

   protected void onObscured() {
      UiApplication.getApplication().requestForeground();
   }

   public boolean keyChar(char key, int status, int time) {
      if (key == Characters.ESCAPE) System.exit(0);
      return false;
   }
}

The TestApp class is a subclass of MainScreen. This means that TestApp can be pushed onto the application stack, and will be rendered to produce a visible interface. The TestApp class implements the ResultListener interface, and calls setListener to register itself with the MicroTestGroup. As tests execute, the unit test framework invokes callback method ran, passing in the MicroTest object.

The ListField Control

I chose a ListField as the presumably simplest control to show the list of passing or failing unit tests. It turns out that the ListField is a bit more involved. A ListField requires a callback object, one that will manage and draw the underlying data that the ListField presents. The ListField callback must implement the ListFieldCallback interface, which declares four methods: drawListRow, get, getPreferredWidth, and indexOfList.

I'll detail the ListFieldCallback interface methods shortly. For now, you can look at Listing 3, which contains my implementation of the interface, TestListFieldModel.

Here's a step-through of the code in the TestApp constructor:

  • Set the callback on the ListField object to an instance of TestListFieldModel.
  • add the list to the MainScreen. This adds the user interface component to the screen so that it will be visible when the screen is rendered.
  • Register this TestApp instance as the ResultListener on the MicroTestGroup object.
  • Create and start a separate thread to execute tests on the MicroTestGroup object.

When the callback method ran gets invoked, its job is to add the test to the list. Two steps are required: First, the code calls insert on the ListField object (list) to grow its size by one. Second, the test object is passed to the ListFieldCallback (which I have named model). Using invokeLater allows this code to properly execute on the application's event queue.

The keyChar method hook allows the TestApp object to trap character events from the BlackBerry. In this case, I exit the application if the user presses the escape key.

The ListFieldCallback (see Listing 3) has two primary jobs: to manage the list of tests, and to draw a given list row entry. The drawListRow method gets called for each row that must be painted. Code in drawListRow first calls get, which returns the MicroTest at the appropriate index from the tests Vector. Using the Graphics object, the code then sets an appropriate color (green for a passing test, red for a failing test), and then draws some text at the coordinate x=0, y=the y coordinate of the current row in the ListField.

The indexOfList method is designed to support the user doing a text search against the contents of the list. Because this is intended to be a minimal implementation, I've not yet implemented any real functionality in this method. The same thing applies to getPreferredWidth, I'm not yet worried about what this method should return. It works (see Figure 2)—that's all I care about for now.

Automatically Running the Test Application

When in development mode, I want my unit tests to show automatically when the BlackBerry simulator starts up. Accomplishing this goal requires two steps. First, the secondary application (the one with the alternate entry point) must be configured to "autorun." The setting is found in the BlackBerry Project Properties under the Application tab, where you'll find a checkbox labeled Auto-run on startup (refer to Figure 1). Second, the application must be configured to come to the foreground; otherwise, it will execute in the background by default (which means you won't be able to see it). A one-line implementation of the callback method onObscured is all that's needed—simply tell the UiApplication singleton object to requestForeground.

Figure 2: The quick & dirty BBTest user interface.





Page 2 of 3



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel