Getting Personal with J2ME's PIM API

J2ME, the Java platform for portable devices, doesn't allow access to a device's address book. The JSR 75 Personal Information Management and JSR 75 FileConnection packages change all this.


March 01, 2006
URL:http://www.drdobbs.com/jvm/getting-personal-with-j2mes-pim-api/184406463

Tom is a technical writer providing support for J2ME wireless technologies at KPI Consulting Inc. He can be contacted at [email protected].


Ever wonder why the PDA market isn't as large as that of desktop computers? The competition fits neatly into your hand—it's the mobile phone. Mobile phones can store contact information and an event calendar, just like a PDA. The mobile phone can also do the PDA one better in that when you glance at a contact name, with just the push of a button you can call that person. Or, it can automatically capture a new client's number if they call your mobile phone. Certainly PDAs can do things that mobile phones can't, and the PDA's UI is much easier to use. However, consider that Nokia alone sold its billionth mobile phone last September (with 2 billion mobile phone subscribers worldwide), compared to the tens of millions of PDAs sold, and you can grasp that the phone's limited address book/calendar capabilities are quite adequate for many people.

However, while this is a fine state for consumers, the situation drives Java 2 Mobile Edition (J2ME) programmers nuts. That's because J2ME, the Java platform tailored for portable devices such as mobile phones, doesn't allow access to the device's address book. If you wrote a killer app that leveraged this information, and could sell it into a market with, conservatively, tens of millions of customers...

Not surprisingly, as a mobile phone tech-support person I often get asked if J2ME can access a mobile phone's address book. Until recently, all I could do was explain that this missing capability was for the sake of security, which is not an idle concern when your mobile phone carries all sorts of personal data on it.

However, I've recently had to change my tune. That's because the Java Community Process (JCP), a consortium of companies that develops standards and new technologies for the Java platform, ratified the final version of Java Specification Request 75 (JSR 75). This specification defines two optional Java packages that implement highly desired PDA functions on the J2ME platform:

These specifications are available on the JCP web site (http://www.jcp.org/en/jsr/detail?id=75). In this article, I focus only on the JSR 75 PIM API.

Because there's a lag anywhere from 6 months to 18 months between the final ratification of a JSR specification and when the API appears in shipping phones, JSR 75-capable phones have only recently appeared on the market. So, this is as good a time as any to delve into the details of the PIM API.

Overview of the PIM API

The PIM API provides a standard interface to the contact, event, and to-do information in a device's PIM database. Quite often it acts as the front end to the phone's native PIM database, although for other portable devices the database could be implemented in Java. Critically, the PIM API was designed to access databases external to the device as well as its internal one. The external PIM database might be stored on a removable memory card, or reside on a remote server in the corporation. If the device has more than one database (perhaps an internal one in non-volatile memory and the other on a removable card), the PIM implementation automatically uses the default database.

A major problem for any PIM interface is how to get data in/out of the database it manages. The PIM API supports the import/export of PIM information using "virtual cards" that comply with the standards-based vCard 2.1 and vCalendar 1.0 formats. A vCard carries address book data (contacts), while a vCalendar contains events and to-do data. These formats were developed by the Internet Mail Consortium for the exchange of contact and calendar data among computer systems (http://www.imc.org/pdi/pdiproddev.html). The PIM API only supports a subset of the data fields these formats describe. This restriction lets mobile phones interoperate with the largest number of disparate platforms.

Both vCard and vCalendar use clear-text encoding that permits data transfers between devices with 7-bit interfaces, limited bandwidth, and short line lengths—making them ideal for wireless communications. This encoding simplifies the design of the reader/writer programs that manage the data import/export operations. This in turn significantly reduces the processing overhead of both the reader/writer programs, so portable devices can implement them. Both of these formats support 8-bit data transfers.

The PIM API maintains several distinct objects called "lists":

To understand how these lists interface with the native database, I briefly review the J2ME architecture.

Getting Outside of the Box

A J2ME platform consists of a configuration and a profile. A configuration specifies the basic hardware and software required to implement the Java platform on a device, while a profile describes the software required to implement the device's runtime environment and system services. Other profiles can specify additional hardware and their software support classes. For example, a profile might add support for Bluetooth hardware and the Object Exchange (OBEX) protocol to manage file transfers through this wireless interface. A J2ME device has only one configuration layered over the device's hardware and native OS, while multiple profiles can be layered atop of the configuration to add other capabilities.

For most portable devices, the J2ME platform uses the Connected Limited Device Configuration (CLDC). The connection is assumed to be low bandwidth and intermittent, making the configuration suitable for wireless devices. The most common profile present on mobile devices is the Mobile Information Device Profile (MIDP), which defines a runtime execution environment that provides event queues, a GUI, and additional security. Often you'll hear the term "MIDlet" used to describe Java applications written for this profile.

Optional packages extend the capabilities of the J2ME platform, such as support for wireless messaging and multimedia. JSR 75 is also an optional package. Many optional packages extend the capabilities of the MIDP, but JSR 75 extends the CLDC. MIDlets can still use these APIs, however.

The PIM API's capability has important security implications: Personal data that resides outside of the J2ME sandbox security model is no longer sacrosanct. Put another way, an application inside the sandbox can now access information outside of the sandbox, courtesy of the PIM API. To safeguard such data, the PIM API has a security mechanism that implements read-only, write-only, and read/write access controls for the data. In addition, a JSR 75 PIM implementation must respond to any SecurityExceptions its methods throw.

A mobile phone with a MIDP 2.0 profile can extend the PIM API's security with its trusted code mechanism. One aspect of this scheme is that only trusted code in the form of a digitally signed MIDlet can access any privileged (restricted) APIs. For security, phone vendors often implement the PIM API as a restricted API. As a result, a MIDlet has to be digitally signed by a trusted code authority before it is granted access to the PIM API. This reduces the potential for downloading a spyware MIDlet that reads your personal data and phones it home to a hacker. However, bear in mind that the trusted code security mechanism only safeguards access to the API, and not to the data. If a program glitch inadvertently corrupts the information within the native database, you're on your own. Therefore, the promise and peril of the PIM API is that while it grants access to the phone's personal data and so offers great potential for application developers, it also opens the door to great mischief.

PIM Classes and Interfaces

Given the wide diversity of the personal data it handles, the PIM API's object hierarchy is starkly simple. It has six classes, four of which handle exception conditions. The other two classes, PIM and RepeatRule, provide access to the native database or establish a recurring event, respectively. Figure 1 displays the API's class and interface hierarchy. The four exception-handling classes, FieldEmptyException, FieldFullException, PIMException, and UnSupportFieldException, are not shown in the figure. Table 1 lists these classes and interfaces and provides a summary of their purpose.

Another eight interfaces specify how to access PIM data. The PIM API maintains contact, event, and task information through appropriately named Contact, Event, and ToDo interfaces. Each interface contains items that represent various data entries in the database. You access the data within an item's object through the fields the interface provides. Each PIM item defines these fields according to their purpose, such as a NAME field for a contact's name. The PIMItem interface provides access to an item's data through getter/setter methods that manipulate standard Java data types.

PIMItem is the superclass for the Contact, Event, and ToDo interfaces. These interfaces inherit PIMItem's core methods, while extending them to handle the unique characteristics of their data. For example, the Event interface defines a pair of methods used to set or retrieve a RepeatRule object, and it has START and END fields that describe the Event's start and end times.

JSR 75 organizes related PIM items into lists, letting you manage and maintain the PIMItems populating the database. If you need to search through to-do information, then you access the ToDoList. The PIMList interface implements the core functions that create and delete PIMItems. This interface also has methods for organizing the data and examining some of its characteristics. A PIMList also dictates which fields it supports for data storage and retrieval. While a PIMItem specifies all of the possible fields supported by the vCard and vCalendar, it is the corresponding PIMList that determines which fields in the PIMItem the device's PIM implementation actually supports.

Similar to PIMItem, PIMList is the superclass for the ContactList, EventList, and ToDoList interfaces. Each of these interfaces provides specialized methods for importing, creating, and removing the PIMItems that they manage.

Using the PIM API

To make use of the PIM API, your MIDlet code first imports the javax.microedition.pim package. Because the JSR 75 PIM API is an optional package, it may not be present on the mobile phone. A prudent programmer should first discover if the package is present. This is done by invoking System.getProperty() with a query string of microedition.pim.version. If the package is present, the method returns a version number and you're set. If the query returns null, the package is absent and you should present a polite message stating such. One gotcha here is that the CLDC lets a J2ME device refuse to load applications that reference classes missing from its implementation. Because the PIM API is an optional extension to the CLDC, the device might not load the MIDlet, rather than give it a chance to run and check for the PIM API's presence.

Once you've confirmed that the PIM API is available, you obtain an instance of PIM to gain access to the phone's database. Quite often you'll combine this step with an operation that involves fetching a PIM list, as Listing One (available electronically; see "Resource Center," page 5) illustrates. Not only does the code get an instance of PIM, but also opens a ContactList with read and write access.

Now that you've connected to the database, you'll search it for any PIMLists it contains. The listPIMLists() method returns the names of all PIM lists of the specified type (say, EventList) in a String array. The first name in this array is the default list.

With the list names in hand, the next step is to open the desired list with the openPIMList() method. The constants PIM.CONTACT_LIST, PIM.EVENT_LIST, and PIM.TODO_LIST determine the type of list this method opens. Or, a list can be referenced by name. If a name isn't specified, openPIMList() opens the default list of the specified type. Listing Two (also available electronically) locates and opens the default PIMLists. The openPIMList() method is also where you set the list's access mode (read-only, write-only, or read/write). Because you're working with personal data, it goes without saying that you should code defensively and be prepared to catch any exceptions that occur.

We're almost ready to work with a particular PIMItem. However, while an item describes all of its fields from the vCard/vCalendar specifications, recall that the PIM API implementation supports only a subset of them. To confirm support for a particular field, you invoke PIMList's isSupportedField() method, which returns a Boolean value of true if the field is accessible. In addition, you can consult the device's technical documentation to verify which fields the PIM implementation supports. Usually, this information is buried in an appendix or implementation notes, but is well worth tracking down to confirm that the target phone permits access to the desired information.

If the requested field is available, use PIMList's items() method to fetch the list's items. Provide the field name to the PIMItem's countValue() method to obtain the number of data values stored in it. If countValue() returns nonzero, call the appropriate getter/setter methods to read and revise the values. Listing Three (available electronically) shows how to access all of the names in the default Contact list. As a safety feature, none of the changes you make propagate into the native database until you invoke the commit() method. The Sun Microsystems Wireless Toolkit (WTK) Version 2.2 provides an excellent demo MIDlet that uses the JSR 75 PIM API to access and update a mobile phone's database (http://java.sun.com/products/sjwtoolkit/download-2_2.html).

Last but not least, recall that the PIM API can import and export PIM data. The method fromSerialFormat() imports data for one or more PIMItems from an InputStream. The InputStream could be connected to another mobile device, or over the air to a corporate mainframe. The method toSerialFormat() writes one PIMItem to an OutputStream. Listing Four (also available electronically) shows how Contacts can be read from a resource containing vCards to populate a ContactList, and then commit the new information into the native database. I've written a simple demo MIDlet (also available electronically) that imports various PIM items and displays them.

Conclusion

The JSR 75 PIM API offers a standard way to access the database on many mobile phones. This capability lets J2ME developers enhance many existing applications. For example, a wireless messaging application that formerly had to maintain its own list of contacts and electronic addresses can now access the phone's native database for this information. This makes for a smaller (no separate contact list code required) and more robust application (the contact information comes from a reliable native database). In addition, the PIM API offers the means to develop a new breed of person-savvy applications. What might those be? Only time—and the ingenuity of J2ME programmers—will tell.

DDJ

March, 2006: Getting Personal with J2ME's PIM API

Figure 1: The JSR 75 PIM API object hierarchy.

March, 2006: Getting Personal with J2ME's PIM API

(a)

PIM PIM Implements the static methods that gather information about PIM lists and provides access to them. Also handles the import and export of PIM data.
RepeatRule Describes an Event item-s repeating interval, which is used to determine when the associated Event occurs.
FieldEmptyException Thrown when an attempt is made to access a field that doesn-t contain any data values.
FieldFullException Thrown when an attempt is made to add data to a field when all of its data slots are occupied.
PIMException Thrown when a PIM class generates an error.
UnSupportedFieldException Thrown when the PIM list element doesn-t support the referenced field.

(b)

Contact Represents one entry in a Contact database.
ContactList Represents a list that contains Contact items. Also manages access to those items supported by the PIM database.
Event Represents one entry in an Event database.
EventList Represents an event list that contains Event items. Also manages access to those items supported by the PIM database.
PIMItem Defines the core interfaces for accessing an item stored in a PIM list.
PIMList Describes core methods that access and maintain PIM items.

ToDo Represents one entry in a ToDo database.
ToDoList Represents a list that contains ToDo items. Also manages access to those items supported by the PIM database.

Table 1: (a) Class description; (b) interface description.

Terms of Service | Privacy Statement | Copyright © 2024 UBM Tech, All rights reserved.