Implementing Phone Book application in J2ME (step-3)

Hi, guys 🙂 I want to end up this PhoneBook series from this post. First I thought to add SMS functions to this series and then had a second thought to do it in  a different post to reduce the length of the post as well as code sample. So in this post I add some small functions such as how to view, update and delete a contact.

The interface I have used additionally in this post is;

  • ItemCommandListener

First look at the Figure 1, then I will explain what I did there.

View Commmand
Figure 1

As you can see, when the Search text field activated, you cannot see the View command. But when the ChoiceGroup activated you can see the View command. That means I added the View command to the ChoiceGroup not for the Form. Then let’s see the what can view when we click on View command. (Figure 2)

Change Interface
Figure 2

You can see the relevant information of the contact that you have selected in the previous interface to view. In this interface you have been provided the Update and Delete options. By clicking on the Delete command the selected contact will be deleted from the RecordStore. If you want to update the name or the phone number or both first you have to do the changes and then click on the Update command. I know that is not user friendly. I did it this way because to reduce some coding lines and even I have not add any confirmation messages before doing this critical editing. I will show how to do that in a separate post. The rest of the code is as below.

package anuja;

import java.util.Vector;
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.AlertType;
import javax.microedition.lcdui.Choice;
import javax.microedition.lcdui.ChoiceGroup;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.Item;
import javax.microedition.lcdui.ItemCommandListener;
import javax.microedition.lcdui.ItemStateListener;
import javax.microedition.lcdui.TextField;
import javax.microedition.midlet.MIDlet;
import javax.microedition.rms.RecordComparator;
import javax.microedition.rms.RecordEnumeration;
import javax.microedition.rms.RecordFilter;
import javax.microedition.rms.RecordStore;
import javax.microedition.rms.RecordStoreException;
import javax.microedition.rms.RecordStoreNotOpenException;

 * @author Anuja
public class SearchContact extends MIDlet implements CommandListener, RecordComparator, ItemStateListener, RecordFilter, ItemCommandListener {

    private Display display;
    private ChoiceGroup searchChoice;
    private Form searchForm;
    private TextField searchTxtField;
    private Command exitCmd;
    private Command addContactCmd;
    private Form addContactForm;
    private TextField nameTxtField;
    private TextField numberTxtField;
    private Command backCmd;
    private Command saveCmd;
    private String nameStr;
    private String numberStr;
    private Alert addAlert;
    private RecordStore openRecStore;
    private Vector vectorArray;

    // Need to declare & initialize when we use this with startsWith()
    // If we don't initialize, it will give us NullPointerException
    // Default value of String is null although other data types have some values like int have 0 as default value
    private String filterStr = "";

    private Form changeContactForm;
    private Command viewCmd;
    private TextField changeNameTxtField;
    private TextField changeNumberTxtField;
    private Command changeBackCmd;
    private Command changeUpdateCmd;
    private Command changeDelCmd;
    private Alert warningAlert;

    public void startApp() {
        display = Display.getDisplay(this);

        // --------------------- Search Contact Form ---------------------------

        searchForm = new Form("Search Contact");
        searchTxtField = new TextField("Search Here", "", 30, TextField.ANY);

        searchChoice = new ChoiceGroup("", Choice.EXCLUSIVE);
        //searchChoice.append("Anuja", null);

        exitCmd = new Command("Exit", Command.EXIT, 7);
        addContactCmd = new Command("Add", Command.OK, 4);

        viewCmd = new Command("View", Command.OK, 4);

        // When we add a command to an Item we have to call setItemCommandListener()
        // To call this method we need to implements ItemCommandListener interface

        // If there is a change of the items here it will call the itemStateChanged()


        //-------------------- Add Contact Form --------------------------------

        addContactForm = new Form("Add Contacts");
        nameTxtField = new TextField("Name", "", 80, TextField.ANY);
        numberTxtField = new TextField("Number", "", 20, TextField.PHONENUMBER);

        backCmd = new Command("Back", Command.BACK, 2);
        saveCmd = new Command("Save", Command.OK, 4);


        //----------------------- Change Contact Form ----------------------------

        changeContactForm = new Form("Change Contact");
        changeNameTxtField = new TextField("", "", 80, TextField.ANY);
        changeNumberTxtField = new TextField("", "", 20, TextField.PHONENUMBER);

        changeBackCmd = new Command("Back", Command.BACK, 2);
        changeUpdateCmd = new Command("Update", Command.OK, 4);
        changeDelCmd = new Command("Delete", Command.OK, 4);


        //-------------------- Open a RecordStore ------------------------------

        try {
            openRecStore = RecordStore.openRecordStore("Contacts", true);
        } catch (RecordStoreException ex) {


    public void pauseApp() {

    public void destroyApp(boolean unconditional) {

    public void commandAction(Command c, Displayable d) {
        if (c == exitCmd) {
        } else if (c == addContactCmd) {
        } else if (c == backCmd) {
        } else if (c == saveCmd) {

            //------------------ Get the inputs ------------------------
            nameStr = nameTxtField.getString();
            numberStr = numberTxtField.getString();
            String fullDetails = nameStr + "*" + numberStr;

            // Can add the name to the ChoiceGroup like below or by getting it from the RecordStore like in loadContacts()
            //searchChoice.append(nameStr, null);

            addAlert = new Alert("Added to the Contacts");
            display.setCurrent(addAlert, searchForm);


//--- To add to the RecordStore we need to convert the String to byte array ---
            byte[] byteArray = fullDetails.getBytes(); // String class

//--- Add a new record to the RecordStore
            try {
                openRecStore.addRecord(byteArray, 0, fullDetails.length()); // RecordStore class
            } catch (RecordStoreException ex) {

            // If you remove the following line, the newly adding contacts are not display. They will display after another contact being added
        }else if(c == changeBackCmd){
        }else if(c == changeUpdateCmd){
            // Get selected index from the ChoiceGroup
            int getSelInd = searchChoice.getSelectedIndex();

            // Get the relevant element from Vector array according to the selected element from ChoiceGroup
            ContactDetails getConInfo = (ContactDetails) vectorArray.elementAt(getSelInd);

            // Get the record ID of the selected option
            int recordId = getConInfo.getContactId();

            String changeName = changeNameTxtField.getString();
            String changeNumber = changeNumberTxtField.getString();

            String changeFullDetails = changeName + "*" + changeNumber;
            byte[] editRec = changeFullDetails.getBytes();

            try {
                // To edit a record we use setRecord()
                openRecStore.setRecord(recordId, editRec, 0, editRec.length);
            } catch (RecordStoreException ex) {

            warningAlert = new Alert("Successfully updated", "", null, AlertType.INFO);
            display.setCurrent(warningAlert, searchForm);

        }else if(c == changeDelCmd){
            // Get selected index from the ChoiceGroup
            int getSelInd = searchChoice.getSelectedIndex();

            // Get the relevant element from Vector array according to the selected element from ChoiceGroup
            ContactDetails getConInfo = (ContactDetails) vectorArray.elementAt(getSelInd);

            // Get the record ID of the selected option
            int recordId = getConInfo.getContactId();

            try {
                // The record is deleted from the record store by using deleteRecord()
                // The recordId for this record is NOT reused.
            } catch (RecordStoreException ex) {
            warningAlert = new Alert("Permanantly Deleted !", "", null, AlertType.CONFIRMATION);
            display.setCurrent(warningAlert, searchForm);

    private void loadContacts() {
        // Add following line to ignore the same contact add twice

        vectorArray = new Vector();

        try {
//---  Returns an enumeration for traversing a set of records in the record store in an optionally specified order.
            //RecordEnumeration enuRec = openRecStore.enumerateRecords(this, this, true);
            RecordEnumeration enuRec = openRecStore.enumerateRecords(this, this, true);

            while (enuRec.hasNextElement()) {
                try {
                    // Take a recoed and convert it from byte array to String
                    //byte[] nextRec = enuRec.nextRecord();
                    //String nextRecStr = new String(nextRec);

                    // Returns the recordId of the next record in this enumeration,
                    // Where next is defined by the comparator and/or filter supplied in the constructor of this enumerator
                    int recordId = enuRec.nextRecordId(); // Method in RecordEnumeration
                    byte[] nextRec = openRecStore.getRecord(recordId); // Method in RecordStore
                    String nextRecStr = new String(nextRec);

                    // Seperate Name and the Phone number from the String
                    // We have to assign the results after substring because Strings are immutable
                    // That means when we assign a String to a variable it will "never change"
                    String takeName = nextRecStr.substring(0, nextRecStr.indexOf("*"));
                    // nextRecStr.substring(0, nextRecStr.indexOf("*"));
                    // There is no error in the above line. It will create a String object as well.
                    // But we can't access that object and it's get lost
                    String takeNumber = nextRecStr.substring(nextRecStr.indexOf("*") + 1, nextRecStr.length());

                    // Add the Name in to ChoiceGroup
                    searchChoice.append(takeName, null);

                    // Create a Vector class to put contacts. We use Vector because it is a growable array
                    // But you can't initialize it here. Because we are calling removeAllElements() in above.
                    // So have to create above all the related methods in Vector class
                    // See first few lines after begining of loadContacts()

                    // We need to put three variables (name, number and id) in to one element in the Vector array.
                    // In addElement method we can only pass an Object.
                    // So the best option is create an Object which is having above mentione attributes (name, number and id)
                    ContactDetails conDet = new ContactDetails();

                    // Add attributes in the ContactDetails class to the Vector array
                    // But it adds the specified component to the end of this vector, increasing its size by one.
                    // Simply, Vector elements are ordered by index
                    // But in a PhoneBook, we don't want to add a contact as it is.
                    // We need to sort according to the name as an example first we expect to see the names begins with "A"
                    // Here we need the compare(byte[] rec1, byte[] rec2) method which comes under RecordComparator

                } catch (RecordStoreException ex) {
        } catch (RecordStoreNotOpenException ex) {

    // Have to overwrite when we implemtnts RecordComparator
    // Remeber to change the second argument in the enumerateRecords from null to this
    public int compare(byte[] rec1, byte[] rec2) {


        String data1 = new String(rec1);
        String data2 = new String(rec2);

        // Compares two strings lexicographically.
        // The comparison is based on the Unicode value of each character in the strings.
        // We use this to atore the contacts in lexicographically sorting order.
        // Means when you add a new contact it will add to the correct place according to letters of the name.
        int x = data1.compareTo(data2); // Method of String class        

        //  System.out.println(data1);
        //  System.out.println(data2);
        //  System.out.println(x);

        if(x == 0){
            // System.out.println("Equal");
            return RecordComparator.EQUIVALENT;
        }else if(x < 0){
            // System.out.println("Less than");
            return RecordComparator.PRECEDES;
            // System.out.println("Greater than");
            return RecordComparator.FOLLOWS;

        //throw new UnsupportedOperationException("Not supported yet.");

    // Have to overwrite when implements ItemStateListener
    public void itemStateChanged(Item item) {       
        if(item == searchTxtField){
            filterStr = searchTxtField.getString();
            //System.out.println("Item State Changed");

        //throw new UnsupportedOperationException("Not supported yet.");

    // Have to overwrite when implements RecordFilter
    // Remeber to change the first argument in the enumerateRecords from null to this
    public boolean matches(byte[] candidate) {

        //System.out.println("Record Filtering");

        String candi = new String(candidate);

        // Tests if this string starts with the specified prefix.
        // We have initialized the filterStr above with the value ""
        if (candi.startsWith(filterStr)) { // Method os String class
            return true;
        return false;

        //throw new UnsupportedOperationException("Not supported yet.");

    // Have to overwrite when implements ItemCommandListener
    public void commandAction(Command c, Item item) {
        if(c == viewCmd){

            // Get selected index from the ChoiceGroup
            int getSelInd = searchChoice.getSelectedIndex();

            // Returns the component at the specified index by using elementAt()
            ContactDetails getConInfo = (ContactDetails) vectorArray.elementAt(getSelInd);

        //throw new UnsupportedOperationException("Not supported yet.");

This is the full code. The changes I have done with compare to my previous post is minor. As usual I encourage you to copy the code to an IDE and see the differences. It’s not difficult.

We will meet with a new mobile application later. Thank You 🙂

About AnujAroshA

Working as an Associate Technical Lead. Specialized in iOS application development. A simple person :)
This entry was posted in J2ME examples. Bookmark the permalink.

3 Responses to Implementing Phone Book application in J2ME (step-3)

  1. Rehan says:

    Thnks thnks thnks thnks thnks a million time :)This helped me a lot 🙂 best wishes from Mauritius xD

  2. janu says:

    ContactDetails class is missing

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s