Interfacing with Personal Information Management (PIM) Applications in BlackBerry

Exclusive offer: get 50% off this eBook here
BlackBerry Java Application Development

BlackBerry Java Application Development — Save 50%

Build and deploy powerful, useful, and professional Java mobile applications for BlackBerry smartphones, the fast and easy way.

$23.99    $12.00
by Bill Foust | August 2010 | Java Web Development Web Graphics & Video

In this article by Bill Foust, author of BlackBerry Java Application Development, we will look at interfacing with other BlackBerry applications. You can create many great applications that don't do anything more complex than interfacing with the user and storing data. Sometimes though, developing an interesting application means doing something more or something special with the existing applications on the device. When you think about development from this point of view, there are suddenly a lot more applications that can be created than before.

Interfacing with the PIM data and messaging applications are some of the most common things an application developer will do when creating a new application. This article shows you how to take advantage of one of most powerful features available to a BlackBerry application. Each BlackBerry device comes with standard applications that you can interface with. These include the address book, calendar, and even the messaging applications. Being able to tightly integrate an application with these can make it even more valuable and useful to the end user.

(For more resources on BlackBerry, see here.)

The BlackBerry handhelds come pre-loaded with many great programs to help make a person more productive. While messages may be the most common reason a person will purchase a BlackBerry, the other Personal Information Management (PIM) applications often quickly become essential as well. Not only can you interface with these applications by adding or editing content in them, you can also listen for events that allow you to react to things that happen. Some of the applications even allow you to add menu items and other "active content" to them. That's a lot to talk about, so we'll just focus on some of the most common tasks to get you started in this article.

As a developer, you cannot ignore the other applications on the handheld. The more integrated an application can be with these standard applications, the better the user experience will generally be. Our TipCalc application is very specialized, and one of the few that works well without integrating with other applications. More often than not though, any applications that you create will benefit from some level of integration.

Introducing PIM

The first area that we will take a look at is the Personal Information Management, or PIM applications and data. PIM applications are a rather generic name for a group of tools that manage your personal information, especially as it relates to your handheld. This could be stretched to include a lot of things, but it generally means your messages, contacts, and scheduling information that help you to manage your life. In BlackBerry terms it means the Messages, Address Book, Calendar, Tasks, and Notes.

Access to the PIM data in the BlackBerry SDK is provided through the JSR-75 specification, which is a Java standard. Like many of the Java standards in the BlackBerry SDK, there are also BlackBerry-specific extensions available that expand the basic classes with new BlackBerry-specific functionality.

Like many of the other standards we find in Java, JSR-75 implements a factory pattern where one class, in this case the PIM class, is used to create objects for the other more specific types of PIM data. The PIM class can basically do only one thing and that is to retrieve a PIMList object that contains a bunch of specialized PIMItem objects.

Why is all so generic?

All of these PIM classes may seem very generic and you would be absolutely correct. They are generic and they are supposed to be that way. PIM data is a very generic concept so the implementation is very generic as well. Also, because it is a Java standard, it needs to be flexible enough to accommodate any system that it might be implemented on.

A perfect example of this kind of flexibility is the BlackBerry PIN field. The BlackBerry PIN is an entry in your address book and therefore, it should be included in the PIM data that you get. However, a PIN is a BlackBerry-specific concept and no other device out there will use it. You can't really expect the Java standard to include specialized fields for every possible piece of data that some device may have or want to include. The answer to this is to present PIM data in a key-value pairing so that it is flexible enough to handle every possible scenario.

A key-value pairing is a somewhat technical term to describe the pattern for storing values based on a static key. Or, more simply, if you know the proper key you can access the value. The flexible part is that the PIM object storing all of the values does not need to know about each specific value or provide any special mechanism for accessing each specific value. All access is done through generic methods, which also require the key.

The difficulty in using this kind of approach is that the keys must be common knowledge. In addition, simple numeric keys do not support self-documenting code or even easily readable code. Keys that are string values offer a lot of advantages—in that the keys are much more readable, but the possibility for mistakes is very great because you don't have the compiler to help ensure that only correct keys are used.

To help solve these issues there are derived classes for each type of PIM item. While you can do nearly everything by using the generic classes that a derived class would offer, I wouldn't recommend it. These classes are here to make your code easier to write and read, and should be used.

PIMLists

As we said early on, the PIM class is used primarily to retrieve a PIMList object for a specific kind of PIM item, that is, address book contact, calendar event, and so on. For each of these types, there is also a specialized class that you can use instead of the generic PIMList class. Classes such as ContactList, EventList, and ToDoList offer a specialized version of the more generic PIMList class. These specialized classes are also part of the Java standard and should be preferred because they offer a few more methods which are specific to that kind of data.

There are BlackBerry-specific versions of these classes as well. Therefore, the BlackBerryContactList class is the BlackBerry-specific version of the ContactList, which is in turn a specialized version of PIMList for contact data. Generally speaking, you will want to use the BlackBerry-specific versions of PIMList classes when making your applications.

PIMItems

A PIMItem is the generic representation for any piece of PIM data. Just like there are specific versions of the PIMList, there are also specific versions of the PIMItem class for each kind of PIMItem. Contact, Event, and ToDo are all specific versions of a PIMItem for that kind of PIM data. As you might expect, there are BlackBerry-specific versions as well. BlackBerryContact, BlackBerryEvent, and BlackBerryToDo all exist to extend and further specialize the standard Java classes.

These specialized classes aren't as specialized or easy to use as one might expect though. Providing a method called getFirstName might be really useful, but unfortunately, you will find nothing of the sort. The specialized classes offer few methods for accessing data. Instead, they provide static values for the keys used to set and retrieve data from the PIMItem class. Remember, earlier we noted that one drawback to using this kind of key-value pairing was that keys were sometimes not clear and that you could not expect help from the compiler. By providing each key value in the specialized class, both of these goals are accomplished. The name of the key value now provides a readable name and the compiler will flag an error if there is a typo or problem with the constant value being used.

Another aspect of PIMItem is that each value that an item has a specific type associated with it as well. Some of these are obvious, such as the start date of an event using a Date type. Some of them, such as the Name field of a Contact that requires an array, are not. Some fields can be given a subtype as well, such as the Phone field. With the subtype you can specify what kind of phone number it is: home, work, or mobile. Furthermore, some of the fields can have multiple occurrences while others cannot. A good example of this is the Email field in a Contact. A contact is allowed to have up to three e-mail addresses, but there is no subtype associated with them like there is with phone numbers. The bottom line to all this is that the PIM items have a defined structure to them and they won't allow just any value to be put into a field. The documentation plays a big role here in understanding this because there are no field-specific methods to provide some additional assistance in the proper way to access each field.

Laying the ground work

Still, this is all rather abstract because you haven't seen any real code samples yet, so let's get into some code! For this article, you will build an application that someone will use to request some time off from their manager. This is definitely one of those applications that just can't be done without interfacing with other applications on the handheld! To make getting started a little easier we will take the starter TimeOff application from the code bundle and add to it throughout this article.

The first task to undertake is one to help make testing and debugging easier. Remember, you will be working on the simulator, which is essentially a brand new device and which can be often reset. That means you don't have any of your contacts there! You will need some contacts later, so to get started let's add a menu item to the application that will create a few contacts that you can later use to test with.

Time for action - creating test contacts

  1. Modify the _AddTestAddressesAction menu item in the TimeOff project to look like the following completed code.
  2. protected MenuItem _AddTestAddressesAction = new MenuItem(
    "Add Test Data", 800000, 50)
    {
    public void run()
    {
    PIM pimInstance = PIM.getInstance();
    try
    {
    // TODO: Create test contacts
    BlackBerryContactList contacts =
    (BlackBerryContactList)pimInstance.openPIMList(
    PIM.CONTACT_LIST, PIM.READ_WRITE);
    BlackBerryContact newContact1 =
    (BlackBerryContact)contacts.createContact();
    BlackBerryContact newContact2 =
    (BlackBerryContact)contacts.createContact();

    String[] names = new
    String[contacts.stringArraySize(BlackBerryContact.NAME)];
    names[BlackBerryContact.NAME_FAMILY] = "Smith";
    names[BlackBerryContact.NAME_GIVEN] = "John";
    if (contacts.isSupportedArrayElement(Contact.NAME,
    Contact.NAME_SUFFIX))
    {
    names[BlackBerryContact.NAME_SUFFIX]="Jr";
    }
    newContact1.addStringArray(
    BlackBerryContact.NAME,
    BlackBerryContact.ATTR_NONE,
    names);
    names[Contact.NAME_FAMILY] = "Doe";
    names[Contact.NAME_GIVEN] = "John";
    if (contacts.isSupportedArrayElement(Contact.NAME,
    Contact.NAME_PREFIX))
    {
    names[Contact.NAME_PREFIX] = "Dr.";
    }
    newContact2.addStringArray(Contact.NAME, Contact.ATTR_NONE,
    names);
    //TODO: Add Phone numbers
    //TODO: Add Email Addresses
    //TODO: Add Addresses
    newContact1.commit();
    newContact2.commit();
    }
    catch (PIMException e)
    {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    };

  3. Then add this line to the constructor to make the menu item available when you run the application.

    this.addMenuItem(_AddTestAddressesAction);

What just happened?

This is the first of several baby steps as you work towards the goal of creating some test contacts in the address book in the simulator. As the address book in the simulator doesn't have any entries to begin with, and can be erased frequently, doing this provides you with a way to quickly and easily create or recreate the contacts you will use later on for testing other parts of this application. It also happens to be a great way to demonstrate how to add contacts.

This first baby step does only a few things. First, it gets a PIMList object for contacts and then creates two new contacts. After this it sets the name of each one and finally commits the records into the address book. These steps make sense at a high level, but let's take a look at the details.

The first step is to get an instance to the PIM object, which is done through a static method in the PIM class called getInstance.

PIM pimInstance = PIM.getInstance();

Once you have an instance of PIM, the next step is to get a list of contact items using the openPIMList method on the instance you just retrieved. This same method is used to get a list of any kind of PIM item so you must specify the type of data to get as one of the parameters. The PIM class offers constant values for every kind of PIM item, so in this case, use the constant PIM.CONTACT_LIST. As you plan to add new contacts, the next parameter needs to be the constant PIM.READ_WRITE so that you have write permissions. It's always good practice to request the minimum amount of permissions that you need, so if your application doesn't change or add data to the list you should simply use the PIM.READ permission.

As we touched on earlier, this method returns a generic PIMList type so you also have to cast it to the appropriate specialized type. If a list type of CONTACT_LIST has been specified, you can cast the resulting PIMList to either of the available specialized classes—ContactList or BlackBerryContactList. As long as your application is a BlackBerry-specific application, there is no good reason to use the less specialized class of ContactList. Instead, you should always use BlackBerryContactList.

BlackBerryContactList contacts =
(BlackBerryContactList)pimInstance.openPIMList
(PIM.CONTACT_LIST, PIM.READ_WRITE);

The next step is to create a couple of new contacts that you will start to populate. This is done through the createContact method available on the ContactList class. Again, you need to cast the resulting objects to the proper type. The createContact method returns a contact, but again you've chosen to use the more specialized version of BlackBerryContact instead. Because this is all being executed on a BlackBerry handheld, you can always cast a contact to a BlackBerryContact safely. The same is true for each of the Java specialized classes and their corresponding BlackBerry specialized class.

BlackBerryContact newContact1 = (BlackBerryContact) contacts.
createContact();
BlackBerryContact newContact1 = (BlackBerryContact) contacts.
createContact();

The next segment of code sets the name attribute of the newly created contacts. Notice that this is done through an array of String objects instead of individual methods. This isn't something that is done to be more efficient, it is done this way because it must be; there is no other way.

We mentioned before about each field in a PIMItem having a type associated with it. Most of the field types are basic String or Date type fields, but NAME is more complicated than most of the other fields. The NAME field is defined as a StringArray because there are many parts to a name and you want to be able to set each part separately. There aren't very many fields of this type used, but this is probably one of the most important. You can only set the NAME field as a whole unit, so if only one part of the name needs to be changed the entire name field must be replaced.

To work with the name, you must first create a string array of the proper size. There is no constant value for this as it may vary with the SDK version. Instead, you must first get the size by using the stringArraySize method on the ContactList and then construct a new array by using the returned value.

String[] names = new String[contacts.stringArraySize(BlackBerryContact.NAME)];

Once you have an array of the proper size each part of the name is set by indexing the array by using the NAME constant from the Contact class.

names[BlackBerryContact.NAME_FAMILY] = "Smith";
names[BlackBerryContact.NAME_GIVEN] = "John";

In this example, you also want to add another name part but are not sure whether the field is supported in this system. Not all fields are supported and not all of the name subfields are supported either. You can test to see whether a field or a subfield is supported by using the isSupportedField or isSupportedArrayElement methods in the ContactList class. In this case, you test to see if the suffix is supported, and then set the suffix if so.

if (contacts.isSupportedArrayElement(Contact.NAME,
Contact.NAME_SUFFIX))
{
names[BlackBerryContact.NAME_SUFFIX]="Jr";
}

This step is very important if you want to use the same code for multiple platforms. Each system can support the fields it chooses. In this case, the suffix is NOT supported and if you were to step through this code in the debugger, you would see that the code to set the suffix is skipped over. Later on, when you test this application, you will also see that the suffix was not added to the contact.

Other platforms may implement it differently. You could just assume each of the name subfields are supported and set the field without testing to see if it is supported. In the BlackBerry SDK, unsupported fields are just quietly ignored. This can lead to confusion wondering why a field doesn't appear in the Address Book application, but it won't cause an error.

The next step is to actually add the NAME field to the contact. Up until this time you've simply been building an array in memory with all of the proper values.

newContact1.addStringArray(
BlackBerryContact.NAME,
BlackBerryContact.ATTR_NONE,
names);

Notice that the method addStringArray doesn't give any indication about what field is being added, but only what type of data is being added. All of the PIMItem methods are like this. Remember, this class is designed to be generic. The first parameter is the field indicator, which is one of the many constants that are defined in the Contact class. In this case, we use the BlackBerryContact class. Because BlackBerryContact derived from Contact, all of the constant values are accessible. The BlackBerryContact class does define some constants that are BlackBerry-specific, such as PIN. For this field you must reference the constant value from BlackBerryContact because the Java standard Contact class does not define it. Partly for this reason, I suggest always referencing constant values from BlackBerryContact because all of the constant values will be available through this class.

The method addStringArray was chosen because that is the type of data that you are adding. The NAME field is defined as a string array and so you must use the addStringArray method because it corresponds to the data type of the field.

Once you finish with the first contact, the code starts building the NAME string array to add a second contact. For demonstration sake, all of the constant values that are referenced are done so using the Contact class instead of the BlackBerryContact class.

names[Contact.NAME_FAMILY] = "Doe";
names[Contact.NAME_GIVEN] = "John";
if (contacts.isSupportedArrayElement(Contact.NAME,
Contact.NAME_PREFIX))
{
names[Contact.NAME_PREFIX] = "Dr.";
}
newContact2.addStringArray(Contact.NAME, Contact.ATTR_NONE, names);

Also, notice that the second contact applies a prefix to the name and tests to see if it is supported in the same way as you did for the suffix when adding the previous contact. However, the prefix is supported and if you were to step through this method in the debugger, you would see that the prefix is being set properly.

The last step you have to do is to commit the data that has been added to the contact.

newContact1.commit();
newContact2.commit();

Simply creating a new contact is not enough; you must commit the changes in it by using the commit method. Creating a contact and then never committing it will not have any effect on the Address Book application. It simply won't be shown in the list. That's the whole point of this exercise, so you have to make sure and commit the changes once they are all done.

At this point, if you were to run the application and select the menu, you would see two new contacts added to the Address Book application in the simulator. They would show up as Dr. John Doe and John Smith. There would be only names with these contacts because that is all that you've added so far.

In the example code that you just stepped through there was one mistake that could have proven to be very serious. Did you catch it? You are reusing the names array to set the names of both contacts. This is actually risky, but it happens to work out in this case. If the SUFFIX field had been supported then your Dr. John Doe would have actually been Dr. John Doe Jr. because the array was not reset before it was used again. If you had changed the order around, John Smith would have been Dr. John Smith. This might have lead to a bug that could have been tough to track down, so keep it in mind.

BlackBerry Java Application Development Build and deploy powerful, useful, and professional Java mobile applications for BlackBerry smartphones, the fast and easy way.
Published: July 2010
eBook Price: $23.99
Book Price: $39.99
See more
Select your format and quantity:

(For more resources on BlackBerry, see here.)

Expanding your test contacts

Being able to create a contact is nice, but you really need for them to have more information than just a name in order to be useful. So, for the next step, add some telephone numbers to the contacts. If you are familiar with the Address Book application already, and you should be, then you know that a contact can have multiple phone numbers—each with a different role or locations. After having seen how the NAME field is handled, you may well assume that the telephone field, named TEL, would operate in the same manner; as a StringArray type. You would be wrong though.

When it comes to the TEL field each field is a simple String and is given an additional attribute defining which kind of phone number it is. Let's take a look at this with the following code.

Time for action - adding telephone numbers

  1. Add the following code to the run method of the AddTestContacts menu item.
  2. //TODO: Add Phone numbers
    newContact1.addString(BlackBerryContact.TEL,
    BlackBerryContact.ATTR_MOBILE, "555-555-1212");
    newContact2.addString(Contact.TEL,Contact.ATTR_HOME,
    "555-555-1234");
    newContact2.addString(Contact.TEL,Contact.ATTR_FAX,
    "555-555-9999");
    newContact2.addString(Contact.TEL,
    Contact.ATTR_MOBILE,"555-555-1313");
    // This is bad!
    newContact2.addString(Contact.TEL,Contact.ATTR_FAX,
    "555-555-1414");

What just happened?

Working with phone numbers may look very straightforward, but there are many pitfalls to look out for here as well. Each phone number is added using the addString method, which should look similar to the addStringArray method that you just worked with. Again, the proper method to add the field is the one that matches the fields' type and has nothing to do with the name of the field or its function.

Also, like the previous example, the first parameter to the method is the constant value defining which field is being added, which in this case is TEL. Following the field indicator though is the important part, called the field attribute. The attributes are used as a way of providing additional information about a field. In this case, that information defines what kind of phone number is being added.

Every add method requires an attribute field, but this doesn't always make sense for some fields. When this is the case, the attribute ATTR_NONE should be used. The phone number field though requires an attribute. Attempting to use ATTR_NONE will in fact be treated the same as ATTR_HOME.

newContact1.addString(BlackBerryContact.TEL,
BlackBerryContact.ATTR_MOBILE, "555-555-1212");

Now that you've covered the basics, this line to add a mobile telephone number to John Doe should be self explanatory.

newContact2.addString(Contact.TEL,Contact.ATTR_HOME,"555-555-1234");
newContact2.addString(Contact.TEL,Contact.ATTR_FAX,"555-555-9999");
newContact2.addString(Contact.TEL,Contact.ATTR_MOBILE,"555-555-1313");

Now, as John Smith is a doctor, he will have many more ways to be reached, but you can see that this also presents no problems for the Contact class. Again, this example uses the Contact class to reference the constant values instead of the BlackBerryContact class. This is fine, but there are some phone attributes which are not available from the Contact class. The Java standard Contact only provides for six telephone types, but the BlackBerry Address Book application will allow eight. So what is the difference? The Home2 and Work2 numbers are specific to BlackBerry. The constants for these attributes can be found only in the BlackBerryContact class.

As long as you use one, and only one, of each attribute, you will be in good shape, but things get really messy when you try to add a number with the same attribute again.

// This is bad!
newContact2.addString(Contact.TEL,Contact.ATTR_FAX,"555-555-1414");

You may expect that adding a number with the same attribute would simply replace any existing value, but this is not the case. Instead, the system will add the number into the "next available slot". The results can be quite confusing because in this case, the number will be placed into the PAGER attribute because FAX is already populated. If the PAGER already had a value, then it would be added to some other field that didn't have a value.

Adding another phone number with the same attribute as an existing number yields unpredictable results.

The corollary to this is that if you are editing a contact in your application you can't just blindly add the TEL fields. You must first either remove the old field by using the removeValue method, or change the value by using the setString method.

Either way, things are going to be a lot more complicated. You would think that there would be methods for getting, setting, or removing values that match those for adding values, but this is not the case either. There are getString, setString, and removeValue methods, but all of the methods rely on an index value and not the attribute that was originally supplied. This just reinforces the idea that attributes are simply meant to provide additional information about the field and nothing more.

So, if you wanted to change one of the TEL fields you first need to find the field with the proper attribute out of the list of TEL fields. Remember that this field is not an array though, so even though there may be up to eight values, there may be as few as 0 and the order in which they are stored apparently has nothing to do with their attribute. The following code fragment should serve as an example of how to update the ATTR_HOME phone number.

// The proper way to change a value
int count = newContact2.countValues(Contact.TEL);
for (int i = 0; i < count; i++)
{
if ((newContact2.getAttributes(Contact.TEL, i) & Contact.ATTR_HOME)
== Contact.ATTR_HOME)
{
newContact2.setString(Contact.TEL, i, Contact.ATTR_HOME,
"555-555-4321");
}
}

To start off, you can get the number of values in the field by calling the countValues method. Once you know how many are there, a simple for loop is used to test each one. In order to see if a value has the ATTR_HOME attribute, you first get all of the attributes of the value by calling the getAttributes method. Some attributes can be combined using a bitwise OR, so to check for a specific attribute you must test with the bitwise AND, which effectively removes just the desired attribute from any other combined attributes. Once you know that a value has the ATTR_HOME attribute, you can call setString by using the index value from the loop to change the value.

Like I said, it's a lot more complicated and as a result, I think it is safe to suggest that you not do it unless you really need to. There will always be special cases where such a thing is desired, but in general, a user should be in charge of their contacts and not your application. Besides, there is no way to stop a user from changing or deleting a contact that has been programmatically added.

Expanding even more

After tackling the relatively complicated fields of NAME and TEL, the EMAIL field should be a lot easier. Making sure that your contacts have an e-mail address is the whole point of this task because these will be used later on when testing another feature. Knowing that the Address Book application allows you to have up to three e-mail addresses, how would you think they are implemented in the PIM? Is it implemented as a String with multiple values (such as the TEL field), or as a StringArray (such as the NAME field)? If you chose a String with multiple values, you chose correctly!

The EMAIL field actually fits well with this concept of a String field with multiple values. Unlike the TEL fields, there are no attributes that are attached to each of the e-mail addresses, so adding one simply adds it to the list and there is nothing more to be concerned about. So let's look at some code already!

Time for action - adding e-mail addresses

  1. Add the following code to the run method of _AddTestAddressesAction under the proper comment line.
  2. //TODO: Add Email Addresses
    newContact1.addString(Contact.EMAIL,Contact.ATTR_NONE,
    "John@Test.com");
    newContact2.addString(Contact.EMAIL,Contact.ATTR_NONE,
    "JDoe@test.com");
    newContact2.addString(Contact.EMAIL,Contact.ATTR_NONE,
    "JohnDoe@test.com");
    newContact2.addString(Contact.EMAIL,Contact.ATTR_NONE,
    "Admin@test.com");

What just happened?

Wow, that code segment looks really easy. The lines are all practically the same! Each line specifies the field as EMAIL and the attributes as ATTR_NONE, so there isn't much more to talk about except for the "what-ifs".

Much like the TEL, things get a little trickier if you want to edit the contact in your application, but not as tricky as they are with the PHONE field. The addresses are stored in the same order that you added them to the field so you can use this fact to your advantage when editing. Because there are no attributes for the various e-mail addresses, it is best to remember the index of each value when you read them out. In this way, when you need to change the value you can use the setString method and provide the index of field.

Alternatively, you can remove one of the EMAIL values and add a new one, but this will also change the order of the values in the field. Values that are added are always placed at the end of the list.

The biggest thing to watch out for here is that you don't add a fourth EMAIL value to the field. This will cause an exception to be thrown that the application will have to handle. In the case of this application, it just quietly fails and neither of the contacts are added.

You can also put bad data into the Address Book application by adding values with bad data. For instance, the Email Address field in the Address Book application has special validation logic to ensure that the value is actually a valid e-mail. If you leave out the @, for instance, the user would see an error and not be allowed to commit the data. All of those safeguards don't exist when working directly with the PIM. This goes for phone numbers as well as for any other formatted values. It is one more reason that you must be very careful about when working with the PIM directly.

Finishing the test contacts

We have done enough work to solve the initial problem of getting some contacts with e-mail addresses into the Address Book. However, there is one more area of the contact left to tackle—the address itself. The ADDR field is a combination of the NAME and PHONE fields in that each address is a StringArray, but there are multiple addresses which each have an attribute specifying what kind of address it is. Sounds confusing? It is by far the most complex piece of PIM data. Seeing code always helps me, so let's dive into the code and tackle it head on.

Time for action - adding e-mail addresses

  1. Add the final code segment under the appropriate comment in the run method of _AddTestAddressesAction.

//TODO: Add Addresses
String[] Address1 = new String[contacts.stringArraySize(BlackBerry
Contact.ADDR)];
String[] Address2 = new String[contacts.stringArraySize(BlackBerry
Contact.ADDR)];

Address1[BlackBerryContact.ADDR_STREET] = "123 Main St.";
Address1[BlackBerryContact.ADDR_EXTRA] = "Apt. 4";
Address1[BlackBerryContact.ADDR_LOCALITY] = "AnyTown";
Address1[BlackBerryContact.ADDR_REGION] = "AnyState";
Address1[BlackBerryContact.ADDR_COUNTRY] = "USA";
Address1[BlackBerryContact.ADDR_POSTALCODE] = "12345";
newContact1.addStringArray(BlackBerryContact.ADDR,
BlackBerryContact.ATTR_HOME,Address1);

Address1[BlackBerryContact.ADDR_STREET] = "345 Main St.";
Address1[BlackBerryContact.ADDR_LOCALITY] = "AnyTown";
Address1[BlackBerryContact.ADDR_REGION] = "AnyState";
Address1[BlackBerryContact.ADDR_COUNTRY] = "USA";
Address1[BlackBerryContact.ADDR_POSTALCODE] = "12345";

Address2[BlackBerryContact.ADDR_STREET] = "20 N Oak St.";
Address2[BlackBerryContact.ADDR_LOCALITY] = "AnyTown";
Address2[BlackBerryContact.ADDR_REGION] = "AnyState";
Address2[BlackBerryContact.ADDR_COUNTRY] = "USA";
Address2[BlackBerryContact.ADDR_EXTRA] = "Suite 200";
Address1[BlackBerryContact.ADDR_POSTALCODE] = "12345";

newContact2.addStringArray(BlackBerryContact.ADDR,
BlackBerryContact.ATTR_HOME,Address1);
newContact2.addStringArray(BlackBerryContact.ADDR,
BlackBerryContact.ATTR_WORK,Address2);

What just happened?

This code should be pretty similar to the code that you saw for the NAME field. The first step is to simply create an array of String objects of the proper size and once again relying on the stringArraySize method to give that proper value. The only real difference here is that the field specified in the code is the ADDR field.

String[] Address1 = new String[contacts.stringArraySize(BlackB
erryContact.ADDR)];

Once you have an array of the right size, setting the data for each part of the address is just a matter of referencing the right index within the array by using the constants already defined. The names of the constant values for the ADDR field are so generic that they are confusing.

Address1[BlackBerryContact.ADDR_STREET] = "123 Main St.";
Address1[BlackBerryContact.ADDR_EXTRA] = "Apt. 4";
Address1[BlackBerryContact.ADDR_LOCALITY] = "AnyTown";
Address1[BlackBerryContact.ADDR_REGION] = "AnyState";
Address1[BlackBerryContact.ADDR_COUNTRY] = "USA";
Address1[BlackBerryContact.ADDR_POSTALCODE] = "12345";

Maybe, other parts of the world think in terms of "locality" and "region", but I somehow doubt it. As if those weren't bad enough, the name ADDR_EXTRA just gives no help at all towards understanding its use. This is just one of those things that you have to remember when working with addresses in a contact though.

Once the address is fully populated, adding it to the field is the same as adding a TEL field in that you also have to specify one of the two supported attributes, either ATTR_HOME or ATTR_WORK.

newContact1.addStringArray(BlackBerryContact.ADDR,
BlackBerryContact.ATTR_HOME,Address1);

The whole point to this is that an address can have more than one address in the contact record and the second contact in the example code has been set up in this way. Because the values for the ADDR field are based on their attribute, the order in which they are added is not important. However, the index is still important when it comes to updating or deleting a value.

The ADDR field also follows the same quirks that the TEL field does. If you add a second address with the ATTR_HOME attribute, the attribute will get silently reassigned to ATTR_WORK if one doesn't already exist. If there are already two addresses in the contact, then an exception will be thrown so it is important to utilize the methods for checking the field before adding new values.

Adding new address values isn't that bad, but changing one is the worst of both worlds. If you recall from working with the NAME field, you cannot change just one element of the StringArray. You have to replace the entire StringArray by calling the setStringArray method.

This quirk is somewhat annoying, but now adds the fact that there is more than one value in the list and it can get pretty complex. In order to get the address you want, you have to find it in the same way that you did for the TEL field. The home address will not be in the same index position all the time so you must look at each address in the list (there are only two at most) and test the attribute to see if it has the attribute you want.

BlackBerry Java Application Development Build and deploy powerful, useful, and professional Java mobile applications for BlackBerry smartphones, the fast and easy way.
Published: July 2010
eBook Price: $23.99
Book Price: $39.99
See more
Select your format and quantity:

(For more resources on BlackBerry, see here.)

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 submitted 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 fly. In short, you would almost be reimplementing the AddressBook application! Wouldn't it be better 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

  1. 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.

    if (this.getFieldWithFocus() == _To &&
    context != Menu.INSTANCE_CONTEXT_SELECTION)
    {
    m.add(_AddressBookAction);
    }

  2. Then, we need to implement the Run method of the _AddressBookAction menu item.

    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 little 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 often and effectively in every application on the handheld. It is an established pattern 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 different 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

  1. 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 different 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 different 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, I still 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. After 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 little more polished, the All Day indicator and the Free or Busy flag. 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 effectively midnight of the start day and the end time is the next midnight after 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 different 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 pattern 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 after 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. Afterward, 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 patterns, you can add dates which are to be excluded from the RepeatRule as well. Generally, these aren't used often, so let's move on to the next step of this application.

Sending e-mail

The last step that you need to do to finish up the TimeOff application is to actually send the message out making the request. Using the messaging system like this is just scratching the surface of what can be done when working with the messaging APIs.

This example will send a message as a regular text e-mail to one recipient. The BlackBerry claim to fame is messaging though, and the API to work with Messages is extensive. Not only can you send plain messages like this, but you can send more complicated messages like multi-part messages with attachments.

Time for action – sending an e-mail from an application

  1. It's time to make this application actually do what it is meant to do—send that email! Add the following code to the sendRequest method in the TimeOff application.

    StringBuffer msgBody = new StringBuffer();
    msgBody.append("A new TimeOff application request has been
    submitted \nFrom:");
    msgBody.append(Integer.toHexString(DeviceInfo.getDeviceId()));
    msgBody.append("\nStarting: ");
    msgBody.append(DateFormat.getInstance(DateFormat.DATE_DEFAULT).
    formatLocal(_StartDate.getDate()));
    msgBody.append("\nEnding: ");
    msgBody.append(DateFormat.getInstance(DateFormat.DATE_DEFAULT).
    formatLocal(_EndDate.getDate()));
    msgBody.append("\nComments: ");
    msgBody.append(_Comments.getText());

    Message newMsg = new Message();
    try {
    Address recipient = null;
    recipient = new Address(Address.EMAIL_ADDR,_To.getText());
    newMsg.addRecipient(Message.RecipientType.TO,recipient);
    newMsg.setSubject("Time off Request");
    newMsg.setContent(msgBody.toString());
    Transport.send(newMsg);
    }
    catch (MessagingException e)
    {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }

What just happened?

The first part of this method is simply creating the body of the message that will be sent. The most interesting part of this code is using the DeviceInfo class to get the device ID, also called a PIN number. You needed some way to identify who the e-mail is from, and the device ID serves this purpose well. Yes, the sender's e-mail will be in the message itself, but this works well too. The PIN number is typically represented in hexadecimal so you must convert it by using the toHexString method.

StringBuffer msgBody = new StringBuffer();
msgBody.append("A new TimeOff application requestion has been
submitted.\nFrom:");
msgBody.append(Integer.toHexString(DeviceInfo.getDeviceId()));
msgBody.append("\nStarting: ");
msgBody.append(DateFormat.getInstance(DateFormat.DATE_DEFAULT).
formatLocal(_StartDate.getDate()));
msgBody.append("\nEnding: ");
msgBody.append(DateFormat.getInstance(DateFormat.DATE_DEFAULT).
formatLocal(_EndDate.getDate()));
msgBody.append("\nComments: ");
msgBody.append(_Comments.getText());

The next section is devoted to actually creating and sending the message. You might expect this to be very complex, but it's almost embarrassing how simple this code is.

The first step is to create a Message object to work with. There are actually three different Message classes available through the BlackBerry API. They all exist in different namespaces and serve different purposes, so this part can be confusing. The Message class that you need here is in the net.rim.blackberry.api.mail.Message package. This Message class is used with e-mail and PIN messages. Fortunately, creating this object is very straightforward.

Message newMsg = new Message();

The next step is to populate the Message object with the recipient. At this point, you should have a valid address in the _To field of the application. You would want to perform basic testing before using the address in a real application, but for now you will just use whatever is in the field. The message doesn't want to use just a string value for the recipient though, you need to construct an Address object before adding it to the message.

This class doesn't do any validation either. Instead, its primary purpose is to provide an address along with a "readable name" for it. In this case, you simply specify a readable name of "TimeOff Recipient". If you chose an address from one of your test contacts instead of manually typing one in, the Message application will match on the address and use the name from the Address Book instead of this readable name provided.

The last step is to add the Address object to the message by using the addRecipient method. This method also requires an identifier constant to indicate what kind of recipient it is. Notice that the Message class has a RecipientType inner class, which in turn contains the constant definitions. This is just another way of organizing the constant values into groups that make sense together. The PIM classes don't do this and as a result, the constant values are harder to use. The Message class has several inner classes like this.

Address recipient = null;
recipient = new Address(_To.getText(), "TimeOff Recipient");
newMsg.addRecipient(Message.RecipientType.TO,recipient);

After setting the recipient of the message, you set the main text of the message in the subject and body. The important thing to note here is that the setContent method can accept a simple string (like you have in this example) or a more complex object called a Multipart. A Multipart is used any time there is more than one piece to a message, such as when a message has an attachment.

newMsg.setSubject("Time off Request");
newMsg.setContent(msgBody.toString());

After the message has been fully constructed, you can finally send it. Here, you see a new class called Transport—a class that handles all of the messy stuff when it comes to integrating with the rest of the system. The send method is as simple as it can be and yet handles so much.

Transport.send(newMsg);

At this point, the message is part of the Messages application and is handled from there just as if the user had typed it up. You can see the message as a sent message by going to the Messages application. It will handle queuing up the message to be sent, retries, failures, and the transmission of the message itself. The TimeOff application simply returns and continues executing without having to worry about any of the technical details of what it takes to actually send the message.

Have a go hero – sending a different kind of message

There is still one kind of PIMItem that we haven't discussed at all, and that is a ToDo item from the Tasks application. This PIMItem type doesn't have any complicated value types like contacts nor does it have any usual aspects like recurring events. It is pretty straightforward once you understand the other concepts from these other PIMItem types.

Take this opportunity to explore the ToDo class and expand the TimeOff application to also add a ToDo item to check on the status as well as the reminder events that have already been added.

Summary

Interfacing with other applications on the handheld is the best way to make the applications you write more user-friendly and more likely to be used. The BlackBerry SDK offers many ways by which applications can leverage, extend, or integrate with the existing suite of applications that come with a new device. In this article, we primarily focused on accessing the PIM data. We also dabbled a little into how to use the messaging systems to send an e-mail message. There is much more that can be done to make applications that don't just work with the operating system, but which can even become embedded into the operating system so that the use may never know they are a separate application.

In this article, we covered:

  • What we mean by PIM data.
  • How to access a particular list of PIM data.
  • How to create new PIM items and how to assign values to their fields.
  • How to send an e-mail message.

Further resources on this subject:


About the Author :


Bill Foust

Bill has been a professional developer for over 15 years in a variety of platforms and languages. Bill first encountered a RIM 950, the predecessor to the BlackBerry brand, in 1998 and has been working with them since that time. During this early period, he wrote and sold many applications for BlackBerry through Handango.com and was involved in many custom development projects as well.
With the release of the BlackBerry 5810 in 2002, the development environment changed from C++ to Java Micro, and Bill started pursuing other opportunities, including .NET and has continued to do development and consulting professionally since then.
He wrote his first book "Mobile Guide to BlackBerry" in 2005 and later became part of the podcasting and blogging team at MobileComputingAuthority.com, which focuses on mobile devices of all kinds.

Books From Packt


Java EE 6 with GlassFish 3 Application Server
Java EE 6 with GlassFish 3 Application Server

Oracle JRockit: The Definitive Guide
Oracle JRockit: The Definitive Guide

JavaFX 1.2 Application Development Cookbook
JavaFX 1.2 Application Development Cookbook

NetBeans Platform 6.9 Developer's Guide
NetBeans Platform 6.9 Developer's Guide

BlackBerry Enterprise Server for Microsoft® Exchange
BlackBerry Enterprise Server for Microsoft® Exchange

JasperReports 3.6 Development Cookbook
JasperReports 3.6 Development Cookbook

Flash 10 Multiplayer Game Essentials
Flash 10 Multiplayer Game Essentials

FreeSWITCH 1.0.6
FreeSWITCH 1.0.6


No votes yet

Post new comment

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
V
D
y
L
D
t
Enter the code without spaces and pay attention to upper/lower case.
Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software