A Simple Diary Application Using RMS

Using the methods described in the previous section, you can now build a simple diary application. The application will demonstrate how to store simple objects (Strings) in a record store.

The purpose of the application is to store one String per day. The user interface consists of a widget and buttons for browsing the diary creating new diary entries.

Because RMS is available in MIDP and PDAP, we will start with the RMS-related functions for loading and saving Strings that can be used in both versions of the diary application. The complete sources of both diary versions, differing in the user interface parts, are given in Listing 5.1 for MIDP and in Listing 5.2 for PDAP. Here, we will focus on the RMS specific calls like opening the record store, loading and saving Strings, and closing the record store.

Because the RMS only provides a mechanism for handling byte array records, you need to convert the diary entries represented as Strings before adding them to the record store. Also, before you can display a diary record in a text widget, you need to convert the byte array back into a String. Fortunately, the functionality for these conversions is available in the String class. In order to convert a String instance to a byte array, you can just call the getBytes() method of the String class. The following line shows how to convert a String to a byte array using the getBytes() method:

byte[] byteArray = new String ("Hello World!").getBytes();

The resulting byte array contains the String Hello World!. This byte array can be stored in a record store using the addRecord() or setRecord() method. In order to convert a byte array read from a record store back into a String object, you can use the corresponding String constructor taking a byte array as parameter.

Before you begin implementing the diary functionality, you need two variables containing the diary record store and an index that points to the record currently displayed. In both versions of the application, these variables are declared as follows:

RecordStore diary;
int currentId = 1;

Now you can start with the loadEntry() method that loads a diary entry from the record store and converts it into a String. The loadEntry() method gets the ID of the desired record as input, sets the current ID to the given value, and returns the corresponding String. If the ID is not valid, a new record is created automatically, and the ID returned from addRecord() is set as the current ID. The following code snippet shows the implementation of loadEntry() for both the MIDP and PDAP versions:

public String loadEntry (int newId) throws RecordStoreException {
    if (newId < 1 || newId > diary.getNumRecords ()) {
        byte [] data = "".getBytes ();
        currentId = diary.addRecord (data, 0, data.length);
    }
    else
        currentId = newId;
    return new String (diary.getRecord (currentId));
}

Now you can load records and also append new records, but you still need a method to update diary entries when the user enters additional information or changes the entry. The saveEntry() method stores the given string with the ID stored in the currentId variable:

public void saveEntry (String entry) throws RecordStoreException {
    byte [] data = (entry).getBytes ();
    diary.setRecord (currentId, data, 0, data.length);
}

Using the two methods loadEntry() and saveEntry(), you have implemented two basic methods that are responsible for loading and storing records to a record store in both the MIDP and PDAP versions of the diary application. The next step to implement the diary application is to open the diary record store in the constructor of the application.

As described in the previous section, the method openRecordStore() can throw RecordStoreExceptions when it is not able to open the record store for some reason. In order to handle these exceptions, it is necessary to put the call in a corresponding try-catch block. In the following snippet, you throw a RuntimeException, terminating the whole application in case of a failure. In real applications, more elaborate error handling may be necessary:

try {
   diary = RecordStore.openRecordStore ("diary", true);
   // load and display the last entry here.
}
catch (RecordStoreException e) {
    throw new RuntimeException ("Cannot open diary; reason: "+e);
}

After the record store is opened, you jump to the last record of the Diary record store and pass the stored String to the text widget of the Diary implementation. Because the UI widgets in MIDP and PDAP are different, we included a comment as placeholder for the actual code. The complete code of the constructors is contained in both full listings.

Note

If you compare the listings to the code snippets for loadEntry() and saveEntry(), you will notice that you save an additional empty space to each record, and use String.trim() when loading it from the RecordStore. You need this workaround because the J2ME WTK 1.0 throws an exception if empty records are stored in a record store.


In order to make sure that the current record is written back and to avoid orphan resources, you need to save the current entry and close the record store when the application is terminated. You do so by implementing a corresponding destroyApp() method. Again, we've included a comment instead of profile-dependent code where the current entry is obtained from the user interface widget:

public void destroyApp (boolean unconditional) {
    try {
        String text;
        // fill text with content of the UI widget here
        saveEntry (text);
        diary.closeRecordStore ();
    }
    catch (RecordStoreException e) {
        throw new RuntimeException ("Cannot close Diary; reason: "+e);
    }
}

When the code is completed with a corresponding user interface, you have a full diary application as shown in Listings 5.1 and 5.2. Figures 5.2 and 5.3 show the running application.

Figure 5.2. The running RmsDemoMidp application.


Figure 5.3. The running RmsDemoPdap application.


Listing 5.1. RmsDemoMidp.java—The Diary Application for MIDP
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.rms.*;

public class RmsDemoMidp extends MIDlet implements CommandListener {

    TextBox textBox = new TextBox ("Diary", "", 150, TextField.ANY);
    int currentId = 1;
    RecordStore diary;

    Display display;
    static final Command prevCommand = new Command ("Prev", Command.SCREEN, 1);
    static final Command nextCommand = new Command ("Next", Command.SCREEN, 2);
    static final Command newCommand = new Command ("New", Command.SCREEN, 3);

    public RmsDemoMidp () {
        try {
            diary = RecordStore.openRecordStore ("diary", true);
            String text = loadEntry (diary.getNumRecords ());
            textBox.setString (text);
            textBox.setTitle ("Diary - Day " + currentId);
        }
        catch (RecordStoreException e) {
            throw new RuntimeException ("Cannot open diary; reason: "+e);
        }

        textBox.addCommand (prevCommand);
        textBox.addCommand (nextCommand);
        textBox.addCommand (newCommand);

        textBox.setCommandListener (this);
    }

    public String loadEntry (int newId) throws RecordStoreException {
        if (newId < 1 || newId > diary.getNumRecords ()) {
            byte [] data = " ".getBytes ();
            currentId = diary.addRecord (data, 0, data.length);
        }
        else
            currentId = newId;
        return new String (diary.getRecord (currentId)).trim ();
    }


    public void saveEntry (String entry) throws RecordStoreException {
        byte [] data = (entry + " ").getBytes ();
        diary.setRecord (currentId, data, 0, data.length);
    }

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

    public void destroyApp (boolean unconditional) {
        try {
            String text;
            text = textBox.getString ();
            saveEntry (text);
            diary.closeRecordStore ();
        }
        catch (RecordStoreException e) {
            throw new RuntimeException ("Cannot close Diary; reason: "+e);
        }
    }

    public void pauseApp () {
    }
    public void commandAction (Command c, Displayable d) {
        try {
            saveEntry (textBox.getString ());

            if (c == nextCommand && currentId < diary.getNumRecords ()) {
                textBox.setString (loadEntry (currentId+1));
            }
            else if (c == prevCommand && currentId > 1) {
                textBox.setString (loadEntry (currentId-1));
            }

            else if (c == newCommand) {
                textBox.setString (loadEntry (diary.getNumRecords () + 1));
            }

            textBox.setTitle ("Diary - Day " + currentId);

        }
        catch (RecordStoreException e) {
            throw new RuntimeException ("Cannot perform; reason: "+e);
        }
    }
}
				

Listing 5.2. RmsDemoPdap.java—The Diary Application for PDAP
import java.awt.*;
import java.awt.event.*;
import javax.microedition.rms.*;
import javax.microedition.midlet.*;

public class RmsDemoPdap extends MIDlet implements ActionListener {
    Frame frame = new Frame ();
    TextArea textArea = new TextArea ();
    int currentId;
    RecordStore diary;

    Button buttonPrev = new Button ("Prev");
    Button buttonNext = new Button ("Next");
    Button buttonNew = new Button ("New");

    public RmsDemoPdap () {
        try {
            diary = RecordStore.openRecordStore ("diary", true);
            String text = loadEntry (diary.getNumRecords ());
            textArea.setText (text);
            frame.setTitle ("Diary - Day " + currentId);
        }
        catch (RecordStoreException e) {
            throw new RuntimeException ("Cannot open diary; reason: "+e);
        }


        frame.add ("Center", textArea);

        Panel buttons = new Panel ();

        buttons.add (buttonPrev);
        buttons.add (buttonNext);
        buttons.add (buttonNew);

        buttonPrev.addActionListener (this);
        buttonNext.addActionListener (this);
        buttonNew.addActionListener (this);

        frame.add ("South", buttons);
        frame.pack ();

        frame.addWindowListener (new WindowAdapter () {
                public void windowClosing (WindowEvent ev) {
                    destroyApp (true);
                    notifyDestroyed ();
                }
            });
    }
    public String loadEntry (int newId) throws RecordStoreException {
        if (newId < 1 || newId > diary.getNumRecords ()) {
            byte [] data = " ".getBytes ();
            currentId = diary.addRecord (data, 0, data.length);
        }
        else
            currentId = newId;

        return new String (diary.getRecord (currentId));
    }


    public void saveEntry (String entry) throws RecordStoreException {
        byte [] data = entry.getBytes ();
        diary.setRecord (currentId, data, 0, data.length);
    }


    public void startApp () {
        frame.show ();
    }


    public void destroyApp (boolean unconditional) {
        try {
            saveEntry (textArea.getText ());
            diary.closeRecordStore ();
        }
        catch (RecordStoreException e) {
            throw new RuntimeException ("Cannot close Diary; reason: "+e);
        }
    }

    public void pauseApp (){
    }


    public void actionPerformed (ActionEvent ev) {

        try {
            saveEntry (textArea.getText ());
            
            if (ev.getSource () == buttonNext
                && currentId < diary.getNumRecords ())
                textArea.setText (loadEntry (currentId+1));
            else if (ev.getSource () == buttonPrev && currentId > 1)
                textArea.setText (loadEntry (currentId-1));
            else if (ev.getSource () == buttonNew)
                textArea.setText (loadEntry (diary.getNumRecords () + 1));
            frame.setTitle ("Diary - Day " + currentId);
        }
        catch (RecordStoreException e) {
            throw new RuntimeException ("Cannot perform; reason: "+e);
        }
    }
}
				

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset