Skip to main content

An Introduction to BlackBerry J2ME Applications

January 24, 2006

{cs.r.title}









Contents
Building a User Interface
Listening for Events
Other UI Considerations
Establishing a Network Connection
Displaying the Results
Conclusion
Resources

Research in Motion's "http://www.blackberry.com">BlackBerry devices and architecture
are commonplace in enterprise infrastructures, but beyond standard
functions like email and calendaring, the platform goes largely
underutilized. For the average Java developer--even one
with no experience in J2ME--writing applications for the
BlackBerry is fairly easy. In this article, I will give an overview
of building a simple user interface, and, because networking is the
very heart and strength of the BlackBerry platform, how to transmit
data through the BlackBerry Enterprise Server to a CGI servlet.

The example application used in this article is a simple
problem-reporting application that a service technician could use
to create trouble tickets for computer problems. Issues reported
from the mobile device would be stored on the server and centrally
accessible. My goal is to show that developing useful BlackBerry
applications for custom business processes can be simple and easy.
Though they provide the basic building blocks of a full-featured
application, the examples used in this article are just a starting
point.

Getting started with BlackBerry development means getting used
to the "http://www.blackberry.com/developers/downloads/jde/index.shtml">BlackBerry
Java Development Environment
provided by Research in Motion.
Though it lacks many of the features of the better IDEs available
to Java developers, the packaging and debugging conveniences that
it does offer make it all but required. The good news is that the
BlackBerry JDE can be freely downloaded from the blackberry.com
website and it contains everything you will need to create J2ME
applications for the BlackBerry, including a device emulator. The
BlackBerry JDE is Windows-only, and though it may be possible to
develop applications on other platforms, the emulator and debugger
will not be available. I won't go into using the JDE in depth, but
a full workspace file is provided in the "#resources">Resources section of this article, so building and
running the sample application should be easy.

Building a User Interface

In our application, we will create three Java classes:
DataCapture, DataCaptureScreen, and
ConnectionThread. The DataCapture class
is the main class of the application and does little other than
instantiate the UI class and the networking class.


screen = new DataCaptureScreen(); 
pushScreen( screen );

Our application extends UIApplication--the base
class for all BlackBerry applications that have a user interface--and the pushScreen() method makes our UI active. In
the case of our example application, there is only one screen.
However, the UIApplication class contains a stack of
screens. To display a new screen, simply invoke
pushScreen() to push it onto the stack. When
popScreen() is called, the new screen closes and the
next one on the stack is displayed.

Everything the user sees and interacts with is contained in our
DataCaptureScreen class. The constructor handles
instantiation of all of the UI elements. Once these have been
created, they work as expected, with no additional programming
required. Developers familiar with Swing or AWT programming will be
in comfortable territory. It is possible to create MIDP
applications that run on devices other than the BlackBerry, but the
BlackBerry API provides a host of classes that allows developers to
take full advantage of the platform. For applications that will be
deployed only on the BlackBerry, the device-specific APIs should
be used. This is especially true for UI elements, as users will
expect the application to behave in a ways similar to the standard
applications deployed to the device.

For most types of user input, there is a corresponding field or
field filter. The DateField class presents the user
with an input that can be changed using the space bar and scroll
wheel to select the desired state and time.

 
DateField dateTimeField = 
    new DateField("Date: ", System..currentTimeMillis(), 
    DateField.DATE_TIME);

In this constructor, the field is instantiated with the current
date and time through the second argument. This first argument is
the label for the field, which displays on the same line. The third
argument to the constructor is the style for this field. Passing
DateField.DATE or DateField.TIME will
create a field for date-only or time-only entry, respectively.

The other fields on the screen provide similar arguments, such
as the field label passed in first, and are created in much the
same way as the DateField.


private ObjectChoiceField category = 
    new ObjectChoiceField("Category:", 
    new String[] 
    { "Hardware", "Software", "Network" });

private AutoTextEditField user =
    new AutoTextEditField("User:", "");

private BasicEditField phone = 
    new BasicEditField("Contact #: ", "", 10,
    EditField.FILTER_PHONE);

private AutoTextEditField notes =
    new AutoTextEditField("Notes:", "");

The ObjectChoiceField provides an interface similar
to a drop-down menu within a web browser. Users can cycle through
the list by clicking the space bar, which allows for fast and
reliable data entry. The AutoTextEditField is for
standard text entry. It differs from the
BasicEditField in that any data entry shortcuts
defined on the device are respected when the user types within this
field. Also, the initial letter is capitalized.

The field defined for entry of a phone number begins as a
BasicEditField, but two restrictions are placed on it
through the third and fourth arguments.

 
private BasicEditField phone =
    new BasicEditField( "Contact #: ","", 10, 
    EditField.FILTER_PHONE);

The third argument is the field length. The fourth argument is
the field "style," a set of constants that restrict the data that
can be entered into the field. Creating a field using the
EditField.FILTER_PHONE argument restricts the
characters for that field to numerals, dashes, parentheses, and the
"x" character. This is especially handy on the BlackBerry, as most
devices use the same keys for numbers as for letters. Using
entering data into a field that only accepts numbers, these keys
are automatically translated to input numbers without forcing the
user to press the Shift key. A variety of other filters and styles
are available, and it is recommended that the developer take
advantage of them when appropriate. Field styles make user input
faster and more reliable, and can make data validation easier for
the developer.

Figure 1 shows these fields as rendered by the emulator.

Application Screen Shot
Figure 1. Input fields

Listening for Events

The last element in our user interface is the button for sending
the data.


private ButtonField sendButton = new ButtonField("Send");

Now that the DataCaptureScreen has the appropriate
elements as instance properties, all that is left is to put them on
the screen; a task handled by the constructor.


setTitle("Data Capture");
add(dateTimeField);
add(category);
add(user); 
add(phone); 
add(notes); 
add(new SeparatorField()); 
FieldListener sendListener = new FieldListener();
sendButton.setChangeListener(sendListener);
add(sendButton);

As the DataCaptureScreen class extends the
MainScreen class, it inherits the methods necessary
for placing components on the screen. More complex and
sophisticated layout managers are available, but the simple
vertical layout manager of the MainScreen class is enough for most
uses. Each field is placed on a new line, beneath the one before it.
Labels are left-justified; fields are right-justified.

The final piece of our example user interface is the
ButtonField and the associated
FieldChangeListener, which is implemented as an inner
class.


class FieldListener implements 
    FieldChangeListener {
        public void fieldChanged(Field field,
            int context) {
                //button action
    }
}

Invoking setChangeListener() on the
ButtonField activates the button in the user
interface. It's possible to have multiple buttons using the same
FieldChangeListener interface. In the case of our
example, we have only one, but simply testing for equality between
the Field argument in the fieldChanged() method and
the instance of the field or button will determine which registered
field has changed.

Other UI Considerations

The default close behavior for classes that extend
MainScreen is to present a save dialog box. Because
our application has no concept of persistence, we suppress the
dialog by overriding onClose(), something you'll want
to do most of the time.

Also, because the example application has only a single action,
one button works well. In many instances, you will want to make use
of the context menu, which is available to users on the device by
depressing the scroll wheel. This menu makes actions accessible
from anywhere on the screen, just as right-clicking with the mouse does
in a desktop environment. Given the small screen, buttons
can quickly clutter the user interface. The menu is more desirable
for screens with multiple actions or navigation options.

Establishing a Network Connection

Now that the user has entered the information into the user
interface and pressed the Send button, our
ConnectionThread class will handle transmitting the
data across the network. In an environment using the BlackBerry
Enterprise Server, this connection can take place "behind the
firewall." The wireless transmission from the device is encrypted,
and the BES can connect to intranet servers not exposed to traffic
from the public internet. In a real-world application, the
https protocol might be a better choice, not only
because it provides additional security, but also because it
provides authentication, allowing the receiving server to know who
sent the data.

Custom BlackBerry applications that attempt network connections
display a prompt to the user before opening the connection.
However, only one thread may have access to the user interface at a
time on a BlackBerry device. If a connection is made from the
MainScreen thread, the screen will be locked and the
user will not see the prompt. The networking thread in the example
application runs in an infinite loop, checking each time for a
change in the Boolean start or stop class properties. The interface
to this class comes in the post() method.


public void post(String url, String data) {
    this.url = url;
    this.data = data;
    sendResult = false;
    sending = true;
    start = true;
}

The class properties in the ConnectionThread

instance are set with the arguments. With our URL and data in
place, the run() method detects that
start is now true and makes the network
connection.


private void httpPost() {
    HttpConnection conn = null;
    OutputStream out = null;
    int responseCode;

    try {
        conn = (HttpConnection) Connector
            .open(url);
        conn
            .setRequestMethod(
            HttpConnection.POST);
        out = conn.openOutputStream();
        out.write(data.getBytes());
        responseCode = conn.getResponseCode();

        if (responseCode != 
            HttpConnection.HTTP_OK) {
            sendResult = false;
        } else {
            sendResult = true;
        }

        start = false;
        sending = false;

        } catch (IOException e) {
            start = false;
            sendResult = false;
            sending = false;
    }
}

We use the Connector class to get our
HttpConnection. This is a factory class that handles
the device-specific networking issues and returns an
HttpConnection without the developer having to worry
about the details. The Connector class has powerful
features for controlling the network connection, but the defaults
will work in most cases. If the device is outside of network
coverage, or otherwise unable to connect to the server, the user
must try again later. In a real-world application, the data could
be persisted and sent at a later time. Posting the data to the URL
works the same as in J2SE, but getting the results is a little more
difficult on the BlackBerry because of the threading issues.

Displaying the Results

The MainScreen class watches the
ConnectionThread until it is through sending, then
reads the result and displays a pop-up message. A
"Sending..."message is displayed to the user, as seen in Figure 2,
so that the device does not appear to be frozen.

Sending Dialog
Figure 2. "Sending" dialog


while (connThread.sending) {
    try {
       Status.show( sb.append(".").toString() );
        Thread.sleep(100);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

if (connThread.sendResult) {
     Status.show("Transmission Successful");
} else {
     Status.show("Transmission Failed");
}

Each thread has its own responsibility. In this case, the
application waits for the connection to succeed or fail, but it's
possible to allow the user to continue to work while the networking
thread attempts to connect.

Conclusion

The power and usefulness of mobile devices lies in the ability to
extend existing applications beyond the desktop or browser. With
the BlackBerry, this power comes standard with regard to email and
calendar. However, developers can bring many more useful tasks to
network-connected mobile devices. Though J2ME and the BlackBerry
API may be unfamiliar to some, I hope that this article shows that
building custom applications for BlackBerry devices does not have
to be difficult.

Resources

width="1" height="1" border="0" alt=" " />
Edward Lineberry is a Senior Consultant for Simplified Technology Solutions in Atlanta, Georgia.
Related Topics >> Mobility   |   Programming   |   

Comments

Hi Edward, I have followed

Hi Edward, I have followed your Tutorial: Web Services in BlackBerry J2ME Applications from the Link http://www.simplified-tech.com/website/webapp.nsf/webpages/ArticlesBBWeb... . I used the same web service that you have used, but unfortunately I could get no result from the Web service. When I checked the URL in browser I got a the following response: <?xml version="1.0" encoding="utf-8" ?> Error occured when translating text please contact support@webservicex.net Please provide me a way to solve the problem. Regards, krishnan.