Programming/J2ME

From Wikibooks, the open-content textbooks collection

Jump to: navigation, search

Contents

[edit] Introduction

Java 2 Micro Edition (J2ME) is a collection of technologies found on more than a billion small devices worldwide. Small devices are less powerful than larger, desktop computers and a full Java Standard Edition (JavaSE) installation would be unworkable on many small devices. As well as this, there is a demand for devices with more rigorous security models than found in the JavaSE. To cope with this demand, two different subsets of JavaSE were created. These are called the CDC (Connected Device Configuration) and the CLDC (Connected Limited Device Configuration). Some of the missing capabilities may confuse developers used to the JavaSE: the CLDC, for example, does not by itself allow a Java program to access the file system. To add functionality useful for specific target use-cases, extensions to the CDC or CLDC APIs were developed. The best-known of these for the CLDC is the Mobile Information Device Profile (MIDP).

The CDC (Connected Device Configuration) runs on 32-bit hardware with a few megabytes of memory. The current version is defined in JSR 218 and has the full name CDC 1.1.2. It includes a fully functional Java Virtual Machine.

The CLDC/MIPD (Connected Limited Device Configuration with Mobile Information Device Profile) runs on 16 or 32-bit hardware with hundreds of kilobytes of memory. The current version of CLDC is 1.1 defined in JSR 139. It includes a reduced Java Virtual Machine called the K Virtual Machine.

Before developing a J2ME application, it is necessary to know which Java technologies are supported on the target platforms. This book will explore the CLDC/MIDP platform as found on hundreds of millions of mobile phones worldwide.

[edit] Overview

[edit] What is Java and why?

In this section I will introduce the Java language with some history as to why Java has the form it has. If you are already versed in Java, feel free to jump to the next chapter.

[edit] A brief introduction to programming languages

The central processing unit of a computer and the main memory are orderly collections of gates. A gate is here a term from Electronics and means a small electronic component with a number of inputs and outputs where the state of the outputs (usually +5 volt or 0 volt, sometimes + 3.3 volt and 0 volt) depends in some way upon the state of the inputs. These gates allow a physical representation of binary logic and discrete mathematics. Put simply, it is possible to arrange these gates in such a way that they can store certain states (http://en.wikipedia.org/wiki/Latch_%28electronics%29) or add two states together (http://en.wikipedia.org/wiki/Adder_%28electronics%29) or do a number of interesting things. Most central processing units available support these basic operations. More directly put, if you set the data inputs of a SPARC processor to be the right combination of high (5V) and low (0V), it will take the last 12 highs and lows and store these states in a register on the chip (a register is a small memory very close the chip which can usually be read from or written to in one clock cycle). If you set a different combination of highs and lows, the chip will do something different, right up to complicated things like "jump over the next 10 numbers to be entered if a number stored in a certain register is larger than the number stored in another register". This is the machine code the chip actually performs. The 32 long sequence of highs and lows can be called a 32-bit number or code. The allowed forms of these codes are called the op-codes (http://en.wikipedia.org/wiki/Op_code) for the processor. Programming in this manner is done rarely nowadays, and machine code is referred to as a first generation programming language (http://en.wikipedia.org/wiki/First-generation_programming_language). It is very error prone—one has to remember the different op-codes or the addresses in your program you may wish to spring to. To help solve these problems, second generation programming languages were developed.

If 10000100 always means "add", why not write "add" and then use a computer program to translate "add" into "10000100"? This is the main addition to computing brought be second generation programming languages. Second generation programming languages (http://en.wikipedia.org/wiki/Second-generation_programming_language) can not be run directly by a computer but first have to be translated into a first generation programming language. Usually this is not particularly difficult. A translation program for this (called an assembler) is usually quite small and error-free. This allows relatively legible code like the following:

add %g0, 5, %l0
add %g0, 7, %l1
add %l0, %l1, %l2

Although this is still not particularly legible, it is nevertheless a vast improvement on the machine code:

100000000010010000100000000010110000000001001000110000000001111010010000100100000000000010001

What does it do? After the third instruction has been performed, the local register l2 will contain the number 12.

Let us examine the following mathematical expression:

s = ½at² + vt

Processing this expression for different values of a, v, and t with a second generation programming language would require a lot of programming. The expression is however well defined and it should be possible to write a program to automatically generate the machine code needed to evaluate this expression.

Another consideration which drove the next step in programming technology was the different types of number which can be processed by a chip. Because this is still relevant to modern programming languages like Java, I will go into this in some depth. The basic question is, what is the best way to store numbers as a combination of high and low states (bits)? When it comes to positive integers, the answer is fairly obvious—one just converts the decimal number to its binary representation. Provided that the number isn't too large (32 bits allow numbers up to about 4 thousand million), the number can be stored with no loss of accuracy. As mentioned above, it is possible to build logic gates to add numbers stored in this manner which work very quickly (often in one clock cycle). Finding a good way to store negative integers is a bit more difficult and various methods were tried out before a satisfactory solution was found (http://en.wikipedia.org/wiki/Twos_complement). Generally chips offer very fast methods of processing integers, though multiplying, dividing and finding remainders will still take appreciably longer than one clock cycle. The question as to how to store floating-point numbers like 0.25 or π is however much more difficult and there is no single right way of doing this. As well as this, the existing circuitry for performing operations on integers would not work with these numbers, so different op-codes must be introduced. Nevertheless a standard had to be found, otherwise exchanging data between two different architectures would have been made much more difficult and computations performed on one architecture may not have reached the same result as computations performed on another. IEEE 754 (http://en.wikipedia.org/wiki/IEEE_754) specifies a number of ways of storing floating-point numbers, two of which are available to Java programmers. These are the "float" (32 bit precision) and the "double" (64 bit precision). Much as in scientific notation, where every number can be expressed as minus or plus one time a number between one and ten multiplied by a power of ten (for example 123 = +1 * 1.23 * 10*10 = +1 * 1.23 * 10²), a floating-point number is defined as minus or plus one times a number between one and two multiplied by a power of two (for example 5 = +1 * 1.25 * 2 * 2 = +1 * 1.25 * 2²). In binary, 1.25 = 1.01. Because the first digit for all numbers recorded in this manner is necessarily 1 (the number is between 1 and 2), it is not recorded and the number only requires 2 bits to store. "float" allows an accuracy of 23 bits (which is about 6 decimal places) and double 52 bits (about 16 decimal places). The rest of the space contains the sign and the power of two for the multiplication. More information can be found in the above mentioned article and only one thing has to be noted here—using first and second generation programming languages, the programmer has to make sure that they use the right op-codes for the right numbers. Calling an integer add on a float and an integer results in the wrong answer. It should be possible to write a program which checks the code to make sure that the programmer hasn't inadvertently tried to subtract a double from an integer and, if this is the case, warn the programmer (or automatically add a line transforming the integer into a double beforehand).

These considerations resulted in third generation programming languages (http://en.wikipedia.org/wiki/Third-generation_programming_language). A program which translates a text in a third generation programming language to a second or first generation programming language is called a compiler. No commonly available computer chip can run a third generation programming language natively, so this compilation step is always necessary.

Third generation programming languages have a number of advantages. The program itself does not rely on a particular architecture. This means that if a compiler is available for an architecture, the program can be compiled to run on it. Java is here different.

[edit] Why Java is different

To understand why Java is different one must first understand what Java is. In general a computer language consists of a set of rules and a list of words with which it is possible to write valid texts or programs in this language. For a language to be used, a compiler for this language has to exist and this compiler has to generate machine code for an architecture which exists. This means that if you wish to run a program on a number of architectures (standard 32 bit intel, AMD64, PowerPC, SPARC, etc.), you need to compile the program text for each architecture individually and make sure the right architecture gets the right program. This approach is not necessary with Java because the Java compiler creates machine code to be performed by another program called a virtual machine. Before a Java program can be run, a Java virtual machine must be available on the computer. Sun Microsystems provides Java virtual machines for a number of architectures and operating systems while IBM and others provide Java virtual machines for other architectures (the op-codes for the Java virtual machine are freely available so anybody with enough programming skill and free time can write a Java virtual machine for a particular architecture and operating system). The first thing the budding Java programmer has to do is make sure that a Java virtual machine is installed on their system.


Java, like many other third generation programming languages, is object oriented. This is a further programming abstraction which has proven itself useful for writing code of high quality.

[edit] CLDC/MIDP Programming

[edit] Setting up an environment

There are two straightforward ways to set up an environment for developing and testing applications for the CLDC configuration with the MIDP extension.

  • Download the Sun Java(TM) Wireless Toolkit for CLDC from www.sun.com
The Sun Java(TM) Wireless Toolkit for CLDC contains the MIDP/CLDC libraries, an emulator and debugging/profiling software. You will need to use your own text editor to create the .java files to be built
  • Download the NetBeans IDE from www.sun.com and install the Mobility Plugin using the Plugin Manager (Tools->Plugins). At time of writing, the Mobility plugin is not supported on SPARC/Solaris
The NetBeans IDE is an Integrated Development Environment offering a large amount of features for creating and running Java Technologies.

Both options require a working Java SDK. The latest version of Sun Microsystems' implementation can be downloaded from www.sun.com. It is recommended that you acquaint yourself with both possibilities. NetBeans offers many options to help programmers but these options also make it more difficult for the beginner to understand how a midlet works. To install and configure the software, follow the relevant instructions on the Sun Microsystems site.

[edit] Getting Started

In this section we will write a very simple midlet to be run using the Wireless Toolkit. A midlet is the name for a small Java program run using the J2ME technologies. Since CLDC/MIPD offers a small subset of the features of JavaSE (the version usually found on desktop computers) with a few supplementary classes for mobile phones, CLDC/MIPD programming is less extensive than JavaSE programming. Start the Wireless Toolkit by navigating to the installation directory, entering the bin directory and starting the ktoolbar application. If you have a compatible Java installation on your system, the program will start.

  • click New Project...
  • enter a Project Name, for example project01
  • enter a MIDlet Class Name, for example MyFirstMidlet
an API Selection screen will open. Click OK

If you now navigate to the installation directory and enter the apps directory, you will see a new folder named project01 has appeared among a number of folders containing demonstration midlets.

  • enter the project01 folder
the Wireless Toolkit has created a number of folders ready to hold files generated when building the project
  • enter the src folder
  • using a text editor, enter the following file:
import javax.microedition.midlet.*;
import java.lang.System;

public class MyFirstMidlet extends MIDlet {
	
	public MyFirstMidlet() {
		System.out.println("hello world!");
		destroyApp(false);
	}
	
	public void startApp() {}
	
	public void pauseApp() {}
	
	public void destroyApp(boolean unconditional) {}
}

Not a book title page. Please remove {{alphabetical}} from this page.

Personal tools
Create a book