java left logo
java middle logo
java right logo
 

Home arrow Java ME Tips
 
 
Main Menu
Home
Java Tutorials
Book Reviews
Java SE Tips
Java ME Tips
Java EE Tips
Other API Tips
Java Applications
Java Libraries
Java Games
Java Network
Java Forums
Java Blog




Most Visited Tips
Java SE Tips
Java ME Tips
Java EE Tips
Other API Tips
Java Applications
Java Libraries
Java Games
Book Reviews
Top Rated Tips
Java SE Tips
Java ME Tips
Java EE Tips
Other API Tips
Java Applications
Java Libraries
Java Games
Book Reviews


Statistics
Registered Users: 4100
Java SE Tips: 614
Java ME Tips: 202
Java EE Tips: 183
Other API Tips: 779
Java Applications: 298
Java Libraries: 209
Java Games: 16
Book Reviews:
 
 
 
Simple Address Book MIDlet E-mail
User Rating: / 17
PoorBest 

This Midlet implements a simple addressbook.


Image Image
Image Image


/*
 * Copyright (c) 2000-2001 Sun Microsystems, Inc. All Rights Reserved.
 */

import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Enumeration;
import java.util.Vector;

import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;
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.ItemStateListener;
import javax.microedition.lcdui.List;
import javax.microedition.lcdui.Screen;
import javax.microedition.lcdui.TextBox;
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;

/**
 * This MIDlet implements a simple address book with the following
 * functionality: browsing, entry, deletion, and searching (both on device and
 * over the network).
 */
public class AddressBookMIDlet extends MIDlet implements CommandListener,
    ItemStateListener {

  private RecordStore addrBook;

  private static final int FN_LEN = 10;

  private static final int LN_LEN = 20;

  private static final int PN_LEN = 15;

  final private static int ERROR = 0;

  final private static int INFO = 1;

  private Display display;

  private Alert alert;

  private Command cmdAdd;

  private Command cmdBack;

  private Command cmdCancel;

  private Command cmdDial;

  private Command cmdExit;

  private Command cmdSelect;

  private Command cmdSearchNetwork;

  private Command cmdSearchLocal;

  private List mainScr;

  private String[] mainScrChoices = "Search""Add New""Browse",
      "Options" };

  private Form searchScr;

  private TextField s_lastName;

  private TextField s_firstName;

  private Form entryScr;

  private TextField e_lastName;

  private TextField e_firstName;

  private TextField e_phoneNum;

  private List nameScr;

  private Vector phoneNums;

  private Form optionScr;

  private ChoiceGroup sortChoice;

  private TextBox dialScr;

  private int sortOrder = 1;

  /**
   * Public no-argument constructor. Called by the system to instantiate our
   * class. Caches reference to the display, allocate commands, and tries to
   * open the address book.
   */
  public AddressBookMIDlet() {
    display = Display.getDisplay(this);

    cmdAdd = new Command("Add", Command.OK, 1);
    cmdBack = new Command("Back", Command.BACK, 2);
    cmdCancel = new Command("Cancel", Command.BACK, 2);
    cmdDial = new Command("Dial", Command.OK, 1);
    cmdExit = new Command("Exit", Command.EXIT, 2);
    cmdSelect = new Command("Select", Command.OK, 1);
    cmdSearchNetwork = new Command("Network", Command.SCREEN, 4);
    cmdSearchLocal = new Command("Local", Command.SCREEN, 3);

    alert = new Alert("""", null, AlertType.INFO);
    alert.setTimeout(2000);

    try {
      addrBook = RecordStore.openRecordStore("TheAddressBook"true);
    catch (RecordStoreException e) {
      addrBook = null;
    }
  }

  /**
   * Called by the system to start our MIDlet. If the open of the address book
   * fails, display an alert and continue.
   *  
   */
  protected void startApp() {
    if (addrBook == null) {
      displayAlert(ERROR, "Could not open address book"null);
    else {
      genMainScr();
    }
  }

  /**
   * Called by the system to pause our MIDlet. No actions required by our
   * MIDlet.
   */
  protected void pauseApp() {
  }

  /**
   * Called by the system to end our MIDlet. No actions required by our
   * MIDlet.
   */
  protected void destroyApp(boolean unconditional) {
    if (addrBook != null) {
      try {
        addrBook.closeRecordStore();
      catch (Exception e) {
      }
    }
  }

  /**
   * Display an Alert on the screen
   
   @param type
   *            One of the following: ERROR, INFO
   @param msg
   *            Message to display
   @param s
   *            screen to change to after displaying alert. if null, revert to
   *            main screen
   */
  private void displayAlert(int type, String msg, Screen s) {
    alert.setString(msg);

    switch (type) {
    case ERROR:
      alert.setTitle("Error!");
      alert.setType(AlertType.ERROR);
      break;
    case INFO:
      alert.setTitle("Info");
      alert.setType(AlertType.INFO);
      break;
    }
    display.setCurrent(alert, s == null ? display.getCurrent() : s);
  }

  /**
   * Notify the system that we are exiting.
   */
  private void midletExit() {
    destroyApp(false);
    notifyDestroyed();
  }

  /**
   * Create the first screen of our MIDlet. This screen is a list.
   */
  private Screen genMainScr() {
    if (mainScr == null) {
      mainScr = new List("Menu", List.IMPLICIT, mainScrChoices, null);
      mainScr.addCommand(cmdSelect);
      mainScr.addCommand(cmdExit);
      mainScr.setCommandListener(this);
    }
    display.setCurrent(mainScr);
    return mainScr;
  }

  /**
   * Sort order option screen. Allows us to set sort order to either sorting
   * by last name (default), or first name.
   */
  private Screen genOptionScr() {
    if (optionScr == null) {
      optionScr = new Form("Options");
      optionScr.addCommand(cmdBack);
      optionScr.setCommandListener(this);

      sortChoice = new ChoiceGroup("Sort by", Choice.EXCLUSIVE);
      sortChoice.append("First name"null);
      sortChoice.append("Last name"null);
      sortChoice.setSelectedIndex(sortOrder, true);
      optionScr.append(sortChoice);
      optionScr.setItemStateListener(this);
    }
    display.setCurrent(optionScr);
    return optionScr;
  }

  /**
   * Search screen.
   
   * Displays two <code>TextField</code>s: one for first name, and one for
   * last name. These are used for searching the address book.
   
   @see AddressBookMIDlet#genNameScr
   */
  private Screen genSearchScr() {
    if (searchScr == null) {
      searchScr = new Form("Search");
      searchScr.addCommand(cmdBack);
      searchScr.addCommand(cmdSearchNetwork);
      searchScr.addCommand(cmdSearchLocal);
      searchScr.setCommandListener(this);
      s_firstName = new TextField("First name:""", FN_LEN,
          TextField.ANY);
      s_lastName = new TextField("Last name:""", LN_LEN, TextField.ANY);
      searchScr.append(s_firstName);
      searchScr.append(s_lastName);
    }

    s_firstName.delete(0, s_firstName.size());
    s_lastName.delete(0, s_lastName.size());
    display.setCurrent(searchScr);
    return searchScr;
  }

  /**
   * Name/Phone number entry screen
   
   * Displays three <code>TextField</code>s: one for first name, one for
   * last name, and one for phone number. These are used to capture data to
   * add to the address book.
   
   @see AddressBookMIDlet#addEntry
   */
  private Screen genEntryScr() {
    if (entryScr == null) {
      entryScr = new Form("Add new");
      entryScr.addCommand(cmdCancel);
      entryScr.addCommand(cmdAdd);
      entryScr.setCommandListener(this);

      e_firstName = new TextField("First name:""", FN_LEN,
          TextField.ANY);
      e_lastName = new TextField("Last name:""", LN_LEN, TextField.ANY);
      e_phoneNum = new TextField("Phone Number""", PN_LEN,
          TextField.PHONENUMBER);
      entryScr.append(e_firstName);
      entryScr.append(e_lastName);
      entryScr.append(e_phoneNum);
    }

    e_firstName.delete(0, e_firstName.size());
    e_lastName.delete(0, e_lastName.size());
    e_phoneNum.delete(0, e_phoneNum.size());

    display.setCurrent(entryScr);
    return entryScr;
  }

  /**
   * Generates a list of first/last/phone numbers. Can be called as a result
   * of a browse command (genBrowseScr) or a search command (genSearchScr).
   
   * title title of this screen (since it can be called from a browse or a
   * search command. f if not null, first name to search on l if not null,
   * last name to search on
   */
  private Screen genNameScr(String title, String f, String l, boolean local) {
    SimpleComparator sc;
    SimpleFilter sf = null;
    RecordEnumeration re;
    phoneNums = null;

    if (local) {
      sc = new SimpleComparator(
          sortOrder == ? SimpleComparator.SORT_BY_FIRST_NAME
              : SimpleComparator.SORT_BY_LAST_NAME);

      if (f != null || l != null) {
        sf = new SimpleFilter(f, l);
      }

      try {
        re = addrBook.enumerateRecords(sf, sc, false);
      catch (Exception e) {
        displayAlert(ERROR, "Could not create enumeration: " + e, null);
        return null;
      }
    else {
      re = new NetworkQuery(f, l, sortOrder);
    }

    nameScr = null;
    if (re.hasNextElement()) {
      nameScr = new List(title, List.IMPLICIT);
      nameScr.addCommand(cmdBack);
      nameScr.addCommand(cmdDial);
      nameScr.setCommandListener(this);
      phoneNums = new Vector(6);

      try {
        while (re.hasNextElement()) {
          byte[] b = re.nextRecord();
          String pn = SimpleRecord.getPhoneNum(b);
          nameScr.append(SimpleRecord.getFirstName(b" "
              + SimpleRecord.getLastName(b" "
              + SimpleRecord.getPhoneNum(b)null);
          phoneNums.addElement(pn);
        }
      catch (Exception e) {
        displayAlert(ERROR, "Error while building name list: " + e,
            null);
        return null;
      }
      display.setCurrent(nameScr);

    else {
      displayAlert(INFO, "No names found"null);
    }

    return nameScr;
  }

  /**
   * Generate a screen with which to dial the phone. Note: this may or may not
   * be implemented on a given implementation.
   */
  private void genDialScr() {
    dialScr = new TextBox("Dialing"(StringphoneNums.elementAt(nameScr
        .getSelectedIndex()), PN_LEN, TextField.PHONENUMBER);
    dialScr.addCommand(cmdCancel);
    dialScr.setCommandListener(this);
    display.setCurrent(dialScr);
  }

  /**
   * Add an entry to the address book. Called after the user selects the
   * addCmd while in the genEntryScr screen.
   */
  private void addEntry() {
    String f = e_firstName.getString();
    String l = e_lastName.getString();
    String p = e_phoneNum.getString();

    byte[] b = SimpleRecord.createRecord(f, l, p);
    try {
      addrBook.addRecord(b, 0, b.length);
      displayAlert(INFO, "Record added", mainScr);
    catch (RecordStoreException rse) {
      displayAlert(ERROR, "Could not add record" + rse, mainScr);
    }
  }

  /***************************************************************************
   * This method implements a state machine that drives the MIDlet from one
   * state (screen) to the next.
   */
  public void commandAction(Command c, Displayable d) {
    if (d == mainScr) {
      // Handle main sceen
      if (c == cmdExit) {
        midletExit()// exit
      else if ((c == List.SELECT_COMMAND|| (c == cmdSelect)) {
        switch (mainScr.getSelectedIndex()) {
        case 0:
          // display search screen
          genSearchScr();
          break;
        case 1:
          // display name entry screen
          genEntryScr();
          break;
        case 2:
          // display all names
          genNameScr("Browse", null, null, true);
          break;
        case 3:
          // display option screen
          genOptionScr();
          break;
        default:
          displayAlert(ERROR, "Unexpected index!", mainScr);
        }
      }
    else if (d == nameScr) {
      // Handle a screen with names displayed, either
      // from a browse or a search
      if (c == cmdBack) {
        // display main screen
        genMainScr();
      else if (c == cmdDial) {
        // dial the phone screen
        genDialScr();
      }
    else if (d == entryScr) {
      // Handle the name entry screen
      if (c == cmdCancel) {
        // display main screen
        genMainScr();
      else if (c == cmdAdd) {
        // display name entry screen
        addEntry();
      }
    else if (d == optionScr) {
      // Handle the option screen
      if (c == cmdBack) {
        // display main screen
        genMainScr();
      }
    else if (d == searchScr) {
      // Handle the search screen
      if (c == cmdBack) {
        // display main screen
        genMainScr();
      else if (c == cmdSearchNetwork || c == cmdSearchLocal) {

        // display search of local addr book
        genNameScr("Search Result", s_firstName.getString(), s_lastName
            .getString(), c == cmdSearchLocal);
      }
    else if (d == dialScr) {
      if (c == cmdCancel) {
        // display main screen
        genMainScr();
      }
    }
  }

  /**
   * Gets called when the user is viewing the sort options in the optionScr.
   * Takes the new selected index and changes the sort order (how names are
   * displayed from a search or a browse).
   
   * item An item list
   */
  public void itemStateChanged(Item item) {
    if (item == sortChoice) {
      sortOrder = sortChoice.getSelectedIndex();
    }
  }
}

/*
 * Copyright (c) 2000-2001 Sun Microsystems, Inc. All Rights Reserved.
 */

/*
 * Class to query a network service for address book entries and parse the
 * result. Uses HttpConnection to fetch the entries from a server.
 
 * The http request is made using a base url provided by the caller with the
 * query arguments for last name and first name encoded in the query parameters
 * of the URL.
 */

class NetworkQuery implements RecordEnumeration {
  private StringBuffer buffer = new StringBuffer(60);

  private String[] fields = new String[3];

  private String empty = new String();

  private Vector results = new Vector(20);

  private Enumeration resultsEnumeration;

  final static String baseurl = "http://127.0.0.1:8080/Book/netaddr";

  /**
   * Create a RecordEnumeration from the network.
   
   * Query a network service for addresses matching the specified criteria.
   * The base URL of the service has the query parameters appended. The
   * request is made and the contents parsed into a Vector which is used as
   * the basis of the RecordEnumeration. lastname the last name to search for
   * firstname the first name to search for sortorder the order in which to
   * sort 1 is by last name, 0 is by first name
   */
  NetworkQuery(String firstname, String lastname, int sortorder) {
    HttpConnection c = null;
    int ch;
    InputStream is = null;
    InputStreamReader reader;
    String url;

    // Format the complete URL to request
    buffer.setLength(0);
    buffer.append(baseurl);
    buffer.append("?last=");
    buffer.append((lastname != null? lastname : empty);
    buffer.append("&first=");
    buffer.append((firstname != null? firstname : empty);
    buffer.append("&sort=" + sortorder);

    url = buffer.toString();

    // Open the connection to the service
    try {
      c = open(url);
      results.removeAllElements();

      /*
       * Open the InputStream and construct a reader to convert from bytes
       * to chars.
       */
      is = c.openInputStream();
      reader = new InputStreamReader(is);
      while (true) {
        int i = 0;
        fields[0= empty;
        fields[1= empty;
        fields[2= empty;
        do {
          buffer.setLength(0);
          while ((ch = reader.read()) != -&& (ch != ',')
              && (ch != '\n')) {
            if (ch == '\r') {
              continue;
            }
            buffer.append((charch);
          }

          if (ch == -1) {
            throw new EOFException();
          }

          if (buffer.length() 0) {
            if (i < fields.length) {
              fields[i++= buffer.toString();
            }
          }
        while (ch != '\n');

        if (fields[0].length() 0) {
          results.addElement(SimpleRecord.createRecord(fields[0],
              fields[1], fields[2]));
        }
      }
    catch (Exception e) {

    finally {
      try {
        if (is != null) {
          is.close();
        }
        if (c != null) {
          c.close();
        }
      catch (Exception e) {
      }
    }
    resultsEnumeration = results.elements();
  }

  /**
   * Read the HTTP headers and the data using HttpConnection. Check the
   * response code to ensure successful open.
   
   * Connector.open is used to open url and a HttpConnection is returned. The
   * HTTP headers are read and processed. url the URL to open throws
   * IOException for any network related exception
   */
  private HttpConnection open(String urlthrows IOException {
    HttpConnection c;
    int status = -1;

    // Open the connection and check for redirects
    while (true) {
      c = (HttpConnectionConnector.open(url);

      // Get the status code,
      // causing the connection to be made
      status = c.getResponseCode();

      if ((status == HttpConnection.HTTP_TEMP_REDIRECT)
          || (status == HttpConnection.HTTP_MOVED_TEMP)
          || (status == HttpConnection.HTTP_MOVED_PERM)) {

        // Get the new location and close the connection
        url = c.getHeaderField("location");
        c.close();
      else {
        break;
      }
    }

    // Only HTTP_OK (200) means the content is returned.
    if (status != HttpConnection.HTTP_OK) {
      c.close();
      throw new IOException("Response status not OK");
    }
    return c;
  }

  /**
   * Returns true if more elements exist in enumeration.
   */
  public boolean hasNextElement() {
    return resultsEnumeration.hasMoreElements();
  }

  /**
   * Returns a copy of the next record in this enumeration,
   */
  public byte[] nextRecord() {
    return (byte[]) resultsEnumeration.nextElement();
  }

  /**
   * The following are simply stubs that we don't implement...
   */
  public boolean hasPreviousElement() {
    return false;
  }

  public void destroy() {
  }

  public boolean isKeptUpdated() {
    return false;
  }

  public void keepUpdated(boolean b) {
    return;
  }

  public int nextRecordId() {
    return 0;
  }

  public int numRecords() {
    return 0;
  }

  public byte[] previousRecord() {
    return null;
  }

  public int previousRecordId() {
    return 0;
  }

  public void rebuild() {
    return;
  }

  public void reset() {
    return;
  }
}

/*
 * Copyright (c) 2000-2001 Sun Microsystems, Inc. All Rights Reserved.
 */

/**
 * This class implements the RecordFilter interface. It works on the records
 * created by SimpleRecord. It filters on first name and/or last name.
 */

class SimpleFilter implements RecordFilter {

  // first and last names on which to filter
  private String first;

  private String last;

  /**
   * Public constructor: stores the first and last names on which to filter.
   * Stores first/last names as lower case so that filters are are
   * case-insensitive.
   */
  public SimpleFilter(String f, String l) {
    first = f.toLowerCase();
    last = l.toLowerCase();
  }

  /**
   * Takes a record, (r), and checks to see if it matches the first and last
   * name set in our constructor.
   
   * Extracts the first and last names from the record, converts them to lower
   * case, then compares them with the values extracted from the record.
   
   * return true if record matches, false otherwise
   */
  public boolean matches(byte[] r) {

    String f = SimpleRecord.getFirstName(r).toLowerCase();
    String l = SimpleRecord.getLastName(r).toLowerCase();

    return f.startsWith(first&& l.startsWith(last);
  }
}

/**
 * This class implements the RecordComparator interface. It works on the records
 * created by SimpleRecord. It sorts on either first name or last name.
 */

class SimpleComparator implements RecordComparator {

  /**
   * Sorting values (sort by first or last name)
   */
  public final static int SORT_BY_FIRST_NAME = 1;

  public final static int SORT_BY_LAST_NAME = 2;

  /**
   * Sort order. Set by constructor.
   */
  private int sortOrder = -1;

  /**
   * Public constructor: sets the sort order to be used for this
   * instantiation.
   
   * Sanitize s: if it is not one of the valid sort codes, set it to
   * SORT_BY_LAST_NAME silently. s the desired sort order
   */
  SimpleComparator(int s) {
    switch (s) {
    case SORT_BY_FIRST_NAME:
    case SORT_BY_LAST_NAME:
      this.sortOrder = s;
      break;
    default:
      this.sortOrder = SORT_BY_LAST_NAME;
      break;
    }
  }

  /**
   * This is the compare method. It takes two records, and depending on the
   * sort order extracts and lexicographically compares the subfields as two
   * Strings.
   
   * r1 First record to compare r2 Second record to compare return one of the
   * following:
   
   * RecordComparator.PRECEDES if r1 is lexicographically less than r2
   * RecordComparator.FOLLOWS if r1 is lexicographically greater than r2
   * RecordComparator.EQUIVALENT if r1 and r2 are lexicographically equivalent
   */
  public int compare(byte[] r1, byte[] r2) {

    String n1 = null;
    String n2 = null;

    // Based on sortOrder, extract the correct fields
    // from the record and convert them to lower case
    // so that we can perform a case-insensitive compare.
    if (sortOrder == SORT_BY_FIRST_NAME) {
      n1 = SimpleRecord.getFirstName(r1).toLowerCase();
      n2 = SimpleRecord.getFirstName(r2).toLowerCase();
    else if (sortOrder == SORT_BY_LAST_NAME) {
      n1 = SimpleRecord.getLastName(r1).toLowerCase();
      n2 = SimpleRecord.getLastName(r2).toLowerCase();
    }

    int n = n1.compareTo(n2);
    if (n < 0) {
      return RecordComparator.PRECEDES;
    }
    if (n > 0) {
      return RecordComparator.FOLLOWS;
    }

    return RecordComparator.EQUIVALENT;
  }
}

/*
 * Copyright (c) 2000-2001 Sun Microsystems, Inc. All Rights Reserved.
 */

/**
 * This class provides static methods that allow us to hide the format of a
 * record. N.B. no synchronized access is provided
 */

final class SimpleRecord {

  private final static int FIRST_NAME_INDEX = 0;

  private final static int LAST_NAME_INDEX = 20;

  private final static int FIELD_LEN = 20;

  private final static int PHONE_INDEX = 40;

  private final static int MAX_REC_LEN = 60;

  private static StringBuffer recBuf = new StringBuffer(MAX_REC_LEN);

  // Don't let anyone instantiate this class
  private SimpleRecord() {
  }

  // Clear internal buffer
  private static void clearBuf() {
    for (int i = 0; i < MAX_REC_LEN; i++) {
      recBuf.insert(i, ' ');
    }
    recBuf.setLength(MAX_REC_LEN);
  }

  /**
   * Takes component parts and return a record suitable for our address book.
   
   * return byte[] the newly created record first record field: first name
   * last record field: last name num record field: phone number
   */
  public static byte[] createRecord(String first, String last, String num) {
    clearBuf();
    recBuf.insert(FIRST_NAME_INDEX, first);
    recBuf.insert(LAST_NAME_INDEX, last);
    recBuf.insert(PHONE_INDEX, num);
    recBuf.setLength(MAX_REC_LEN);
    return recBuf.toString().getBytes();
  }

  /**
   * Extracts the first name field from a record. return String contains the
   * first name field b the record to parse
   */
  public static String getFirstName(byte[] b) {
    return new String(b, FIRST_NAME_INDEX, FIELD_LEN).trim();
  }

  /**
   * Extracts the last name field from a record. return String contains the
   * last name field b the record to parse
   */
  public static String getLastName(byte[] b) {
    return new String(b, LAST_NAME_INDEX, FIELD_LEN).trim();
  }

  /**
   * Extracts the phone number field from a record. return String contains the
   * phone number field b the record to parse
   */
  public static String getPhoneNum(byte[] b) {
    return new String(b, PHONE_INDEX, FIELD_LEN).trim();
  }
}

 Related Tips

 
< Prev   Next >

Page 1 of 0 ( 0 comments )

You can share your information about this topic using the form below!

Please do not post your questions with this form! Thanks.


Name (required)


E-Mail (required)

Your email will not be displayed on the site - only to our administrator
Homepage(optional)



Comment Enable HTML code : Yes No



 
       
         
     
 
 
 
   
 
 
java bottom left
java bottom middle
java bottom right
RSS 0.91 FeedRSS 1.0 FeedRSS 2.0 FeedATOM FeedOPML Feed

Home - About Us - Privacy Policy
Copyright 2005 - 2008 www.java-tips.org
Java is a trademark of Sun Microsystems, Inc.