Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Motorola J2ME
handsets
WHITE PAPER
Using RMS on Motorola handsets
By
Motocoder
E ven though the RMS API’s are fairly simple to use and haven't changed much since MIDP 1.0, a
developer may see some unexpected results when porting their application across different
platforms. This guide outlines some tips to ensure portability and general usability for the end user, and
gives guidance on how to cope with common problems such as data corruption or data loss.
RMS introduction
“The Mobile Information Device Profile provides a mechanism for MIDlets to persistently store data
and later retrieve it. This persistent storage mechanism is modeled after a simple record oriented
database and is called the Record Management System.” [1]
Using the RMS to store persistent data in your application may seem simple at a first glance. Applying
some of the guidelines below may increase the user experience of your application and help you to
prevent common mistakes when building an application for Motorola phones.
Performance
There are numerous devices on the market supporting MIDP and they have different hardware and
software affecting how the RMS acts in different situations. Performance is one of the areas where
devices vary a lot. When developing applications using RMS to store persistent data, developers should
always keep in mind that the target device might not be as fast as the PC emulator or even another
phone. Just storing a single byte to persistent memory may seem to be a simple task, but there are a lot
of hardware and software factors that affects the performance of this operation. In the article “J2ME
devices: Real-world performance” at www.javaworld.com [2] shows that the performance of RMS
operations can vary from microseconds to several seconds depending on the target device.
Performance measurement depends not only on hardware and Virtual Machine implementation,
but also on the application doing the benchmarking. Some operations may be performed in
different ways to suit the underlying implementation better or worse and may have significant
effect on performance results. The above reference is provided only to emphasize the difference
in performance of various device platforms.
Due to the varying performance of RMS operations across platforms, developers are strongly
encouraged to display a dialog of some sort informing the end user that the application is busy while
managing the persistent storage.
Data Loss
Some user actions such as removing the battery while an application is running may result in data loss of
an application’s RecordStores. A well written application can recover from such a situation and
continue functioning. For Motorola devices specifically, developers should be aware that keeping a
RecordStore object in the open state throughout the application lifetime greatly increases the chance
of encountering this issue. To resolve this, developers are encouraged to close the RecordStore object
as soon as the block of read and/or write operations are done.
try {
dbgout( "open recordstore and write one record" );
db = RecordStore.openRecordStore( "test", true );
db.addRecord( writestr.getBytes(), 0, writestr.length() );
db.closeRecordStore();
dbgout( "done" );
}
catch( Throwable t ) {
dbgout( t.toString() );
}
}
try {
dbgout( "List records in RecordStore" );
db = RecordStore.openRecordStore( "test", false );
enum = db.enumerateRecords( null, null, false );
while( enum.hasNextElement() ) {
record = enum.nextRecord();
dbgout( new String( record ) );
}
enum.destroy();
db.closeRecordStore();
dbgout( "done" );
}
catch( Throwable t ) {
dbgout( t.toString() );
}
}
public void run() {
switch( m_action ) {
case RMSTest.RMS_ACTION_ADD:
addRecord();
break;
case RMSTest.RMS_ACTION_LIST:
listRecords();
break;
}
}
}
}
There are a number of ways you can launch a new thread to perform your RMS operation or other type
of task, the above example is just to show you the concept of it. In fact the example above can be
optimized so that it doesn’t create a new thread for each of these tasks, but instead adds the task to a
queue in the existing RMSThread, which is then served when the Thread is ready for it. That would
reduce some overhead in creating, starting and stopping new threads.
This should ONLY be done if you are experiencing problems with your application using RMS
operations such as creating a RecordStore even though the application doesn’t have any
previous RecordStore objects created.
Conclusion
By following the guidelines below, the user experience of an application can be greatly improved
together with the portability of an application across various MIDP platforms.
Make sure the MIDlet displays a “please wait” dialog during RMS operations or other lengthy task.
Make sure the MIDlet can cope with corrupted RMS data (i.e. gracefully recover and reconstruct the
database).
Make sure the MIDlet synchronizes access of RMS operations from multiple threads.
CommandListener implementations should create a separate thread to perform any RMS operations.
Don’t keep RecordStore objects open.
Emulator7.x based emulators may generate false RecordStoreException when creating databases.
References
1. JSR 37, JSR 118, RecordStore class description. http://java.sun.com/products/midp/
2. J2ME devices: Real-world performance. http://www.javaworld.com/javaworld/jw-10-2002/jw-1025-
j2mebenchmark.html
3. JSR 37, JSR 118, CommandListener interface description. http://java.sun.com/products/midp/