THIS is the least exciting chapter of this book, but you should read it anyhow. Remember that great achievements are made up of many smaller achievements. To raise a child, you must learn how to change dirty diapers. To build a Great Pyramid, you must move a lot of rocks.
To kick butt with your MIDP applications, you have to understand the core APIs, which are similar but not the same as the corresponding APIs in the desktop Java platform.
Fundamental classes in java.lang
define strings, primitive type wrappers, and important classes like Object
and Thread
.
The stream classes in java.io
allow you to send and receive information. Stream classes are used mainly for networking and file access.
The utilities in java.util
include basic collections, classes for handling dates and times, and a random number generator.
Don’t assume that you know all this stuff, even if you’re experienced with Java technology on the desktop or in a server environment. The constraints of small devices dictate that these APIs are more compact and less rich than their desktop counterparts.
For all you geezers that can remember JDK 1.0 (circa 1996), the core APIs for MIDP/CLDC are very similar to the corresponding JDK 1.0 APIs. Nevertheless, they are not identical. Read on to find out exactly what you can and cannot do with the core APIs.
MIDP, CLDC, and other mobile device Java technologies are grouped together as the Java Platform, Micro Edition (Java ME). Desktop Java technology is the Java Platform, Standard Edition (Java SE).
MIDP is based on Connected, Limited Device Configuration (CLDC), which is both a virtual machine specification and a set of core APIs. The virtual machine used in CLDC devices is more compact and has fewer features than its desktop cousin.
For reasons that are shrouded in the mists of legend, the CLDC virtual machine is known as the K Virtual Machine, or KVM. Some say the K refers to the kilobyte scale of CLDC devices, while others contend that K is short for Kaui, a project code name from the early days of MIDP.
Regardless of naming, KVM is missing some features compared to the Java SE platform:
No native methods. The Java SE platform provides a way for Java applications to invoke native code. CLDC does not include any such mechanism.
No object finalizers. When an object is harvested by the garbage collector in the Java SE platform, its finalize()
method is called. In CLDC, Object
has no finalize()
method.
No reflection. The Java SE platform allows applications to examine classes and invoke methods dynamically. CLDC does not include this feature.
No classloaders. This is more of a relief than a hindrance. The CLDC implementation has a classloader, of course, but it’s not accessible to applications. You cannot define other classloaders in your application.
Partial bytecode verifier. As discussed in Chapter 2, class files are preverified at build time. A second stage of verification is run when classes are loaded on the device.
java.lang.String
represents character strings, just as in the Java SE platform. The MIDP/CLDC String
does not have all the bells and whistles that are in the Java SE platform, but in other respects it behaves just as you would expect. For example, the MIDP/CLDC String
does not have methods relating to Locale
s, CharSequence
s, or regular expressions.
Memory is often scarce in a MIDP/CLDC device, so you should be careful about string handling in your application. The MSA specification requires a 1MB heap, which is generous, but it’s not the same unlimited feeling you get on the desktop. That heap memory might be shared with other running applications. Furthermore, if you rapidly create and discard many objects, the garbage collector might affect the performance of your application.
Although it’s convenient to assemble strings using the +
operator, it is not the most efficient method. Consider using a StringBuffer
instead, which creates a new String
object only when you call toString()
.
MSA incorporates CLDC 1.1, which has all the same primitive types you’ll find in Java SE. If you want to write applications on older CLDC 1.0 devices, you’ll have to do without float
and double
. That’s all I’m going to say on that subject, because this book is about MSA.
Just as in the Java SE platform, class wrappers for primitive types are present in the java.lang
package. For example, java.lang.Long
is a wrapper class for the primitive type long
.
Finally, java.lang.System
and java.lang.Runtime
include methods that apply to the whole system. You can find out the total heap size, the free heap memory, and the current time. You can run the garbage collector manually. The method you are more likely to use is System.getProperty()
, which retrieves the value of a system property.
In most respects, threads work just as they do in the Java SE platform. To do some work in another thread, create a Thread
object and call start()
. Your old friend Runnable
is still around too. Not surprisingly, the java.util.concurrent
package is not available.
Like memory, however, processing power can be scarce on a MIDP/CLDC device. Threads, in particular, can be a scarce commodity. The MSA specification requires that an application must be allowed to create ten threads. Just because you can doesn’t mean you should. In general, try to use the fewest resources possible so that your application will run as smoothly as possible.
Many of the methods you will write in your applications are callbacks, which means that the thread is owned by the system, not your application. For example, when the device calls your MIDlet’s startApp()
method, the thread that executes startApp()
is a system thread. The rule about system threads and callback methods is to be clean and brief. It’s a lot like using a toaster in a cafeteria. You shouldn’t melt cheese into the heating elements, and you shouldn’t take all day because other people want to toast their bagels too.
If you must perform lengthy processing in response to a user action, put it in a separate application thread. Network connections definitely fall into this category, but plenty of other operations are slow enough to merit their own threads. Mobile devices are much less powerful than desktop computers, so even operations that seem to run quickly on a desktop emulator might be relatively slow on a real device.
In MIDP/CLDC, streams are defined in java.io
, just as in the Java SE platform. To save space, the palette of streams in MIDP/CLDC is reduced to essentials. In particular, MIDP/CLDC does not contain more elaborate or exotic streams like PushbackReader
, PipedWriter
, and LineNumberOutputStream
.
Despite the abbreviated java.io
package, streams are fundamental to any type of input or output in MIDP/CLDC applications. Streams are used for reading and writing data over HTTP, IP, Bluetooth, and other types of network connections. Streams are used to exchange data with local file systems when they are available. Streams are crucial to the Generic Connection Framework, which is fully described in Chapter 18.
When working with InputStream
or any of its subclasses, be wary of the available()
method. Many programmers assume that it returns the number of bytes remaining in a file or network transmission, but in truth it returns the number of bytes that can be read without blocking. Most of the time, you have no use for this number.
Another common error with InputStream
is assuming that the read()
method will fully populate an array that is passed to it as long as there is enough data left in the stream. In reality, the implementation can read as much or as little data as it pleases. Always check the return value of read()
to see how many bytes were actually pulled from the stream.
A final word of caution is to make sure you clean up after yourself. Like memory and threads, streams can also be a scarce resource on mobile devices, especially if they are related to network connections. Whatever streams you’ve opened, make sure you close them. Use finally
to make sure streams get closed. This isn’t good enough:
If any kind of exception is thrown while you are reading data, in
will never be closed because your application will jump into the exception handler. A more robust solution follows. It’s more trouble, but it’ll work better and save you some heartburn.
You can make it a little less messy by bumping exception handling up to the containing method.
One common problem in MIDP/CLDC applications is reading all the data from a stream when you don’t know how much there will be. This often happens when you are retrieving data from a network connection.
A simple approach would be to allocate a big array and read directly into it. However, because memory is scarce, it makes more sense to allocate smaller chunks of memory as necessary.
Here is a method that reads all available data from an InputStream
and returns the result as a properly sized byte array:
As in the Java SE platform, java.util
contains an assortment of useful utility classes. However, the toolbox is a lot smaller in MIDP/CLDC.
Dates are represented by java.util.Date
, which is really just a thin wrapper for a long
value representing the number of milliseconds since January 1, 1970. The long
value is a standard way of representing instants in time and is exactly the same as in the Java SE platform.
A long
or Date
identifies a moment in time in a way that makes sense to a machine, but humans understand calendars and times specific to a time zone. The Calendar
and TimeZone
classes make it possible to convert between Date
s and calendar fields that make sense to humans. In general, these classes are very similar to the Java SE platform, but a lot of the extra API weight (and convenience) has been shed in the interests of compactness.
Before you get too embroiled in Calendar
, think about the needs of your application. If you just want to show a representation of a Date
on the screen, or allow a user to enter a Date
somehow, read about the DateField
class in Chapter 8, “More User Interface.” It might be just what you need.
The java.util
package also contains rudimentary collections, although they are a pale shadow of the Collections API that is part of the Java SE platform. MIDP/ CLDC includes Vector
and Stack
for keeping lists of objects and HashTable
for mapping keys to objects. The Enumeration
interface completes the party as a way to iterate through lists.
None of the collections are multithread safe. If you plan on accessing a collection from more than one thread, you must take steps to avoid trouble.
Finally, java.util.Random
is a simple pseudorandom number generator. Create a Random
and call one of its next
methods to retrieve a pseudorandom number.
In this chapter, you learned about the core APIs of MIDP/CLDC. Classes in java.lang
, java.io
, and java.util
provide stream handling, object collections, and other important functionality. These APIs are similar to the Java SE platform, but they are reduced in size and complexity to fit neatly on small devices.
18.226.98.208