Embedding the address book into your application
Now that you have some test data in the address book it’s time to use it. The purpose of
the TimeOff application is to provide a way for an employee in the field to request time
off . In order to do this, the application will collect an e-mail address, beginning and ending
dates, and a reason for the request through four fields on the screen. When the request
is submitt ed through the menu item the application uses these pieces of information to
compose an e-mail message that will be sent to the manager by using the e-mail
address provided.
As we already have a field for the e-mail address, wouldn’t it be nice to be able to allow the
user to pick the e-mail address to use from the address book instead of requiring them to
re-enter it by hand?
You already went over how to get the ContactList from the PIM object. You could create a
screen and list all of the contacts on the screen, but this could be quite a long list that would
take up a lot of processing time and memory. There are some other techniques you could
use to display only a limited list, but even if you went through all of that work you still would
be lacking several key pieces of functionality such as searching or even adding a new contact
on the fl y. In short, you would almost be reimplementing the AddressBook application!
Wouldn’t it be bett er to just reuse the address book?
Good news, you can do that! The AddressBook application has exposed an interface
that lets you leverage it, so you don’t have to solve all of those problems a second time. In
addition to saving a ton of work, it also helps to provide a consistent user interface that will
be familiar and easy to use.
Time for action – embedding the address book
- You first start by overriding the makeMenu method . With this
method you can display the menu to access the Address Book
application only when the e-mail field is selected. - Then, we need to implement the Run method of the _AddressBookAction menu
item.
if (this.getFieldWithFocus() == _To &&
context != Menu.INSTANCE_CONTEXT_SELECTION)
{
m.add(_AddressBookAction);
}
PIM pim = PIM.getInstance();
try
{
BlackBerryContactList contacts =
(BlackBerryContactList)pim.openPIMList(PIM.CONTACT_LIST,
PIM.READ_WRITE);
BlackBerryContact selected = (BlackBerryContact) contacts.
choose();
if (selected != null)
{
int EmailAddressCount = selected.countValues(Contact.EMAIL);
// check to make sure that there is an Email address for
this contact.
if ( EmailAddressCount > 0)
{
String selectedEmail;
// If there is more than just one email, display a
dialog to choose
if (EmailAddressCount > 1)
{
String[] Addresses = new String[EmailAddressCount];
int[] Values = new int[EmailAddressCount];
for (int i= 0; i< EmailAddressCount; i++)
{
Addresses[i] = selected.getString(Contact.EMAIL, i);
Values[i] = i;
}
Dialog dlg = new Dialog("Select which address to use.",
Addresses, Values, 0,
Bitmap.getPredefinedBitmap(Bitmap.QUESTION));
int selectedAddr = dlg.doModal();
selectedEmail = Addresses[selectedAddr];
}
else
{
selectedEmail = selected.getString(Contact.EMAIL, 0);
}
TimeOffMainScreen theScreen =
(TimeOffMainScreen)UiApplication.getUiApplication()
.getActiveScreen();
theScreen._To.setText(selectedEmail);
}
}
}
catch (PIMException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
What just happened?
The first part of this is all about making the menu item appear when the users want it to be
shown, and not when they don’t. It makes sense that when the Email field has focus, the
menu will be shown in the list. When any of the other fields are selected, the user probably
doesn’t care about selecting an e-mail address from the Address Book application and so the
menu should be hidden. By adding a litt le bit of logic to the already understood makeMenu
method you can see how you can improve the user experience simply by choosing to hide or
show menu items when it is appropriate.
The standard BlackBerry applications do this oft en and eff ectively in every application on the
handheld. It is an established patt ern that you as a developer should give conscious thought
to and follow.
The next step of this is much more involved with several parts. The first part is just about
setting up the PIM object and getting the ContactList (which we’ve done in the previous
section). The real magic happens with this simple line of code:
BlackBerryContact selected = (BlackBerryContact) contacts.choose();
The choose method is rather nondescript and plain, but this simple method is the exposed
functionality that will display the address book list and prompt the user to select a contact.
All of the functionality of the AddressBook is available, including searching by typing a
contact name and even adding or modifying an existing contact, and it’s been optimized to
be fast and memory efficient.
There are a number of menu items that are NOT present, such as those allowing you to
compose messages or initiate calls. As you can see, a lot of thought went into this screen
and you should all be thankful that the choose method is available and is able to be reused.
It’s not perfect though, and there are several limitations. For instance, you can’t provide any
parameters at all to the method so you can’t specify that you want addresses only with an
e-mail address to be shown, for instance.
Any contact may be selected, and as a result you must handle any situations where the
selected contact does not have the information that you desire. In this case, you are
interested in collecting only an e-mail address from the contact so you must check to make
sure that it has one.
int EmailAddressCount = selected.countValues(Contact.EMAIL);
// check to make sure that there is an Email address for this contact.
if (EmailAddressCount > 0)
{
…
}
else
{
Dialog.alert(“This contact has no Email Addresses.”);
}
Once you are sure that the contact has at least one e-mail address you need to further
examine how many addresses the contact does have. Remember that a contact can have
up to three e-mail addresses. If there is just one, then it is very easy to know which one to
use. However, if a contact has more than one then the user needs to choose which of them
should be used.
String selectedEmail;
// If there is more than just one email, display a dialog to choose
if (EmailAddressCount > 1)
{
…
}
else
{
selectedEmail = selected.getString(Contact.EMAIL, 0);
}
If there is more than one e-mail address in the selected contact you need to present a dialog
box listing all of the addresses available and allow the user to choose the correct one. You
haven’t seen this form of a dialog before, so let’s cover it now.
One of the standard forms of the dialog class is one that just forces the user to select a value
from a list of values. This constructor for the form of dialog requires two parameters—an
array of objects and an array of Integer values. Therefore, the first step to creating this
dialog is to create arrays that contain the same number of elements as the number of e-mail
addresses in the contact. The integer value can be any value that makes sense to your
application, but in this case you really just want the index position of the selected address in
the list.
String[] Addresses = new String[EmailAddressCount];
int[] Values = new int[EmailAddressCount];
for (int i= 0; i< EmailAddressCount; i++)
{
Addresses[i] = selected.getString(Contact.EMAIL, i);
Values[i] = i;
}
Once these arrays are created, the dialog can be displayed. The doModal method is used to
display the dialog in a modal style, which just means that the application will wait until the
dialog has been dismissed before continuing. Alternatively, there is a show method that will
display a modeless dialog, which just means that the application will not wait for a response
before continuing to run.
Dialog dlg = new Dialog(“Select which address to use.”,
Addresses,Values,0,Bitmap.
getPredefinedBitmap(Bitmap.QUESTION));
int selectedAddr = dlg.doModal();
selectedEmail = Addresses[selectedAddr];
The value returned by the doModal call is one of the values supplied in the Values
array—the value that corresponds to the index of the selected item returned. In this
example, if the second item in the dialog was selected the return value of doModal
would be 1.
Once you have an e-mail address, the last action is to set the text of the _To field to be
that address. Remember, earlier we mentioned that if you insert contacts directly you will
bypass all of the formatting and validation that would otherwise normally happen. The same
holds true here—inserting an e-mail address by using the setText method will bypass any
validation and formatting that would normally happen with the EmailAddressTextField.
Adding the event to your calendar
The next step would be to actually submit the request. There are actually two diff erent
things that we want to happen when a user submits the request. The first is that, we will
assume that the request will be approved and go ahead and add the time off to your
calendar as a new event. Second, we will need to compose and send the e-mail request. This
second part we will cover in more detail later. For now, let’s stay focused on the PIM data
and add an event.
Working with the calendar is very similar to working with contacts. Items in the calendar are
generically called events and are also included in the umbrella of PIM items. As a result, the
process begins with the PIM class once again. The similarity continues with the Java standard
Event class and the BlackBerry-specific BlackBerryEvent class.
With that understanding, let’s get started looking at some code.
Time for action – adding an event to the calendar
- Add the following code to the addEvent method.
PIM pim = PIM.getInstance();
EventList events;
try {
events = (EventList)pim.openPIMList(PIM.EVENT_LIST,
PIM.READ_WRITE);
BlackBerryEvent newEvent =
(BlackBerryEvent) events.createEvent();
newEvent.addString(BlackBerryEvent.SUMMARY,
BlackBerryEvent.ATTR_NONE, “Requested time off.”);
newEvent.addString(BlackBerryEvent.LOCATION,
BlackBerryEvent.ATTR_NONE, “Special place”);
newEvent.addDate(BlackBerryEvent.START,
BlackBerryEvent.ATTR_NONE, _StartDate.getDate());
newEvent.addDate(BlackBerryEvent.END,
BlackBerryEvent.ATTR_NONE, _EndDate.getDate());
newEvent.addString(BlackBerryEvent.NOTE,
BlackBerryEvent.ATTR_NONE, _Comments.getText());
newEvent.addBoolean(BlackBerryEvent.ALLDAY,
BlackBerryEvent.ATTR_NONE, true);
newEvent.addInt(BlackBerryEvent.FREE_BUSY,
BlackBerryEvent.ATTR_NONE, BlackBerryEvent.FB_BUSY);
newEvent.commit();
BlackBerryEvent reminder = (BlackBerryEvent) events.createEvent();
reminder.addString(BlackBerryEvent.SUMMARY,
BlackBerryEvent.ATTR_NONE, “Check on request”);
reminder.addDate(BlackBerryEvent.START, BlackBerryEvent.ATTR_NONE,
new Date().getTime()+86400000);
reminder.addDate(BlackBerryEvent.END, BlackBerryEvent.ATTR_NONE,
new Date().getTime()+86400000);
RepeatRule repeat = new RepeatRule();
repeat.setInt(RepeatRule.FREQUENCY,RepeatRule.DAILY);
repeat.setInt(RepeatRule.INTERVAL, 1);
reminder.setRepeat(repeat);
reminder.commit();
}
catch (PIMException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
What just happened?
The menu item Submit request uses two helper methods to do the work of submitting the
request. The menu item and these methods are already stubbed out in the starter code so
this section is devoted to implementing the second step of the submit process—adding an
event to the calendar.
To get started, use the same general steps that you did when working with the contacts.
Calling the same openPIMList method with a diff erent parameter, PIM.EVENT_LIST,
gives you a list of events instead of a list of contacts. The createEvent method on this list
is used to establish a new Event object to start populating.
PIM pim = PIM.getInstance();
EventList events;
try {
events = (EventList)pim.openPIMList(PIM.EVENT_LIST, PIM.READ_
WRITE);
BlackBerryEvent newEvent = (BlackBerryEvent) events.createEvent();
The next step is to add each piece of data to the event. Unlike the contact, events do not have
complicated data types at all. There is only one field with multiple values and none of the fields
use a StringArray type. They are all basic types like you’ve seen before. You do see several
new types such as Date and Boolean, but setting and getting values from these is not any
diff erent then setting or getting String values; just use the right method for the field.
Also, like contact, most of the field indicator constants are available in the Event class, but
there are a few that are available only through the BlackBerryEvent class. For this reason,
istill recommend using the BlackBerryEvent for all field identifier constants.
The code starts off by setting some constant values to the SUMMARY and LOCATION fields.
On a BlackBerry, these are the first two fields on the screen where a new event is entered in
the Calendar application. The SUMMARY field is labeled as Subject in the calendar application.
It didn’t make sense to prompt for these values in TimeOff request (does your boss really
need to know where you sister’s wedding will be?), so they are just set to some static values.
Presumably, the user can change them later. Aft er that, the start and end dates are set to the
dates which have been entered into the fields on the screen. The NOTE field follows and is
populated with the Comments field from the entry screen.
newEvent.addString(BlackBerryEvent.SUMMARY, BlackBerryEvent.ATTR_NONE,
“Requested time off.”);
newEvent.addString(BlackBerryEvent.LOCATION, BlackBerryEvent.ATTR_
NONE,
“Special place”);
newEvent.addDate(BlackBerryEvent.START, BlackBerryEvent.ATTR_NONE,
_StartDate.getDate());
newEvent.addDate(BlackBerryEvent.END, BlackBerryEvent.ATTR_NONE,
_EndDate.getDate());
newEvent.addString(BlackBerryEvent.NOTE, BlackBerryEvent.ATTR_NONE,
_Comments.getText());
The last thing you do is to set two other fields that make the whole thing a litt le more
polished, the All Day indicator and the Free or Busy fl ag. When the All Day indicator is set to
true the time portions of the START and END date time values are ignored because the event
will take the entire day. The start time is eff ectively midnight of the start day and the end
time is the next midnight aft er the end day. Because the TimeOff application doesn’t even
allow a time portion to be entered, you can just hardcode the ALLDAY field to be true. The
FREE_BUSY field uses special constants that are defined in BlackBerryEvent to determine
the status. These constants all begin with FB_ to define the status. As you are asking for the
entire day off , you will set the FREE_BUSY field to FB_BUSY.
newEvent.addBoolean(BlackBerryEvent.ALLDAY, BlackBerryEvent.ATTR_NONE,
true);
newEvent.addInt(BlackBerryEvent.FREE_BUSY, BlackBerryEvent.ATTR_NONE,
BlackBerryEvent.FB_BUSY);
After setting all of the fields up for your new event, the last step is to commit (just like you
did when adding the contacts).
newEvent.commit();
Recurring events
Events do have one thing that is diff erent than contacts and which can be rather
confusing—a recurring event. A recurring event is an event that is set up once and shows
up many times in your calendar at regular intervals. An example might be a regular Monday
morning conference call at work. You don’t really want to enter that event into your calendar
every week, but you do want it to show up on your calendar so that other people don’t try to
set up another meeting at the same time.
The event you just requested time off for doesn’t need to be a recurring event. Let’s create
another event to remind you to check for approval of your request in order to demonstrate
this aspect of the Calendar. The initial steps to create the event are the same as before. You
won’t supply as much information because this is just a reminder.
BlackBerryEvent reminder = (BlackBerryEvent) events.createEvent();
reminder.addString(BlackBerryEvent.SUMMARY, BlackBerryEvent.ATTR_NONE,
“Check on request”);
reminder.addDate(BlackBerryEvent.START, BlackBerryEvent.ATTR_NONE,
new Date().getTime()+86400000);
reminder.addDate(BlackBerryEvent.END, BlackBerryEvent.ATTR_NONE,
new Date().getTime()+86400000);
The special math for the START and END fields is there to create the event 24 hours from
now. The long integer value that represents date and time is actually the number of
milliseconds from January 1, 1970 (commonly called the epoch for Unix time). The really
big number being added to it actually the number of milliseconds in 24 hours (24 hrs * 60
minutes/hour * 60 seconds/min * 1000 milliseconds/second).
That bit of code only sets up one event for the next day. The real work of a recurring event is
done by the RepeatRule class —the class that holds the logic for how an event is to repeat.
Your example of a reminder repeating each day is very simplistic. You might need a rule that
describes an event that repeats every seven days instead of everyday. Or how about events
that happen on the third Tuesday of the month? With just these few examples you can see
that there can be some very complicated rules about how an event repeats.
RepeatRule repeat = new RepeatRule();
repeat.setInt(RepeatRule.FREQUENCY,RepeatRule.DAILY);
repeat.setInt(RepeatRule.INTERVAL, 1);
repeat.setDate(RepeatRule.END, new Date().getTime()+(86400000 * 7));
This format should look very familiar now because it follows the same patt ern that all of
the PIM items do. It is not, however, derived from PIMItem itself. As a result, you should
never use any of the constant values that are defined in BlackBerryEvent or any other
PIMItem with a RepeatRule. All of the constants that are needed will be defined with the
RepeatingRule class itself.
There are two basic parts of a RepeatRule though, and those are the frequency with
which something repeats and the interval of time between events. In this case, you set the
FREQUENCY field to the constant RepeatRule.DAILY because the time between events is
counted in days. The INTERVAL field is set to 1 because we want this event to happen again
aft er just one day. These two values together indicate that the event should repeat every
day. How would you represent a biweekly meeting? The FREQUENCY would be set to WEEKLY
and the INTERVAL would be set to 2. There are a great many possibilities, but this example
should get you started understanding how the two fields work together.
The third line in your RepeatRule sets up the date that the event should stop repeating.
In this case, the last day to prompt the user is seven days from the current time. This is an
arbitrary number for the sake of this example, but the thought is that if the user’s request
hasn’t been resolved in 7 days then you should stop checking on it.
Once the RepeatRule is set up, you still need to apply the rule to the event by calling the
setRepeat method . Aft erward, the only thing left to do is to commit the event to the
Calendar application.
reminder.setRepeat(repeat);
reminder.commit();
There is so much more that you can do with a RepeatRule. In addition to some of the
more complex repeating patt erns, you can add dates which are to be excluded from the
RepeatRule as well. Generally, these aren’t used oft en, so let’s move on to the next step
of this application.
Pop quiz
- What is the base data type for items from the Calendar application?
- EventItem
- CalendarItem
- BlackBerryCalendarItem
- What class is used to define events that occur more than once?
- Recurrance
- RepeatRule
- RepeatingEventItem
- What two values are used to define how oft en an event repeats?
- TIMESPAN and OCCURANCE
- INTERVAL and FREQUENCY
- OCCURANCE and INTERVAL






October 1, 2010
BlackBerry