Displaying the contacts list

Instead of requiring the user to type in the recipient's number, the MIDlet allows the user to select the number from the device's contacts list. This feature is launched from the EventCreationForm with a separate option, which displays the ContactListForm. The ContactListForm contains a list of saved contacts on the device, and an option for selecting the contact, whose details are then filled into the EventCreationForm.

Figure: Selecting the recipient from the contacts list

To implement the ContactListForm class:

  1. Create the ContactListForm.java class file.

  2. Import the required packages, initialize the UI elements and Commands, and create a CommandListener.

    import java.util.*;
    import javax.microedition.lcdui.*;
    import javax.microedition.pim.*;
    
    // This Form shows a list of the contacts in the local databases
    class ContactListForm extends List implements CommandListener {
        private final Command exitCommand, selectCommand, backCommand;
        private final EventSharingMIDlet parent;
        private boolean available;
        private Vector allTelNumbers = new Vector();
    
        public ContactListForm(EventSharingMIDlet parent) {
            super("Contacts", Choice.IMPLICIT);
            this.parent = parent;
    
            // init UI
            selectCommand = new Command("Select", Command.OK, 0);
            backCommand = new Command("Back", Command.BACK, 1);
            exitCommand = new Command("Exit", Command.EXIT, 1);
    
            addCommand(backCommand);
            addCommand(exitCommand);
            setCommandListener(this);
            setFitPolicy(Choice.TEXT_WRAP_ON);
    
            // load the list of names in a different thread
            parent.enqueueOperation(new LoadContacts());
        }
    
        public void commandAction(Command cmd, Displayable displayable) {
            // if no names are available return
            if (!available) {
                parent.showMain();
                return;
            } else if (cmd == selectCommand) {
                int selected = getSelectedIndex();
                if (selected >= 0) {
                    // will get the number from the list
                    parent.contactSelected((String)allTelNumbers.elementAt(selected));
                } else {
                    parent.showMain();
                }
            } else if (cmd == backCommand) {
                parent.showMain();
            } else if (cmd == exitCommand) {
                parent.notifyDestroyed();
            }
        }
  3. Create a method for getting a new instance of the PIM class, and use the PIM.openPIMList method to open the default list for the used contact list type.

    Verify that the required fields are supported by calling the PIMList.isSupportedField method. After verification, read the local database for phone numbers and extract the contact information, including first and last names (where available), and telephone numbers.

        // loads the names of a named contact list
        private void loadNames(String name) throws PIMException, SecurityException {
            ContactList contactList = null;
            try {
                contactList = (ContactList) PIM.getInstance().openPIMList(PIM.CONTACT_LIST, PIM.READ_ONLY, name);
                // First check that the fields we are interested in are supported
                // by the PIM List
                if (contactList.isSupportedField(Contact.NAME) && contactList.isSupportedField(Contact.TEL)) {
                    // Put an informative title while reading the contacts
                    setTitle("Contacts");
                    Enumeration items = contactList.items();
    
                    Vector telNumbers = new Vector();
                    // For each Contact in the List
                    while (items.hasMoreElements()) {
                        String firstname=null;
                        String lastname=null;
    
                        Contact contact = (Contact) items.nextElement();
                        //Get First Name if available
                        try {
                            firstname=contact.getStringArray(Contact.NAME,
                            Contact.ATTR_NONE)[Contact.NAME_GIVEN];
                        }
                        catch(Exception e){}
                        //Get Last Name if available
                        try {
                            lastname=contact.getStringArray(Contact.NAME,
                            Contact.ATTR_NONE)[Contact.NAME_FAMILY];
                        }
                        catch(Exception e){}
    
                        //Counts the number of telephone entries for this contact
                        int telCount=contact.countValues(Contact.TEL);
  4. Continuing in the loadNames method, set the appropriate search criteria. Check the contents of the retrieved contacts to sort out the data and to fetch only those entries that have phone numbers attached to them and either a first or last name defined. To verify that a PIMList supports the attributes you are interested in, use the isSupportedAttribute and getSupportedAttributes methods.

                        // we're only interested on contacts with a phone number
                        // and a name (either first or last).
    
                        if (telCount > 0 && (firstname!=null || lastname!=null)) {
                            String contactName=null;
                            if(firstname!=null && lastname!=null)
                                contactName = firstname+" "+lastname;
                            else if(lastname==null)
                                contactName=firstname;
                            else
                                contactName=lastname;
    
                            // go through all the phone numbers
                            for (int i = 0; i < telCount; i++) {
                                // check if it is a cell phone and put it at the beginning
                                // this doesn't necessary work since in many cases is up
                                // to the user to indicate whether it is a mobile phone
                                int telAttributes = contact.getAttributes(Contact.TEL, i);
                                String telNumber = contact.getString(Contact.TEL, i);
                                // check if ATTR_MOBILE is supported
                                if (contactList.isSupportedAttribute(Contact.TEL, Contact.ATTR_MOBILE)) {
                                    if ((telAttributes & Contact.ATTR_MOBILE) != 0) {
                                        telNumbers.insertElementAt(telNumber, 0);
                                    } else {
                                        telNumbers.addElement(telNumber);
                                    }
                                } else {
                                    telNumbers.addElement(telNumber);
                                }
                                allTelNumbers.addElement(telNumber);
                            }
                            // Shorten names which are too long
                            if (contactName.length() > 20) {
                                contactName = contactName.substring(0, 17) + "...";
                            }
                            // insert elements in the list in order
                            for (int i = 0; i < telNumbers.size(); i++) {
                                append(contactName + ": " + telNumbers.elementAt(i), null);
                            }
                            telNumbers.removeAllElements();
                        }
                    }
                    available = true;
                } /*else {
                    append("Contact list required items not supported", null);
                    available = false;
                }*/
            } finally {
                // always close it
                if (contactList != null) {
                    contactList.close();
                }
            }
        }
  5. Create an inner class for reading the contacts from the contacts list. The operation is better handled in a separate thread so as to not lock the rest of the MIDlet. When the contacts are read and printed on screen, add a Command for selecting a contact.

        // load the names in a separate thread
        private class LoadContacts implements Operation {
            public void execute() {
                try {
                    // go through all the lists
                    String[] allContactLists = PIM.getInstance().listPIMLists(PIM.CONTACT_LIST);
                    if (allContactLists.length != 0) {
                        for (int i = 0; i < allContactLists.length; i++) {
                            loadNames(allContactLists[i]);
                        }
                        addCommand(selectCommand);
                    } else {
                        append("No Contact lists available", null);
                        available = false;
                    }
                } catch (PIMException e) {
                    parent.showMessage(e.getMessage(), ContactListForm.this);
                    available = false;
                    append("Press a key to return", null);
                } catch (SecurityException e) {
                    parent.showMessage(e.getMessage(), ContactListForm.this);
                    available = false;
                    append("Press a key to return", null);
                }
            }
        }
    }

Now that you have implemented the functionality for displaying the contacts list, handle incoming events.