Vous êtes sur la page 1sur 14

Using JSR 75 : PIM

August 29, 2006

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

Introduction and Background

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:

• Explaining the limitations of the JSR 75 PIM implementation


• Examining the architecture of the PIM package
• Demonstrating code that can read contact data from the phonebook
• Demonstrating code that can create a new Contact in the phonebook
• Providing tips to improve code portability between different Motorola devices

What are the Limitations of JSR 75?

JSR 75 is a protected API

On a Motorola phone the JSR 75 API is protected by a security framework. In order


for an application to run on the phone and use the APIs contained within JSR 75, the
application must be digitally signed with a compatible Motorola developer certificate.

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.

JSR 75 PIM Implementation differs between Device Groups

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.

Architecture of JSR 75 PIM Application

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.

What data can be stored into a Contact object?

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.

Field Name Attributes


Contact.FORMATTED_NAME None
Contact.NICKNAME None
Contact.TEL Pager, Work, Home, Mobile. Fax
Contact.UID None
Contact.BIRTHDAY None

Finally each contact can be assigned to a Category. Categories are predefined by the
handset.

Categories
Business, Personal, VIPs

How to Read Contacts from the Phonebook

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.

PIM myPIM = PIM.getInstance();

Once the PIM database instance has been created the ContactList must be
extrapolated from the PIM database using the following method:

ContactList myContactList = (ContactList)


myPIM.openPIMList(PIM.CONTACT_LIST, PIM.READ_WRITE);

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.

Field Type Of Data Correct method to use


Formatted Name String PIMItem.getString(int field,
int index)
Nickname String PIMItem.getString(int field,
int index)
Telephone String PIMItem.getString(int field,
int index)
Unique ID String PIMItem.getString(int field,
int index)
Birthday Date PIMItem.getDate(int field,
int index)

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));
}
}
}
}

How to Create a New Contact

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 = new Form("Enter new contact");


addContact = new Command("Add", Command.OK, 0);
enterName = new TextField("Enter Name","", 20, TextField.ANY );
enterNick = new TextField("Enter Nick","", 20, TextField.ANY );
enterNumber = new TextField("Enter Tel","", 20, TextField.ANY );

newContactForm.append(enterName);
newContactForm.append(enterNick);
newContactForm.append(enterNumber);
newContactForm.addCommand(addContact);
newContactForm.addCommand(displayPhonebook);
newContactForm.setCommandListener(this);

display.setCurrent(newContactForm);
}

When creating a contact in the PIM database the contactList.createContact()


method is used which returns a new Contact object. The fields are then initialized with
data captured in the form. The following fields of the Contact object are populated. It
is important to note the type of data that each field accepts because the appropriate
method must be used to set its value.

Field Data Type


Contact.FORMATTED_NAME String
Contact.NICKNAME String
Contact.TEL String

In this the example the following method is used to assign the values to the Contact
field:

PIMItem.setString(int field, int index, int attributes,


java.lang.String value);

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:

public boolean PIMItem.PIMisSupportedField(int field);

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();

The code example:


void createNewContact(){

String getName = enterName.getString();


String getNick = enterNick.getString();
String getNumber = enterNumber.getString();
Contact newContact = myContactList.createContact();

//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();
}
}

Tips: Making the Application Portable

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:

Find the list of supported fields on your device


void displayContactListCategories(){
try{
String[] listCategories = myContactList.getCategories();
for(int i = 0; i < listCategories.length ; i++){
System.out.println(listCategories[i]);
}
}
catch(Exception e){
e.printStackTrace();
}
}

Find the list of supported categories on your device

void displayContactListFields(){

int[] arrayFields = myContactList.getSupportedFields();


for(int i = 0; i < arrayFields.length ; i++){
try{
System.out.println(myContactList.
getFieldLabel(arrayFields[i]));
}
catch(Exception e){
e.printStackTrace();
}
}
}

Find out which attributes are supported for each of the fields
void displayFieldAttributes(){

int[] arrayFields = myContactList.getSupportedFields();


for(int i = 0; i < arrayFields.length ; i++){
try{
int attrList[] = myContactList.
getSupportedAttributes(arrayFields[i]);
for(int j=0;j<attrList.length;j++){
System.out.println(myContactList.
getAttributeLabel(attrList[j]));
}
}
catch(Exception e){
e.printStackTrace();
}
}
}

Complete Source Code example

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.pim.*;
import java.util.*;

public class myPIM extends MIDlet implements CommandListener{

//Forms
Form myForm;
Form newContactForm;
//Text Fields
TextField enterName;
TextField enterNick;
TextField enterNumber;

//Display object
Display display;

//ContactList
ContactList myContactList = null;

//Enumeration object for storing contacts in


Enumeration contact;

//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(){

myForm = new Form("Contact PIM");

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();

private void initPIM(){


myForm.deleteAll();
myPIM = PIM.getInstance();
try {
String ContactList[] =
myPIM.listPIMLists(PIM.CONTACT_LIST);
myContactList = (ContactList)
myPIM.openPIMList(PIM.CONTACT_LIST, PIM.READ_WRITE);
contact = myContactList.items();
}
catch (Exception e) {
e.printStackTrace();
}
DisplayContacts();
}

void DisplayNewContactForm(){

newContactForm = new Form("Enter new contact");


addContact = new Command("Add", Command.OK, 0);

enterName = new TextField("Enter Name","", 20,


TextField.ANY);
enterNick = new TextField("Enter Nick","", 20,
TextField.ANY);
enterNumber = new TextField("Enter Tel","", 20,
TextField.ANY);

newContactForm.append(enterName);
newContactForm.append(enterNick);
newContactForm.append(enterNumber);
newContactForm.addCommand(addContact);
newContactForm.addCommand(displayPhonebook);
newContactForm.setCommandListener(this);
display.setCurrent(newContactForm);
}

void createNewContact(){

String getName = enterName.getString();


String getNick = enterNick.getString();
String getNumber = enterNumber.getString();

Contact newContact = myContactList.createContact();

//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(){

int[] arrayFields = myContactList.getSupportedFields();


myForm.append("Supported Fields \n");
for(int i = 0; i < arrayFields.length ; i++){
try{
myForm.append(myContactList.
getFieldLabel(arrayFields[i]) + "\n");
}
catch(Exception e){
e.printStackTrace();
}
}
}

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");
}
}
}
}
}

public void startApp() {


}

public void pauseApp() {


}

public void destroyApp(boolean unconditional) {


}

public void commandAction(Command c, Displayable d) {

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:

JAD and MANIFEST Attribute Declarations

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

Digital Signing of MIDlet against Development Certificate

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

Java Community Process: JSR 75


Motorola Java ME SDK for Motorola OS Products

Vous aimerez peut-être aussi