|
|
||||||||||||||
by Edward Lineberry | ||||||||||||||
| ||||||||
Research in Motion's 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 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 section of this article, so building and running the sample application should be easy.
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.

Figure 1. Input fields
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.
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.
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.
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.

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.
Edward Lineberry is a Senior Consultant for Simplified Technology Solutions in Atlanta, Georgia.
View all java.net Articles.
Showing messages 1 through 18 of 18.
|
|