Cell phones, like computers, have a well-defined internal file structure to store information. Phone books, images, music, and even applications are stored in various folders under a root directory. However, the classes in the core Java ME [8] packages cannot fully use these folders and files. JSR 75 [9] provides an optional API that enables MIDlets to access the internal directories and files in a mobile phone.
In this article we'll use the classes in JSR 75 to build a
simple application, FileTester, that moves images from a mobile
handset into a server. The emphasis here will mainly be on some of
the intricacies involved in handling files in real devices. I
assume the reader is familiar with Java ME. In order to build and
use the application developed here, the following resources will be
required:
There are a number of articles and books on installation and use of WTK22. This tutorial [12] is one of them. Tomcat is a servlet container and will be used as a server for this application. You will need to download and install Tomcat on your PC to run the application. If you are new to Tomcat and would like some help to download and install it, I would suggest that you refer to Marty Hall's tutorial [13].
In order to run the example, you will need a mobile phone that implements the FileConnection API and the system property used in this article, has a pre-assigned folder for images and is internet-capable. You will also need a suitable data plan for your phone. Your PC should also be connected to internet and should have, preferably, a static IP address.
Even without the FileConnection (FC) API, it is possible to read from files using classes available in Java ME. The FC API is required for manipulating files in all the other ways listed in the documentation. The FC API also comes in handy in browsing and locating predefined folders as explained in the discussion on the example MIDlet.
The API for file access is a part of JSR 75, the rest of the JSR
being devoted to handling the PIM database like the Phonebook. The
JSR 75 is an optional API and, therefore, cannot be expected on
every device. The first step in running an application based on the
FC API is to ascertain whether it is supported on a given device. To
do this, use the following statement:
String versioninfo = System.getProperty
("microedition.io.file.FileConnection.version");
If the platform supports the API, the version number (currently
1.0) will be returned. Otherwise null will be
returned. A short MIDlet (CheckAPI) is available in
the Resources [7] section for checking API
availability. You can build this MIDlet and run it on a phone to
check if the FC API is available. Figure 1 shows the screenshot of
CheckAPI being run on the WTK22 emulator.

Figure 1. Checking API availability
Theoretically, an FC-API-based application can be expected to run once a version number is returned. In practice, this may not be the case. Some manufacturers may restrict the actual use of this API to signed MIDlets only.
Before we plunge into our example application, let's take a
quick look at the classes and interfaces that make up the API. The
FC API is contained in the javax.microedition.io.file
package and incorporates the following
classes/interfaces:
interface FileConnection: Defines the process of
accessing the onboard and removable file systems on a device.interface FileSystemListener: Enables an
application to sense when a file system (like a card) is added or
removed.class FileSystemRegistry: Central registry for
file system listeners.class ConnectionClosedException: Thrown when an
application tries to operate on a closed file connection.class IllegalModeException: Thrown when an
application with proper security clearance tries to access a file
with a wrong mode. For example, if an application has opened a file
connection in READ mode but tries to write to the connection,
this exception will be thrown.It would be a good idea to download the API documentation [14] for reference.
Opening a connection to a file is similar to opening a network
connection. The method used is Connector.open(), with
the resulting Connection object being cast to
FileConnection (where filename includes the path):
FileConnection fc =
(FileConnection)Connector.open(String filename);
The process for accessing a file is settling on a root folder
and opening a connection to it. The listRoots() method
of the FileSystemRegistry class returns an enumeration
listing all available file system roots. Obviously, an application
can start from here and go on to explore the file system on a
device. This can be done by opening a connection to a root and
listing its contents:
FileConnection fc =
(FileConnection)Connector.open(String root);
Enumeration contents = fc.list();
However, there are other ways of getting straight to a specific folder, as we shall see when we discuss our example MIDlet.
Once a connection to a file has been opened, an input or output stream needs to be obtained so that the file can be read from or written into. Note that many other operations (rename, delete, create, and so on) are possible. For a complete list of operations, refer to the API documentation. The fundamentals of the FC API have been explained with great clarity in an article by Qusay Mahmoud [15].
The handling of files in a mobile device is influenced by the
security models of Java ME as well as those adapted by device
manufacturers. Applications running on MIDP-2.0-compliant handsets
are subject to security restrictions applicable to their domain
classification. MIDlets like FileTester would be
classified as "untrusted," since they do not incorporate verifiable
security credentials. At runtime, such MIDlets have to explicitly be granted
permission by the user to access files.
In addition to the above, applications are also subject to
restrictions placed by device manufacturers. Some folders may not
be accessible to all user applications. Such restrictions may
differ from device to device and it is necessary to study
manufacturers' documentation in order to make an application able
to operate on as wide a selection of platforms as possible. More on
this when we discuss FileTester.
MIDlets have an alternative to files for storing information--record stores. It must be emphasized that the FC API
cannot access record stores.
FileTester is an application that uploads images
from a mobile phone to a server. A simple servlet is also included
to complete the demonstration.
The application has the following classes to do the actual
work:
FileTester: The MIDlet.FileSelPage: The class that reads and shows the
contents of the system folder that contains photos.SendFile: The class that reads the image file
and sends it to the server.In addition, it has three more classes that serve to display
messages:
MessageCanvas: A window-like screen to display
messages.TextFormatter: A companion class for
MessageCanvas that breaks long strings into lines that can fit into
the screen.CommMessage: A subclass of MessageCanvas that
can abort an ongoing communication task.When the MIDlet is launched, its startApp() method
is invoked after the constructor has returned. In this case, the
startApp() method instantiates
FileSelPage, which, as mentioned above, reads the
contents of the folder in which images are stored (we'll call it
the IMAGES folder from now on) and displays the list for
selection.
The FileSelPage class is of interest to us and we
shall look at it in some detail.
In order to display the contents of IMAGES, the proper folder
has to be located. There are several options for this, such
as:
The path to IMAGES could be hardcoded into the class. This is not a good option, because different models of handsets store images in different folders. So the actual name of the IMAGES folder and its path will vary from phone to phone. Obviously, hardcoding the filename will make the application usable only on a specific handset.
As we have seen in the preceding section, it is possible to start at the root of the internal file system of the device and navigate manually through the chain of folders until we come to the desired folder. This exploratory action could be built into the application the way code for attaching files to an email allows us to browse. This too has disadvantages. For one thing, this manual browsing on a mobile would be tedious. The other problem is that on some devices, access to the root of the internal file system is restricted and this would prevent the browsing action.
The method adapted for FileSelPage uses the
getProperty() method of System class. In
many devices the following call to getProperty()
returns the path to the folder that the device uses for saving
photos:
String srcdir = System.getProperty("fileconn.dir.photos");
This avoids the disadvantages mentioned above. Note that properties are available for all commonly predefined folders. For more information, refer to Java ME Developer's Library 1.2, which can be downloaded from Forum Nokia [16].
Once the folder has been located, a connection is opened to it
and an Enumeration object containing a list of the
files in the photos folder is obtained. All the items in
the Enumeration object are then cast to
Strings and are appended to FileSelPage,
which extends List:
if (srcdir != null)
{
//if there is such a folder open connection to it
srcconn = (FileConnection)Connector.open(srcdir);
//get a list of its contents and add to list
Enumeration files = srcconn.list();
while (files.hasMoreElements())
{
String file = (String) files.nextElement();
append(file, null);
}
if(size() == 0)
{
//the list is empty
append("The folder is empty", null);
removeCommand(CMD_SUBMIT);
}
//successful
return "Done";
}
When the showFiles() method of
FileSelPage returns, FileTester displays
FileSelPage. The user can now select the item to be
uploaded and activate the Submit command. When this is
done FileTester starts a thread--SendFile--for transmitting the file to the
server.
SendFile again locates the folder and then the
selected file. It then opens an HTTP connection to the server,
opens the required input and output streams, reads the file, and
transmits it over the HTTP connection. Finally, it reads and
displays the response from the server.
The servlet, FCServlet, is very simple. When it is
initiated, it checks to see if there is an Album folder under
C:\. If such a folder does not exist, then it
creates the folder.
When a client logs in and the doPost() method is
invoked, input and output streams are opened. The first information
to be read is the name of the image file. Once the file name is
known a new file is set up in the Album folder and a
FileOutputStream is opened on this file. Next, the size
of the file is read and the input stream is piped into the file
output stream so that the incoming file gets copied. Finally, a
response is sent to the client.
Any application based on an optional API cannot be expected to
run on all devices, as such an API is unlikely to be universally
implemented. We have also seen earlier that the availability of the
FC API does not, by itself, guarantee that an application using
this API will be permitted to run on a given handset. Further, we
must remember that the use of system properties for locating a
folder as shown above is not supported by all phones. Fortunately, a
large number of devices using the S60 and S40 platforms (from Nokia
and some other manufacturers) do support this functionality. The
developer guidelines [17] from Sony Ericsson shows that this
manufacturer too provides system properties for folder access. But
there are other manufacturers that do not. We can see, therefore, that
to implement a folder location method that can be used more
universally, a two-pronged approach may be advisable:
String srcdir = System.getProperty("fileconn.dir.photos");
if (srcdir != null)
{
//use the method shown above
.
.
.
}
else
{
//start from the root and browse manually
}
The devices that do not allow the method demonstrated here usually do not restrict access to file system roots, so the fallback should work. I would also like to point out that I have worked here on the assumption that the folder to access is located in the phone memory and not on an add-on file system like a micro-SD card. If this assumption is invalid, browsing may be the only option. This means the user should be able to decide whether to override the system property approach even though it may be supported by her phone.
Today, using the FC API is a bit complicated. But there is good news for the future: JSR 75 has been made mandatory under Mobile Service Architecture [18] (MSA), the next generation of the Java ME specification. As MSA takes root, the FC API will be available on all new Java-compliant mobile devices and, hopefully, the gray areas will be gradually resolved into black or white.
This article shows a way to simplify access to predefined folders using a facility not mandated by the FC API but available on many popular phones. It also points out a number of issues that one has to contend with when coding an application using the FC API to be deployed on real physical devices.
FileTester has the features that are just essential
to illustrate the subject at hand. It is possible to enhance it in
many ways--some minor and some not so minor--to make it more
usable and meaningful. The servlet, to consider one example, may be
modified such that the incoming file is copied into the target
folder only after the entire file is received. This will ensure
that an interrupted internet connection does not result in a
partially copied file.
Not to be forgotten is the matter of user authentication. Some sort of password protection should be considered if the servlet is kept active for extended periods.
Finally, note that the FC API allows us to reverse the direction of information flow quite easily. So it is relatively simple to create an upload/download package for sharing mobile content.
CheckAPI, FileTester, and
FCServlet.Links:
[1] http://www.java.net/author/biswajit-sarkar
[2] http://www.java.net/article/2007/03/27/working-java-me-fileconnection-api-physical-devices
[3] http://www.java.net/article/2007/03/27/working-java-me-fileconnection-api-physical-devices#the-need-for-the-fileconnection-api
[4] http://www.java.net/article/2007/03/27/working-java-me-fileconnection-api-physical-devices#the-example
[5] http://www.java.net/article/2007/03/27/working-java-me-fileconnection-api-physical-devices#compatibility-issues
[6] http://www.java.net/article/2007/03/27/working-java-me-fileconnection-api-physical-devices#conclusion
[7] http://www.java.net/article/2007/03/27/working-java-me-fileconnection-api-physical-devices#resources
[8] http://java.sun.com/javame/index.jsp
[9] http://jcp.org/en/jsr/detail?id=75
[10] http://java.sun.com/products/sjwtoolkit/download-2_2.html
[11] http://tomcat.apache.org/
[12] http://www.mobilefish.com/emulators/j2me_wt/j2me_wt_quickguide_22_build3.html
[13] http://www.coreservlets.com/Apache-Tomcat-Tutorial/Tomcat-5.0-and-4.0.html
[14] http://jcp.org/aboutJava/communityprocess/final/jsr075/index.html
[15] http://developers.sun.com/techtopics/mobility/apis/articles/fileconnection/
[16] http://www.forum.nokia.com/info/sw.nokia.com/id/35cee3ff-9053-4892-b413-64c6165032cc/Java_ME_Developers_Library_v1_2.zip.html
[17] http://developer.sonyericsson.com/site/global/docstools/java/p_java.jsp?cc=gb&lc=en&ver=4000&template=ps1&zone=ps&lm=ps1
[18] http://jcp.org/en/jsr/detail?id=248
[19] http://www.java.net/today/2007/03/29/src_codes.zip
[20] http://www.java.net/today/2007/03/29/srvr_setup.zip
[21] http://www.apress.com/book/bookDisplay.html?bID=426