|
Mobile handsets such as cellphones typically have an address book to keep track of people we like to stay in touch with, a calendar to keep track of important events, and a to-do list to keep track of items we don't want to forget. This type of personal information is one of the most important functions found in a handset, just second to voice. You can use the PIM API for Java ME to enable your mobile Java applications to read and write to/from the locally stored personal information databases. You can even write synchronizers to keep your handset PIM data in-sync with remote PIM data stores. This article, the first part in a series of articles on using the PIM API for Java ME, provides a comprehensive introduction to the PIM API.
Contents
The PIM API for Java ME is an optional package defined in the Java Specification Request (JSR) 75. The PIM API allows applications to manage PIM data that is stored on the handset.
The PIM API and the Mobile Service Architecture
The PIM API is one of the mandated APIs as defined by the Mobile Service Architecture (MSA) specification.
|
|
The PIM API is encapsulated in a single Java package javax.microedition.pim, which defines the following interfaces, classes and exceptions:
Table 1: the javax.microedition.pim Optional Package
 |
Interfaces: |
Contact, ContactList, Event, EventList, PIMItem, PIMList, ToDo, and ToDoList.
|
Classes: |
PIM and RepeatRule.
|
Exceptions: |
FieldEmptyException, FieldFullException, PIMException, and UnsupportedFieldException.
|
The API is designed around the organization of the PIM data itself. PIM data is organized into databases or lists. Multiple lists can exist -for calendar events, address-book contacts, and to-do items. PIM lists contain items which are groupings of related fields. A field consists of a label, a data type, values, and attributes. This relationship is illustrated here:
Figure 1: PIM data organization
|
In this data model, PIM lists or databases are represented by interface javax.microedition.pim.PIMList and its sub-interfaces. PIM items are represented by interface javax.microedition.pim.PIMItem and its sub-interfaces. Fields are represented by the corresponding Java data type such as String, Date, int, boolean and arrays of bytes and Strings.
The PIM Class
At the center of the PIM API is the abstract PIM class that provides access to the PIM implementation. The PIM class exposes a static method to retrieve the PIM instance itself, and abstract methods to manage the PIM lists/databases, and to import and export PIM data:
getInstance() - static method to retrieve the PIM instance that allows you to manage the local PIM
listPimList(...) - abstract method to get the names of existing PIM databases
openPimList(...) - abstract method to open the default database, or open a specific database by name
fromSerialFormat(...) and toSerialFormat(...) - abstract methods to import and export PIM data respectively
supportedSerialFormats(...) - abstract method get the supported PIM data exchange formats such as vCard version 2.1 and vCalendar version 1.0
The PIMList Interface and Sub-Interfaces
The PIM class provides access to the PIM lists. Think of PIM lists as the PIM databases themselves. PIM lists are represented by the PIMList interface and its sub-interfaces as described next:
Figure 2: The PIMList Interface and Sub-Interfaces
|
...where:
PIMList represents a PIM database in general
ContactList represents the contact list database
EventList represents the calendar events database
ToDoList represents the to-do list database
The PIMList super-interface exposes a large number of methods to manage or discover the list's categories, supported fields and related information, to retrieve all or some of the PIM items on the list, and methods for retrieving the list name and for closing the list to release resources. The PIMList methods are summarized next:
- Miscellaneous methods:
close, getName
- Category related methods:
addCategory, deleteCategory, getCategories, isCategory, maxCategories, renameCategory
- Field related methods:
getFieldDataType, getSupportedArrayElements, getSupportedFields, isSupportedArrayElement, isSupportedField, maxValues, stringArraySize
- Field label related methods:
getArrayElementLabel, getAttributeLabel, getFieldLabel
- Field attribute related methods:
getSupportedAttributes, isSupportedAttribute
- Methods
items(...) to enumerate some or all the items in the list, and method itemsByCategory to list all items for specified category
The sub-interfaces ContactList, EventList and ToDoList expose methods that are specific to the type of PIM database (sub-interface), for example:
ContactList exposes all the methods inherited from PIMList, plus methods to create, remove, and import a contact item - createContact(), removeContact(...), importContact(...)
EventList exposes all the methods inherited from PIMList, plus methods to create, remove, import event items, as well as a method to search events that fall within a specified date range, and a method to discover the (recurring) event's supported RepeatRule fields for a given frequency - createEvent(), getSupportedRepeatRuleFields(...), importEvent(...), items(...), removeEvent(...)
ToDoList exposes all the methods inherited from PIMList, plus methods to create, remove and import to-do items, as well as a method to search for items that fall within a specified date range - createToDo(), importToDo(...), items(...), removeToDo(...)
The PIMItem Interface and Sub-Interfaces
PIM lists are collections of PIM items. Think of PIM items as the rows or records of the database. PIM items are represented by the PIMItem super-interface and its sub-interfaces as described next:
Figure 3: The PIMItem Interface and Sub-Interfaces
|
...where PIMItem exposes methods to manage the item's fields and attributes:
PIMItem is a generalization of PIM data, such as contact, calendar or a to-do item
Contact represents a contact item in the address book database
Event represents an event in the calendar database
ToDo represents a to-do item in the To-Do database
PIMItem super-interface exposes a large number of methods: to manage the list's categories, to get all the fields for an item, manage a field's values, attributes, and to save changes to the list. The PIMItem methods are summarized next:
- Get the PIM list associated with an item:
getPIMList
- Get all fields for the item:
getFields
- Add a value to a field:
addBinary, addBoolean, addDate, addInt, addString, addStringArray
- Get a value from a field:
getBinary, getBoolean, getDate, getInt, getString, getStringArray
- Set (update) a field value:
setBinary, setBoolean, setDate, setInt, setString, setStringArray
- Remove the value from a field:
removeValue
- Find out the number of values on a specific field:
countValues
- Get all field attributes:
getAttributes
- Test if a specific item has changed since last commit:
isModified
- Save item:
commit
- Manage categories; items can be tagged by associating one or more categories with it:
addToCategory, getCategories, removeFromCategory, maxCategories. See the section Using Categories for more information.
PIMItem sub-interfaces Contact, Event, and ToDo expose methods that are particular to their type, for example:
- Contact exposes all the methods inherited from
PIMItem, plus a method to get the preferred index for multi-value fields: getPreferredIndex(...)
- Event exposes all the methods inherited from
PIMItem, plus methods to get and set the RepeatRule for the event: getRepeat(), setRepeat(...)
- ToDo only exposes all the same methods that inherited from
PIMItem
- In addition, all the above interfaces also define a number of constants that represent the various supported fields and attributes for the particular
PIMItem
The Fields
PIM items are groupings of related fields. Fields are specific to the type of PIM Item. For example, a calendar event item consists of fields such as start and end-event times, event description, location, and other. The address-book item contain fields such as first and last-names, home and work phone numbers and addresses, email address, and so on. Fields have an id, a descriptive label, a data type, values, and attributes, as illustrated next:
Figure 4: Structure of PIM fields, using Contact as an example
|
Fields are uniquely identified within a given PIM list/item by field ID. Field IDs are constants that are defined by the specific PIM item Contact, Event and ToDo. For example, the Contact PIM item defines the fields Contact.NAME (with field id of 106) and Contact.ADDR (with a field ID of 100), and Contact.EMAIL (with field ID of 103), while Event and ToDo define their own field IDs-refer to the Javadoc for more information.
Fields are considered either standard or extended fields. Standard fields are the common fields that should be available across PIM implementations. Extended fields are PIM implementation specific fields that must be discovered. All supported fields, both standard and extended, can be discovered by calling the method getSupportedFields() for the particular PIM list. Extended fields are easy to identify because their field IDs are values that are greater than or equal to PIMItem.EXTENDED_FIELD_MIN_VALUE.
UID is a Special Kind of Field
The UID field is a special field that uniquely identifies a PIM item; each specific PIMItem interface (Contact, Event and ToDo) defines a UID field. The field's UID is a String that is assigned by the platform at the time the item is saved (committed), and exists for the life of the PIM item. You can use the UID to test for identify using the String.equals() method. You can test if an item has been assigned a UID by calling the method countValues(UID) passing for argument the UID. The UID value can be reused by the platform if the item is removed. Use this field to uniquely identify and correlate the PIM item for example during data synchronization.
|
|
Labels
The field's label is a String that describes the field. To discover a field's label call the PIMList method getFieldLabel(int field ID), passing as argument the field ID of interest.
Data Types
Field data types are: INT, BINARY, BOOLEAN, DATE, STRING_ARRAY or STRING, as defined in PIMList. To discover a field's data type, call the PIMList method PIMList.getFieldDataType(int field ID), passing as argument the field ID of interest. The following table shows all the defined standard PIM fields and their associated data type:
Table 2: PIMItem Fields and Data Types
 |
NAME, ADDR |
PIMItem.STRING_ARRAY
|
EMAIL, FORMATTED_NAME, NICKNAME, NOTE, ORG, TEL, TITLE, UID, URL, PHOTO_URL, PUBLIC_KEY_STRING
|
PIMItem.STRING
|
BIRTHDAY, REVISION |
PIMItem.DATE
|
PHOTO, PUBLIC_KEY |
PIMItem.BINARY
|
LOCATION, NOTE, SUMMARY, UID |
PIMItem.STRING
|
END, REVISION, START |
PIMItem.DATE
|
ALARM, CLASS |
PIMItem.INT
|
NOTE, SUMMARY, UID |
PIMItem.STRING
|
CLASS, PRIORITY |
PIMItem.INT
|
COMPLETION_DATE, DUE, REVISION |
PIMItem.DATE
|
COMPLETED |
PIMItem.BOOLEAN
|
Data Values
Fields can have zero or more data values. Simple fields are represented by the corresponding Java data type, while a multi-value or compound field is represented by an array, such as String or byte arrays. And example of a multi-value field is NAME, which consists of first, middle and last name. To manipulate the field's value, you first need to know or discover its data type as mentioned above, then invoke the appropriate add (new value), get (retrieve value) or set (update value) method. The following table shows the different methods to manipulate PIM fields:
Table 3: PIMItem Field Add, Set, and Get Methods
 |
BINARY |
addBinary(...)
|
getBinary(...)
|
setBinary(...)
|
BOOLEAN |
addBoolean(...)
|
getBoolean(...)
|
setBoolean(...)
|
DATE |
addDate(...)
|
getDate(...)
|
setDate(...)
|
INT |
addInt(...)
|
getInt(...)
|
setInt(...)
|
STRING |
addString(...)
|
getString(...)
|
setString(...)
|
STRING_ARRAY |
addStringArray(...)
|
getStringArray(...)
|
setStringArray(...)
|
...where arguments are field ID, value-index (0 for single-value fields), attributes, and data value as appropriate-please refer to the Javadoc for more information.
Attributes
Attributes further define field data values. For example, a Telephone (Tel) field, which has a data type of PIMItem.STRING, can be further qualified using predefined attributes such as the home telephone number (ATTR_HOME), work telephone number (ATTR_WORK), mobile telephone number (ATTR_MOBILE) or other type of telephone number. Attributes are optional, and are specified when adding data values to a field-see the add methods in Table 3. To discover the attributes for a given field call the PIMItem method getAttributes(fieldID, valueIndex), passing as arguments the field ID and the value-index of interest. Use PIMItem.ATTR_NONE to explicitly indicate that a field has no assigned attributes.
Not all Fields and Attributes Might be Supported
Some PIM implementations are more complete than others; some implementations may or not support all the fields and attributes defined in the PIM API specification. Before using a specific field or attribute, you should test if it is supported by the underlying PIM implementation by calling the appropriate isSupportedXXX(...) method, otherwise the code will throw (and you must catch) the javax.microedition.pim.UnsupportedFieldException that will result when trying to access an unsupported field.
The RepeatRule Class
Calendar events can be recurring events. Recurring events are defined by using repeat rules, as defined by the RepeatRule class. The RepeatRule class is very flexible, and as in the case of PIMItem, it exposes generic methods based on the concepts of fields, field types and field data values, but in this case is to set the repeat rules. The following table shows the RepeatRule fields, methods, and valid values:
Table 4: RepeatRule Fields and Data-types
 |
FREQUENCY
|
setInt
|
DAILY, WEEKLY, MONTHLY, YEARLY
|
COUNT
|
setInt
|
Any positive int |
INTERVAL
|
setInt
|
Any positive int |
END
|
setDate
|
Any valid Date |
MONTH_IN_YEAR
|
setInt
|
JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER (Note: these are different from ones in Calendar class)
|
DAY_IN_WEEK
|
setInt
|
SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY (Note: these are different from ones in CLDC Calendar class)
|
WEEK_IN_MONTH
|
setInt
|
FIRST, SECOND, THIRD, FOURTH, FIFTH, LAST, SECONDLAST, THIRDLAST, FOURTHLAST, FIFTHLAST
|
DAY_IN_MONTH
|
setInt
|
1-31 |
DAY_IN_YEAR
|
setInt
|
1-366 |
As in the case of PIM items, a particular PIM implementation may or not support all the repeat rule fields as defined in the JSR 75 specification. Before using a particular RepeatRule field, you should test if it is supported by the underlying implementation by calling the EventList method getSupportedRepeatRuleFields(int frequency), passing for argument the repeat rule frequency. Attempting to use an unsupported RepeatRule field will result in a java.lang.IllegalArgumentException being thrown that you must catch.
Many thanks to Kevin Lym, Vasily Isaenko, and Alexander.Glasman for all their feedback and helping improve this article.
C. Enrique Ortiz is a mobile technologist, software architect and developer, and a writer and blogger. He has been author or co-author of many publications, and is an active participant in the Java mobility community and in various Java ME Expert Groups. Enrique holds a B.S. in Computer Science from the University of Puerto Rico and has more than 17 years of software engineering, product development, and management experience.
|
|