JSR 75 PIM

Cosc 4755
Personal Information Manager
JSR-75
Optional PIM package
PIM
• Personal Information Managers
– Contacts
• including the phone contacts info
– Calendars
• events, recurring and alarms
– lists
• To-Do lists.
– uses a subset of the Vcard and Vcalendar
specifications.
• Package
– import javax.microedition.pim.*;
Optional Package
• Like others, is the package installed?
// Check that PIM Optional Package is available
String v = System.getProperty(
"microedition.pim.version" );
if( v != null ){
// PIMOP available
} else {
// PIMOP not available
}
//NOT necessary on Blackberry, the PIM package
is installed.
PIM Package
PIM
<<Opens>>
PIMList
via enumeration interface
<<extends>>
PIMItem
<<extends>>
•ContactList
•Contact
•ToDoList
•ToDo
•EventList
•Event
RepeatRule
•Used with Event
PIM
• With a security model, but assuming your app has
permission
– view the information
– add/remove/modify information
• We will work this the "default" of PIM. This should
allow you access to information, that the "phone"
app's use, such as the contact list for dialing.
• Outside the simulators, you app will need to be signed.
– Think of the damage this package can allow!
Opening the "database"
//static method.
PIM singleton = PIM.getInstance();
• Now which of the three do we want
– PIM.CONTACT_LIST, PIM.EVENT_LIST, PIM.TODO_LIST
• And PIM.READ_ONLY, PIM.READ_WRITE, or PIM.WRITE_ONLY.
ContactList cl = (ContactList)
singleton.openPIMList( PIM.CONTACT_LIST,
PIM.READ_ONLY );
EventList el = (EventList)
singleton.openPIMList( PIM.EVENT_LIST,
PIM.READ_ONLY );
ToDoList tl = (ToDoList) singleton.openPIMList(
PIM.TODO_LIST, PIM.READ_ONLY );
PIMList and PIMItem
• All three lists inherit from a PIMList
• All three “items” inherit from PIMItem
– You can just use PIMList and PIMItem instead of
the others, but easier not too.
ContactList
• Contact createContact()
– Factory method to create a Contact for this contact
list.
• Returns a blank contact that has been entered into the
contact list.
• Contact importContact(Contact contact)
– Imports the given Contact into this contact list by
making a new Contact for the list and filling its
information with as much information as it can from
the provided Contact.
• void removeContact(Contact contact)
– Removes a specific Contact from the list.
ContactList (2)
• There are more methods, but the primary is
• Enumeration items()
– Return an Enumeration of all items in the list.
• The order is undefined.
• Throws:
– PIMException
• If an error occurs or the list is no longer accessible or closed.
– java.lang.SecurityException
• if the application is not given permission to read the PIM list
or the list is opened WRITE_ONLY.
ContactList (3)
• Category methods, to set/remove/rename
categories. IE work, personal, etc.
• And field and attribute methods
– We’ll look at those as we are dealing with contact.
Getting an Contact
try {
Enumeration enum = cl.items();
while( enum.hasMoreElements() ){
Contact contact = (Contact) enum.nextElement();
// do something with the contact
}
} catch( PIMException e ){
// an error occurred }
catch( SecurityException e ){
// can't read this list
}
Contact
Fields
Type of Data Associated with Field
NAME, ADDR
PIMItem.STRING_ARRAY
EMAIL, FORMATTED_NAME, NICKNAME,
NOTE, ORG, TEL, TITLE, UID, URL
PIMItem.STRING
BIRTHDAY, REVISION
PIMItem.DATE
PHOTO, PUBLIC_KEY
PIMItem.BINARY
PHOTO_URL, PUBLIC_KEY_STRING
PIMItem.STRING
CLASS
PIMItem.INT
Attributes, which may or may not apply to the all of the above fields
ATTR_ASST (ASSISTANT), ATTR_AUTO, ATTR_FAX, ATTR_HOME, ATTR_MOBILE,
ATTR_OTHER, ATTR_PAGER, ATTR_SMS, ATTR_WORK,
ATTR_PREFERRED (Attribute classifying a data value with preferred status for
retrieval or display purposes [platform specific])
ATTR_NONE (meaning there is no attribute for that field)
Retrieving contact info
• You need to use try caught around the get methods. If
the field is not support, it throws an exception
– If the value of the field is blank, it also throws an
exception!
• Example, lets get the FORMATTED_NAME
try {
String str = contact.getString(Contact.FORMATTED_NAME, 0);
System.out.println("FN: "+str);
} catch ( java.lang.IndexOutOfBoundsException e) {
//The field is blank!
} catch (UnsupportedFieldException e) {
//That field is not supported
}
Retrieving contact info (2)
• Retrieving the name fields
try {
String str1[] =
contact.getStringArray(Contact.NAME, 0);
for (int i = 0; i < str1.length; i++) {
System.out.println("Name: " +str1[i]);
}
} catch ( java.lang.IndexOutOfBoundsException e) {
//The field is blank!
} catch (UnsupportedFieldException e) {
//That field is not supported
}
• NOTE: Name has NAME_FAIMLY, NAME_GIVEN, NAME_OTHER,
NAME_PREFIX, and NAME_SUFFIX
Creating a new contact
• First a blank contact
Contact contact = contacts.createContact();
• Now add the information
String[] name = new String[contacts.stringArraySize(Contact.NAME)];
if (contacts.isSupportedField(Contact.FORMATTED_NAME))
contact.addString(Contact.FORMATTED_NAME, PIMItem.ATTR_NONE, "Mr. John Q. Public, Esq.");
if (contacts.isSupportedArrayElement(Contact.NAME, Contact.NAME_FAMILY))
name[Contact.NAME_FAMILY] = "Public";
if (contacts.isSupportedArrayElement(Contact.NAME, Contact.NAME_GIVEN))
name[Contact.NAME_GIVEN] = "John";
contact.addStringArray(Contact.NAME, PIMItem.ATTR_NONE, name);
if (contacts.isSupportedField(Contact.TEL))
contact.addString(Contact.TEL, Contact.ATTR_HOME, "613-123-4567");
try {
contact.commit(); //until a commit() the record is not updated!
} catch (PIMException e) {
// An error occurred
}
updating a contact
•
•
Assuming contact is the contact we want to update, it is just like creating a new one.
We'll add an address.
String[] addr = new String[contacts.stringArraySize(Contact.ADDR)];
if (contacts.isSupportedArrayElement(Contact.ADDR, Contact.ADDR_COUNTRY))
addr[Contact.ADDR_COUNTRY] = "USA";
if (contacts.isSupportedArrayElement(Contact.ADDR, Contact.ADDR_LOCALITY))
addr[Contact.ADDR_LOCALITY] = "Coolsville";
if (contacts.isSupportedArrayElement(Contact.ADDR, Contact.ADDR_REGION))
addr[Contact.ADDR_REGION] = "Wyoming";
if (contacts.isSupportedArrayElement(Contact.ADDR, Contact.ADDR_POSTALCODE))
addr[Contact.ADDR_POSTALCODE] = "91921-1234";
if (contacts.isSupportedArrayElement(Contact.ADDR, Contact.ADDR_STREET))
addr[Contact.ADDR_STREET] = "123 Main Street";
if (contacts.isSupportedField(Contact.ADDR))
contact.addStringArray(Contact.ADDR, Contact.ATTR_HOME, addr);
//Note there is also ADDR_EXTRA, and ADDR_POBOX
try { contact.commit(); } catch (PIMException e) {
// An error occurred
}
ToDoList
• Very similar to contacts
–
•
Note this one and calendar are less likely to be implemented on all phones.
ToDo createToDo()
– Factory method to create a ToDo entry for this ToDo list.
• ToDo importToDo(ToDo item)
– Imports the given ToDo into this list by making a new ToDo for the list and
filling its information with as much information as it can from the provided
ToDo.
• void removeToDo(ToDo item)
– Removes a specific ToDo from the list.
• java.util.Enumeration items(int field, long startDate, long endDate)
– Return an enumeration of all the ToDos in the list where the value of the
specified date field falls in the range from startDate to endDate inclusive.
• The data for Date is expressed in the same long value format as java.util.Date, which is
milliseconds since the epoch (00:00:00 GMT, January 1, 1970).
• To get all the ToDO items, use items() like from contacts.
ToDo Item
Fields
Type of Data Associated with Field
NOTE, SUMMARY, UID
PIMItem.STRING
CLASS, PRIORITY
PIMItem.INT
COMPLETION_DATE, DUE, REVISION
PIMItem.DATE
COMPLETED
PIMItem.BOOLEAN
There are no attributes for the ToDo fields.
Example creating an ToDo
ToDoList todos = null;
try {
todos = (ToDoList) PIM.getInstance().openPIMList(PIM.TODO_LIST, PIM.READ_WRITE);
} catch (PIMException e) {
// An error occurred
}
ToDo todo = todos.createToDo();
if (todos.isSupportedField(Event.SUMMARY))
todo.addString(ToDo.SUMMARY, PIMItem.ATTR_NONE, "Buy going away present for Judy");
if (todos.isSupportedField(ToDo.DUE))
//note import java.util.Date; is needed!
todo.addDate(ToDo.DUE, PIMItem.ATTR_NONE, new Date().getTime());
if (todos.isSupportedField(ToDo.NOTE))
todo.addString(ToDo.NOTE, PIMItem.ATTR_NONE, "Judy really likes stained glass");
if (todos.isSupportedField(ToDo.PRIORITY))
todo.addInt(ToDo.PRIORITY, PIMItem.ATTR_NONE, 2);
try { //We'll come back to categories at the end of the lecture
if (todos.maxCategories() != 0 && todos.isCategory("Work"))
todo.addToCategory("Work");
} catch (PIMException ex) {
//Work is not a category
}
try { todo.commit(); } catch (PIMException e) {
// An error occured
}
EventList
• Calendar events
• Event createEvent()
– Factory method to create an Event for this event list.
• int[] getSupportedRepeatRuleFields(int frequency)
– Returns the Repeat Rule fields that are settable by the class user and supported
by this EventList for the provided Repeat Rule frequency.
• Event importEvent(Event item)
– Imports the given Event into this list by making a new Event for the list and filling
its information with as much information as it can from the provided Event.
• void removeEvent(Event item)
– Removes a specific Event from the list.
• Enumeration items(int searchType, long startDate, long endDate,
boolean initialEventOnly)
– Return an enumeration of all the Events where at least one of the Event's
occurrences falls in the specified range from startDate to endDate inclusive.
– Searchtype constants: ENDING, OCCURRING, STARTING
• Enumeration items() will return all events.
Event Item
Fields
Type of Data Associated with Field
LOCATION, NOTE, SUMMARY, UID
PIMItem.STRING
END, REVISION, START
PIMItem.DATE
ALARM, CLASS
PIMItem.INT
• There are no field attributes.
• A single event may have multiple occurrences; i.e. the event may be a recurring event
that is repeated at specified intervals. Each occurrence of an event is determined by
using a RepeatRule to calculate when the event should have additional occurrences,
besides the one defined by the Event.START field.
Event creation example
EventList events = null;
try {
events = (EventList) PIM.getInstance().openPIMList(PIM.EVENT_LIST, PIM.READ_WRITE);
} catch (PIMException e) {
// An error occurred
}
Event event = events.createEvent();
Date aDate = new Date(); //variable should be set to something other then now!
if (events.isSupportedField(Event.SUMMARY))
event.addString(Event.SUMMARY, PIMItem.ATTR_NONE, "Meeting with John");
if (events.isSupportedField(Event.START))
event.addDate(Event.START, PIMItem.ATTR_NONE, aDate.getTime());
if (events.isSupportedField(Event.END))
event.addDate(Event.END, PIMItem.ATTR_NONE, aDate.getTime());
if (events.isSupportedField(Event.ALARM))
event.addInt(Event.ALARM, PIMItem.ATTR_NONE, (int) aDate.getTime() - 60000);
if (events.isSupportedField(Event.NOTE))
event.addString(Event.NOTE, PIMItem.ATTR_NONE, "I phoned on Monday to book this
meeting");
try {
if (events.maxCategories() != 0 && events.isCategory("Work"))
event.addToCategory("Work");
} catch (PIMException ex) {
//Work is not a catergory
}
try { event.commit(); } catch (PIMException e) { // An error occured
}
try {events.close(); } catch (PIMException e) { }
RepeatRule
• Event has two addition methods
• RepeatRule getRepeat()
– Retrieves a RepeatRule object specifying how
often and when this event occurs.
• void setRepeat(RepeatRule value)
– Sets the RepeatRule specifying how often and
when this event occurs.
• EventList has the
– int[] getSupportedRepeatRuleFields(int frequency)
RepeatRule (2)
Fields
Set Method
Valid Values
FREQUENCY
setInt
DAILY, WEEKLY, MONTHLY, YEARLY
COUNT
setInt
any positive int
INTERVAL
setInt
any positive int
END
setDate
any valid Date
setInt
JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST,
SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER (Note: that
these are constants defined in the RepeatRule class and are not
the same as those in the Calendar class)
DAY_IN_WEEK
setInt
SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY,
SATURDAY (Note: that these are constants defined in the
RepeatRule class and are not the same as those in the 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
MONTH_IN_YEAR
RepeateRule examples
• To specify the associated event occurs every day:
– setInt(RepeatRule.FREQUENCY, RepeatRule.DAILY);
• To specify the associated event occurs every day for the next five
days:
– setInt(RepeatRule.FREQUENCY, RepeatRule.DAILY);
– setInt(RepeatRule.COUNT, 5);
• To specify this event occurs every week on Monday and Tuesday:
– setInt(RepeatRule.FREQUENCY, RepeatRule.WEEKLY);
– setInt(RepeatRule.DAY_IN_WEEK, RepeatRule.MONDAY |
RepeatRule.TUESDAY);
• To specify the associated event occurs every year on the 4th of July:
– setInt(RepeatRule.FREQUENCY, RepeatRule.YEARLY);
– setInt(RepeatRule.MONTH_IN_YEAR, RepeatRule.JULY);
– setInt(RepeatRule.DAY_IN_MONTH, 4);
RepeateRule examples (2)
• To check if a particular Repeat Rule frequency value
is supported for events for a certain event list:
// Check if RepeatRule.DAILY is supported in the
default event list
EventList el = PIM.openPIMList(PIM.EVENT_LIST,
PIM.READ_WRITE);
int[] supported_fields =
el.getSupportedRepeatRuleFields(RepeatRule.DAILY);
if (supported_fields.length > 0) {
System.out.println("RepeatRule.DAILY is supported
in default event list");
}
Category
• Category is in PIMList and PIMItem, which is
inherited by the three lists.
– Categories are string items assigned to an item to
represent the item's inclusion in a logical grouping.
– The category string correspond to category values
already existing in the PIMItem's associated PIMList.
– Category support per list is optional, depending on
the implementing PIMList class that the item is
associated with.
– The item's list determines if categories can be
assigned, and how many categories can be assigned
per item.
PIMList Category
• void addCategory(String category)
– Adds the provided category to the PIM list.
• void deleteCategory(String category, boolean deleteUnassignedItems)
– Deletes the indicated category from the PIM list.
• String[] getCategories()
– Returns the categories defined for the PIM list.
• boolean isCategory(String category)
– Returns indication of whether the given category is a valid existing category for this
list.
• void renameCategory(String currentCategory, String newCategory)
– Renames a category from an old name to a new name.
• int maxCategories()
– Returns the maximum number of categories that this list can have.
• Enumeration itemsByCategory(String category)
– Returns an enumeration of all items in the PIM list that match the provided
category.
– Field: UNCATEGORIZED
• Constant for the itemsByCategory(String) method to indicate to search for uncategorized items.
PIMItem category
• void addToCategory(String category)
– Adds a category to this item.
• void RemoveFromCategory(String category)
– Remove a category from this item.
• String[] getCategories()
– Returns all the categories for that the item belongs to.
If there are no categories assigned to this item, a zero
length array is returned.
• int maxCategories()
– Returns the maximum number of categories that this
item can be assigned to.
Category example
• From Todo Example
• todos is TodoList and todo is the Item.
try {
if (todos.maxCategories() != 0
//0 says no category support
&& todos.isCategory("Work"))
//Makes sure that Work is a category
todo.addToCategory("Work");
} catch (PIMException ex) {
//Error, list is closed or not accessible, assuming
the above if statements.
}
//To see all the categories associated with an item
String cat[] = todo.getCategories()
Blackberry PIM
• net.rim.blackberry.api.pdap.BlackBerryPIM
– Note, BlackBerryPIM required a signed app.
– development on BlackBerry Smartphone Simulators can occur
without code signing.
– Extends PIMList
• BlackBerryContactList, BlackBerryEventList,
BlackBerryMemoList, BlackBerryPIMList, BlackBerryToDoList,
ContactList, EventList, ToDoList
– Extends PIMItem
• BlackBerryContact, BlackBerryContactGroup,
BlackBerryEvent, BlackBerryMemo, BlackBerryToDo,
Contact, Event, ToDo
Blackberry PIM (2)
•
Other then the added pieces, works the same
•
Example memo (Fields: NOTE, TITLE, UID as string)
PIM p = PIM.getInstance();
BlackBerryMemoList memoList;
try {
memoList = (BlackBerryMemoList) p.openPIMList( BlackBerryPIM.MEMO_LIST,
BlackBerryPIM.READ_WRITE );
} catch ( PIMException e ) { // BlackBerryMemoList could not be opened...
}
try {
BlackBerryMemo memo = memoList.createMemo();
memo.addToCategory( "Work" );
if ( memoList.isSupportedField( BlackBerryMemo.TITLE ) ) {
memo.addString( BlackBerryMemo.TITLE, 0, "New Company Policy" ); }
if ( memoList.isSupportedField( BlackBerryMemo.NOTE ) ) {
memo.addString( BlackBerryMemo.NOTE, 0, "Here are the details..." ); }
} catch( PIMException e ) {
// BlackBerryMemo could not be created
}
memo.commit();
Blackberry Note
• With the simulators that allow you leave it
open and insert the new package.
– I got a Access Exception for the PIM.
– I had to restart the simulator every time I wanted
to try a new version of the code.
Android
• Does no support JSR75 of course
• Has contacts built in
– The calendar is supported via gmail app and must provide
login credentials to access it.
• I was able to login to my gmail account with the email app on the
android simulators. I could access my email, but I could not find a
"calendar" app (looked at the Droid doc's for help).
– The "android" calendar app doesn't look to be installed on the
simulators, nor is gmail app that sync's contacts and calendar events.
– Nor could I find any APIs on their development site.
• Gmail and calendar app are closed source from google and are not
provided in the SDK
• There is no built in support for a memo or todo list.
ContactsContract API
• There is a demo application, ContactManager
• requires Google APIs Target for the simulator API level 7
– Causes Eclipse on my system to crash when
importing the project. Ignore the
stackOverflowError, then it loads.
– Fails to work on the simulator.
• no obvious reason for the failure.
– attempts to connect to gmail contacts?
» needs the gmail app?
– Connected to Eclipse load problem?
gmail
• On a real android phone
– The first thing you must due is either connect to
your gmail account or create one on the spot.
– since it's not provided with the SDKs, this causes a
lot of testing problems
• you need an actual phone to test with.
– The forums are full of some very "unhappy"
people attempting to test their app's.
Q&A
References
• http://developers.sun.com/mobility/apis/ttips
/pim/
• http://java.sun.com/javame/technology/msa/j
sr75.jsp
• Sort of JavaDocs
– http://mobilezoo.biz/jsr/75/pim/index.html