The Source for Java Technology Collaboration
User: Password:
Register | Login help    

Search

Online Books:
java.net on MarkMail:


 E-mail  Print

Working with the Java ME FileConnection API on Physical Devices

Thu, 2007-03-29

{cs.r.title}



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 packages cannot fully use these folders and files. JSR 75 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 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.

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.

The Need for the FileConnection API

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 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.

Checking API availability
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 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.

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.

The Example

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.

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.

Compatibility Issues

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 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 (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.

Conclusion

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.

Resources

Biswajit Sarkar is an electrical engineer with a specialization in programmable industrial automation.
Related Topics >> Mobility      
Comments
Comments are listed in date ascending order (oldest first)