Accessing Palm Address Book
       

This example shows how to access the Palm Address Book database. In this example, a single Address Book entry is displayed on the screen at one time. There are three buttons on the bottom of the screen. A next, previous and an exit button. The next and previous buttons walk you through the database one at a time. A status title at the top shows what record number you are currently looking at.

Backgound

I began this code to try to learn how to access the Palm Address Book database. At first I was only partially successful because I did not understand how the database was stored on the Palm. I attempted to view the address.dat file in the PalmDesktop application to see how the data was stored. An important note is that the palm stores data differently than the desktop application. The format of the database is entirely different on the desktop compared to the Palm itself.

Code Example

A key to understanding how the Palm stores and accesses the data is get the free Conduit Development Kit for Java, version 4 (CDKJ4) from Palm. The conduit development kit allows you to develop Java applications that will sync with the Palm. It also has some classes that show how data is stored in the Palm as well. In this example, I use a modified AddressRecord class that is found in the palm.conduit package of the CDKJ4. I simplified the class slightly for this example. It was this class that revealed how the data is formatted for the Address Book. Each record contains in the database contains a header of two ints, followed by the text data entered for the database.

The first int is a mapping of labels to phone fields. Every 4 bits in the first int represents a mapping of each entry into the following phone label array:

    static private String []phoneLabelText = 
           {"Work", "Home", "Fax", "Other", 
            "E-mail", "Main", "Pager", "Mobile"};
You pull the five phone labels off one by one, and you also pull off the users selection of the "Display Phone" as well. The code snippet to do so is shown below:
        // Options
        options = in.readInt();
        for (i = 0; i < 5; i++) {
            phoneLabelId[i] = (int) (options & 0xF);
            options >>>= 4;
        }
        displayPhone = ((int) (options & 0xF) + 1);

A table showing the bit locations is shown below

4 bit grouping
Key
0
Mapping for first phone entry label
1
Mapping for second phone entry label
2
Mapping for third phone entry label
3
Mapping for fourth phone entry label
4
Mapping for fifth phone entry label
5
Mapping for Display phone label

The second int in the record is used to map which fields are filled in for the Address Book entry. The mapping is show below:

Bit Number
Key
0
Last Name
1
Fist Name
2
Company
3
Phone 1
4
Phone 2
5
Phone 3
6
Phone 4
7
Phone 5
8
Address
9
City
10
State
11
Zip Code
12
Country
13
Custom 1
14
Custom 2
15
Custom 3
16
Custom 4
17
Custom 5
18
Note

The text data is seperated by null bytes (value of 0), and it is the header that lets you know how to map the text data to the specific fields of the Address Book. The first int of the header lets you know how the phone number labels are configured for this record. The second int is a bit by bit map of which fields are used by this record. You map the record by iterating through the field bits, and reading an entry from the text part of the record if its bit value is one, if it is zero you skip to the next type of entry. There are two classes used in this example. Thie first AddrView.java opens the Palm Address Book and displays the data on the screen. The second class, AddressRecord.java allows you to load up a Address Book Record object from the byte[] array you get from accessing a given record.


The screenshot at right shows the output of the program when you first run it. If the address book is empty, a message indicating such is displayed, otherwise the first record in the database is displayed. If there is more than one record, the next button is enabled, allowing you to view the next record. The header at the top shows you which record your are in, and how many currently exist in the database.


This screenshot shows what the output looks like if you push the next button at the bottom of the screen. The second record is displayed, and the previous button is enabled.


Explanation of the code

The source code for this project:

First, you need to be able to open the Database. I used code out of my database example, which opened up a database to read. The gotcha here is that you need to know that the typeID for the AddressBook is "DATA", and the creatorID is "addr" (remember, these are case sensitive).

When opening the database, I used a simple algorithm to convert a four character string to a byte array.

    public int convertTypeToInt(String type) {
	byte[] b = type.getBytes();
	return ((int)b[0])*(256*256*256)+
            ((int)b[1])*(256*256)+
            ((int)b[2])*(256)+
            ((int)b[3]);
    }

In the constructor for the Spotlet:

  1. I open up the database.
  2. Check to see how many records there are in the database.
  3. I then draw the header to the screen, and paint the components.

The method readAddressRecord() is as follows:

    protected void readAddressRecord(int index) {
	// read the record
	record = db.getRecord(index);
	// convert it into a DataInputStream
	byteIn = new ByteArrayInputStream(record, 0, record.length);
	dataIn = new DataInputStream(byteIn);
	// now read the data into the AddressRecord
	try {
	    //translates the body of the record	    
	    addressRecord.readData(dataIn);  
	    dataIn.close();
	  } catch (IOException ioe) {
	      scrollText.setText("ERROR: Unable to read record " +
				 index +
				 "...");
	  }
    }
Note the use of the ByteArray and Data InputStreams. This allows you to take an array of bytes, and use it as a standard DataInputStream. This input stream is used by the AddressRecord class to read in the values from the record.

AddressRecord is a utility class that is taken from the CKDJ4. It is found in the palm.conduit package, and contains methods to get data into and out of the DataInputStreams that have been associated with the database records. It contains methods to access the formatting bits described above that tell you how to read the entire database record correctly. The bulk of this code involves the parsing and formatting of values within an Address Book entry.