Académique Documents
Professionnel Documents
Culture Documents
TECHNICAL ARTICLE
Using JSR 75 PIM
By
MOTODEV Staff
Contents
Introduction and Background .................................................................................... 2
What are the Limitations of JSR 75?......................................................................... 3
JSR 75 is a protected API ...................................................................................... 3
JSR 75 PIM Implementation differs between Device Groups............................... 3
Architecture of JSR 75 PIM Application................................................................... 3
What data can be stored into a Contact object?......................................................... 4
How to Read Contacts from the Phonebook.............................................................. 4
How to Create a New Contact ................................................................................... 6
Tips: Making the Application Portable...................................................................... 8
Find the list of supported fields on your device .................................................... 8
Find the list of supported categories on your device ............................................. 8
Find out which attributes are supported for each of the fields .............................. 9
Complete Source Code example................................................................................ 9
Security Considerations ........................................................................................... 14
JAD and MANIFEST Attribute Declarations...................................................... 14
Digital Signing of MIDlet against Development Certificate............................... 14
References................................................................................................................ 14
The Holy Grail in many enterprise applications resides in the ability to synchronize
Personal Information Management (PIM) data from one device to another over an
established network connection. In order for a Java ME application to access a
device’s native PIM database the device must support the JSR 75 PIM package. The
APIs provided in this package give application developers the ability to build Java
ME applications that can interact with the device’s PIM data.
This article shows how JSR 75 can be used to build a phonebook application on a
Motorola handset, targeting devices categorized in the A.4 emulator:
• L2/L6
• PEBL
• V3(CLDC 1.1)
• RAZR V3i
• ROKR E1
• SLVR
• V190/V191
• V230/V235
• V360/V361
• V557/V557p
There are minor differences in the implementations of JSR 75 PIM between devices
listed in the A.4 emulator and A.3 emulator. This is due to small differences in
implementation of the Contact class with respect to the supported fields in these two
device groups. Therefore the majority of the information contained in this article is
pertinent to both device groups but there maybe some incompatibility when applying
it to the devices in the A.3 emulator group. The purpose of this article is to
demonstrate how to build a JSR 75 PIM Java ME application by:
Although it is possible to run a MIDlet on the Emulator using JSR75 without digital
signing of the MIDlet, a real handset will generate a SecurityException when the API
is accessed unless the application has been signed.
The implementation of JSR75 (PIM) differs between the A.3 and A.4 Emulator device
groups. These differences are minor but should be noted when developing a PIM
MIDlet from a portability perspective. Please consult documentation supplied in the
Motorola SDK for more information.
Looking at the PIM API the first thing to notice is the architecture of this package and
how the hierarchy of classes are tiered and interact with each other. The diagram
below gives an overview on the relationship between the different classes.
com.motorola.pim
com.motorola.pim.PIMList
com.motorola.pim.ContactList
com.motorola.pim.PIMItem
com.motorola.pim.Contact
The Contact class defines the supported types of information that are accessible in a
Contact object. The main methods in the Contact class are inherited from the PIMItem
class, which provides a range of methods for interacting with the data in a Contact
object – for example, inserting a value for the Telephone field. Contacts are stored in
a ContactList which provides high level administration tasks such as creating a new
Contact or removing an existing Contact from the list. ContactList is a subclass of
PIMList, which has further high level responsibilities for administering the other
available PIM lists on a phone such as the EventList. Finally a PIMList is initialized
from a PIM object, which is created from the instance of the whole PIM database on
the phone.
When creating a new contact using the native phonebook application on the handset,
there are many fields in which to store data. Only a subset of those fields are
supported in the Java ME environment. The table below displays the main supported
fields that make up the JSR 75 implementation of a contact.
Field Details
Formatted Name This is the main name of the contact
Nickname Short name of contact
Telephone Main telephone number for the contact
Unique ID Every contact must have a unique ID entry
Birthday Birthday for the contact
It is possible that each field can have specific attributes which provide additional
information. The supported attributes for the fields above are predefined by the
device.
Finally each contact can be assigned to a Category. Categories are predefined by the
handset.
Categories
Business, Personal, VIPs
Any MIDlet that utilizes the JSR75 API must first import the PIM package using the
following import statement:
import javax.microedition.pim.*;
To be able to read or write to the PIM contact database an instance of the PIM
database on the handset must be created.
Once the PIM database instance has been created the ContactList must be
extrapolated from the PIM database using the following method:
All Contact items contained in the ContactList can then be extracted and put into an
enumeration object using the following method:
Enumeration contact = myContactList.items();
Each contact can now be extracted consecutively from the enumeration object and the
data stored in their fields can be accessed.
For the purpose of this demonstration data is extracted and displayed from the name
and the phone number fields. This is done for each Contact object by first returning an
array of fields for that Contact, iterating through this array and extracting the data
when the fields match either Contact.FORMATTED_NAME or Contact.TEL. To extract
the data from a field you should refer to the methods provided for in the PIMItem
class.
Additionally, the example below also demonstrates how to show the category in
which the contact has been placed and how to discern the telephone number attribute.
Void DisplayContacts(){
while (contact.hasMoreElements()) {
c = (Contact) contact.nextElement();
int[] Fields = c.getFields();
String[] catArray = c.getCategories();
for(int ii = 0; ii < catArray.length ; ii++){
System.out.println("Category :" + catArray[ii]);
}
for(int i = 0; i < Fields.length ; i++){
String field = myContactList.getFieldLabel(Fields[i]);
if(Fields[i] == Contact.FORMATTED_NAME){
System.out.println("Name : " +
c.getString(Fields[i],0));
}
if(Fields[i] == Contact.TEL){
int att = c.getAttributes(Fields[i],0);
String attributeLabel =
myContactList.getAttributeLabel(att);
System.out.println(attributeLabel +
c.getString(Fields[i],0));
}
}
}
}
The following code example provides a basic Form that allows a user to enter details
for a new Contact. It provides three text fields for Name, Nickname and Phone
number:
void DisplayNewContactForm(){
newContactForm.append(enterName);
newContactForm.append(enterNick);
newContactForm.append(enterNumber);
newContactForm.addCommand(addContact);
newContactForm.addCommand(displayPhonebook);
newContactForm.setCommandListener(this);
display.setCurrent(newContactForm);
}
In this the example the following method is used to assign the values to the Contact
field:
For portability requirements of your application you may also want to verify that the
field that you wish to populate is actually supported on the phone, this can be done by
using the following methods:
Finally, once all the fields of the contact have been populated they can be written to
the the new Contact object and to the ContactList:
PIMItem.commit();
//Name
if (myContactList.isSupportedField(Contact.FORMATTED_NAME)){
try{
newContact.addString(Contact.FORMATTED_NAME,
PIMItem.ATTR_NONE, getName);
}
catch(Exception e){
e.printStackTrace();
}
}
else{
System.out.println("THIS IS NAME");
}
//NickName
if (myContactList.isSupportedField(Contact.NICKNAME)){
try{
newContact.addString(Contact.NICKNAME,
Contact.ATTR_MOBILE, getNick);
}
catch(Exception e){
e.printStackTrace();
}
}
//Telephone
if (myContactList.isSupportedField(Contact.TEL)){
try{
newContact.addString(Contact.TEL, PIMItem.ATTR_NONE,
getNumber);
}
catch(Exception e){
e.printStackTrace();
}
}
try{
//write the new Contact to the PIM database
newContact.commit();
System.out.println("Contact Added \n");
}
catch(Exception e){
e.printStackTrace();
}
}
In order to make the MIDlet portable you need to be able to discover the fields,
categories and attributes supported by the implementation on the target handset. The
following code example demonstrates how these can be discovered on the actual
device at runtime:
void displayContactListFields(){
Find out which attributes are supported for each of the fields
void displayFieldAttributes(){
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.pim.*;
import java.util.*;
//Forms
Form myForm;
Form newContactForm;
//Text Fields
TextField enterName;
TextField enterNick;
TextField enterNumber;
//Display object
Display display;
//ContactList
ContactList myContactList = null;
//Contact
Contact c = null;
//Commands
Command contactDB;
Command displayPhonebook;
Command enterContact; //Take to contact input form
Command addContact; //Commit contact to DB
Command showFields;
Command showFieldAttributes;
Command showCategories;
Command clearScreen;
//PIMS
PIM myPIM;
public myPIM(){
display = Display.getDisplay(this);
displayPhonebook = new Command("PhoneBook",Command.OK, 0);
enterContact = new Command("EnterContact",Command.OK, 0);
showFields = new Command("Fields",Command.OK, 0);
showFieldAttributes = new Command("Attributes",Command.OK,
0);
showCategories = new Command("Categories",Command.OK, 0);
clearScreen = new Command("Clear Screen",Command.OK, 0);
myForm.addCommand(displayPhonebook);
myForm.addCommand(enterContact);
myForm.addCommand(showFields);
myForm.addCommand(showFieldAttributes);
myForm.addCommand(showCategories);
myForm.addCommand(clearScreen);
myForm.setCommandListener(this);
display.setCurrent(myForm);
myPIM = PIM.getInstance();
initPIM();
void DisplayNewContactForm(){
newContactForm.append(enterName);
newContactForm.append(enterNick);
newContactForm.append(enterNumber);
newContactForm.addCommand(addContact);
newContactForm.addCommand(displayPhonebook);
newContactForm.setCommandListener(this);
display.setCurrent(newContactForm);
}
void createNewContact(){
//Name
if (myContactList.isSupportedField(Contact.FORMATTED_NAME)){
try{
newContact.addString(Contact.FORMATTED_NAME,
PIMItem.ATTR_NONE, getName);
}
catch(Exception e){
e.printStackTrace();
}
}
else{
System.out.println("THIS IS NAME");
}
//NickName
if (myContactList.isSupportedField(Contact.NICKNAME)){
try{
newContact.addString(Contact.NICKNAME,
Contact.ATTR_MOBILE, getNick);
}
catch(Exception e){
e.printStackTrace();
}
}
//Telephone
if (myContactList.isSupportedField(Contact.TEL)){
try{
newContact.addString(Contact.TEL, PIMItem.ATTR_NONE,
getNumber);
}
catch(Exception e){
e.printStackTrace();
}
}
try{
//write the new Contact to the PIM database
newContact.commit();
System.out.println("Contact Added \n");
}
catch(Exception e){
e.printStackTrace();
}
}
void displayContactListFields(){
void displayContactListCategories(){
try{
String[] listCategories = myContactList.getCategories();
myForm.append("Supported Categories");
for(int i = 0; i < listCategories.length ; i++){
myForm.append(listCategories[i] + "\n");
}
}
catch(Exception e){
e.printStackTrace();
}
}
void displayFieldAttributes(){
int[] arrayFields = myContactList.getSupportedFields();
for(int i = 0; i < arrayFields.length ; i++){
try{
myForm.append("\n" +
myContactList.getFieldLabel(arrayFields[i]) + " : ");
int attrList[] = myContactList.
getSupportedAttributes(arrayFields[i]);
for(int j=0;j<attrList.length;j++){
myForm.append(myContactList.
getAttributeLabel(attrList[j]) + " ");
}
}
catch(Exception e){
e.printStackTrace();
}
}
}
void DisplayContacts(){
while (contact.hasMoreElements()) {
c = (Contact) contact.nextElement();
int[] Fields = c.getFields();
String[] catArray = c.getCategories();
for(int ii = 0; ii < catArray.length ; ii++){
myForm.append("Category :" + catArray[ii] + "\n");
}
for(int i = 0; i < Fields.length ; i++){
String field = myContactList.getFieldLabel(Fields[i]);
if(Fields[i] == Contact.FORMATTED_NAME){
myForm.append("Name : " + c.
getString(Fields[i],0) + "\n");
}
if(Fields[i] == Contact.TEL){
int att = c.getAttributes(Fields[i],0);
String attributeLabel =
myContactList.getAttributeLabel(att);
if(attributeLabel.compareTo("NONE") < 0){
myForm.append(attributeLabel + " : " +
c.getString(Fields[i],0) + "\n");
}
else{
myForm.append("Telephone : "+
c.getString(Fields[i],0) + "\n");
}
}
}
}
}
if(c == displayPhonebook){
initPIM();
display.setCurrent(myForm);
}
else
if(c == enterContact){
DisplayNewContactForm();
}
else
if(c == addContact){
createNewContact();
DisplayNewContactForm();
}
else
if (c == showFields){
displayContactListFields();
}
else
if(c == showFieldAttributes){
displayFieldAttributes();
}
else
if(c == showCategories){
displayContactListCategories();
}
else
if(c == clearScreen){
myForm.deleteAll();
}
}
Security Considerations
As JSR 75 PIM is protected by the KVM security framework it is not accessible from
a MIDlet unless these two requirements are met:
The following JAD MIDlet-Permission attribute values are pertinent to JSR 75 PIM:
javax.microedition.pim.ContactList.read
javax.microedition.pim.ContactList.write
javax.microedition.pim.EventList.read
javax.microedition.pim.EventList.write
javax.microedition.pim.ToDoList.read
javax.microedition.pim.ToDoList.write
An example JAD attribute permission statement (this should be placed in the JAD and
MANIFEST.MF files:
MIDlet-Permissions: javax.microedition.pim.ContactList.read,
javax.microedition.pim.ContactList.write
In order for the MIDlet to access the PIM, it must be digitally signed against a
Motorola development certificate. For more information about obtaining a
development certificate, please see the Development MIDlet Signing Process FAQ.
References