Вы находитесь на странице: 1из 15

J2ME

introducción al lenguaje Java.


En este capítulo quiero presentarte, de forma general, J2ME y encuadrarla
dentro de la tecnología Java. También vamos a hacer una breve introducción al
lenguaje Java, al menos en sus aspectos básicos para poder adentrarte sin
problemas en la programación con J2ME.

J2ME
Cuando Sun decidió lanzar su nuevo standard Java, llamado Java2, creó tres
diferentes entornos para desarrollo y ejecución de aplicaciones. Estos fueron
J2SE, J2EE y J2ME.

J2SE (Java 2 Standard Edition) es, por decirlo de alguna manera, la base de la
tecnología Java. Permite el desarrollo de applets (aplicaciones que se ejecutan
en un navegador web) y aplicaciones independientes (standalone). J2SE es el
heredero directo del Java inicial (antes de Java 2). J2EE (Java 2 Enterprise
Edition) está basado en J2SE, pero añade una serie de características
necesarias en entornos empresariales, relativos a redes, acceso a datos y
entrada/salida que requieren mayor capacidad de proceso, almacenamiento y
memoria. La decisión de separarlos es debida a que no todas estas
características son necesarias para el desarrollo de aplicaciones standard.
Al igual que J2EE cubre unas necesidades más amplias que J2SE, se hace
patente la necesidad de un subconjunto de J2SE para entornos más limitados.
La respuesta de Sun es J2ME (Java 2 Micro Edition).
J2ME se basa en los conceptos de configuración y perfil. Una configuración
describe las características mínimas en cuanto a la configuración hardware y
software. La configuración que usa J2ME es la CLDC (Connected Limited
Device Configuration).

Concretamente CLDC define:


- Cuáles son las características del lenguaje Java incluidas.
- Qué funcionalidad será incluida en la máquina virtual Java.
- Las APIs necesarias para el desarrollo de aplicaciones en móviles.
- Los requerimientos Hardware de los dispositivos.
Debido a las limitaciones del hardware en el que correrá la máquina virtual,
algunas de las características del lenguaje Java han sido recortadas. En
concreto, se ha omitido el soporte de operaciones matemáticas en punto
flotante, y por lo tanto, los tipos de datos que manejan esta de información. La
otra gran diferencia es que la máquina virtual tampoco dará soporte al método
finalize() encargado de eliminar los objetos de la memoria. También se limita el
número de excepciones disponibles para el control de errores.
J2ME está formado por la configuración CLDC y por el perfil MID (conocido por
MIDP o MID Profile). CLDC es una especificación general para un amplio
abanico de dispositivos, que van desde PDAs a teléfonos móviles y otros. Un
perfil define las características del dispositivo de forma más específica. MIDP
(Mobile Information Device Profile) define las APIs y características hardware y
software necesarias para el caso concreto de los teléfono móviles. Las
características concretas de la versión 1.0 y 2.0 de MIDP pueden ser
consultadas en la página web de Sun (http://java.sun.com/j2me/).
Introducción
Los pasos a seguir para crear una aplicación Java para nuestro terminal Java
enabled. Lo primero de todo será conseguir e instalar los entornos de
desarrollo necesarios para empezar a desarrollar:
- J2SDK 1.3 (o superior) Proporciona la base sobre la que se instalan el resto
de aplicaciones.
- J2ME Wireless Toolkit 1.0.1 (o superior) Ofrece un entorno de compilación,
depuración y ejecución para la creación de MIDlets bajo la plataforma J2ME.

Una vez instalados todos estos componentes comenzaremos el proceso de


desarrollo. Para ello se seguirán los siguientes pasos:

Instalación e inicio de Wireless Toolkit


Nota.- Durante la instalación de este programa se preguntará al usuario entre
dos tipos de instalación: “Integrated” y “Stand Alone”.
- La primera permitirá a aquellos usuarios de Forte for Java crear aplicaciones
(MIDlets) desde dicho entorno, para lo cual deberá estar instalado ya el
programa.
- La segunda opción no incluye esta posibilidad y será el usuario el que edite el
código fuente con el programa que desee.
Una vez instalado correctamente este software de desarrollo se instalará en
nuestro menú ,Inicio un acceso directo al programa. Para iniciarlo nos bastará
con ejecutar el icono kToolbar que ejecutará el
programa principal del Wireless Toolkit.
Nota.- En algunos sistemas operativos como Windows NT o Windows 2000
puede que no se cree este acceso al programa. En este caso bastará con
ejecutar el fichero kToolbar .bat del directorio bin de la aplicación.

Nuestro primer MIDlet

En esta oportunidad vamos a construir y ejecutar nuestro primer MIDlet.


Existen diferentes herramientas válidas para construir programas bajo el
standard J2ME, como el propio “Sun One Studio” de Sun Microsystems o
“Jbuilder” de Borland. Nosotros vamos a valernos del “J2ME Wireless Toolkit
2.0” que proporciona Sun. Este entorno es el más sencillo de utilizar, y aunque
no nos ofrece una gran potencia a la hora de desarrollar aplicaciones, no nos
distraerá con grandes complejidades del principal objetivo que es aprender a
hacer aplicaciones (juegos) en J2ME.

Para instalar J2ME Wireless Toolkit, primero hemos de instalar el entorno de


programación de J2SE (JDK). Una vez descargado e instalado, estaremos en
condiciones de descargar e instalar J2ME, El entorno de desarrollo que nos
provee el Wireless Toolkit se llama KToolBar.

Compilando el primer MIDlet

Vamos a construir paso a paso nuestro primer MIDlet usando esta herramienta.
Tras la instalación del wireless toolkit, tendremos un nuevo submenú en el
menú inicio con un aspecto similar a éste:
Selecciona la aplicación KToolBar e inicializa el entorno. Verás aparecer la
ventana del entorno.

Vamos a crear un nuevo proyecto, así que pulsamos el botón New Project.
Nos solicitará un nombre para el proyecto y otro para la clase principal de la
aplicación.
Tanto el proyecto como la clase principal se llamarán HelloWorld, así que
introducimos este nombre en ambos cuadros de texto y pulsamos el botón
Create Project. En este momento KToolBar crea la estructura de directorios
necesaria para albergar el proyecto.

Cada una de las carpetas creadas tiene una misión concreta. Por ahora nos
bastará saber que nuestros archivos fuente irán emplazados en el directorio src,
y los recursos necesarios como gráficos, sonidos, etc... se alojarán en el
directorio res.

A diferencia de otros entornos de programación, KToolBar no cuenta con un


editor integrado para editar los programas, por lo tanto vamos a utilizar uno
externo. Puedes utilizar el bloc de notas de Windows o tu editor favorito.

Utilizando tu editor favorito introduce el programa siguiente:

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

public class HelloWorld extends MIDlet implements CommandListener {


private Command exitCommand;
private Display display;
private Form screen;

public HelloWorld() {
// Obtenemos el objeto Display del midlet.
display = Display.getDisplay(this);
// Creamos el comando Salir.
exitCommand = new Command("Salir", Command.EXIT,2);

// Creamos la pantalla principal (un formulario)


screen = new Form("HelloWorld");

// Creamos y añadimos la cadena de texto a la pantalla


StringItem saludo = new StringItem("","Hola Mundo...");
screen.append(saludo);

// Añadimos el comando Salir e indicamos que clase lo


manejará
screen.addCommand(exitCommand);
screen.setCommandListener(this);
}

public void startApp() throws MIDletStateChangeException {


// Seleccionamos la pantalla a mostrar
display.setCurrent(screen);
}

public void pauseApp() {


}

public void destroyApp(boolean incondicional) {


}

public void commandAction(Command c, Displayable s) {


// Salir
if (c == exitCommand) {
destroyApp(false);
notifyDestroyed();
}
}
}

No es necesario tratar de comprender el programa ahora. Entraremos en más


detalles un poco más adelante. Por ahora simplemente lo vamos a almacenar
en el directorio src que ha creado KToolBar con el nombre HelloWorld.java. Es
importante que el nombre sea exactamente éste incluidas mayúsculas y
minúsculas. Esto es así, ya que el nombre de la clase principal tiene que ser
idéntico al nombre del archivo que lo contiene. Una vez hecho esto, volvemos
al entorno KTooBar y pulsamos el botón Build. Si todo va bien, aparecerá el
texto Build Complete. Ya tenemos nuestro programa compilado y podemos
ejecutarlo en el emulador. En el desplegable Device puedes seleccionar el
emulador que quieres utilizar. El DefaultColorPhone tiene soporte de color, así
que te resultará más atractivo. Pulsa el botón Run. Verás aparecer un
emulador con forma de teléfono móvil. En la pantalla del móvil aparece un
menú con un sólo programa llamado HelloWorld. Pulsa select para ejecutarlo.

Deberías ver como aparece la frase Hola Mundo... en la pantalla.

Ahora que hemos comprobado que el programa funciona en el emulador,


estamos listos para empaquetar el programa y dejarlo listo para descargar a un
dispositivo real. En KToolBar despliega el menú project, y selecciona create
package del submenú package. KToolBar nos informa de que ha creado los
archivos HelloWorld.jar y HelloWorld.jad dentro del directorio bin. Estos son los
archivos que habremos de transferir al teléfono móvil.
Desarrollo del programa
La aplicación se podrá desarrollar con cualquier editor de textos, la única
limitación es que los ficheros residan en los directorios antes mencionados.
Para crear una aplicación el programador deberá ceñirse al API ofrecido por el
entorno MIDP de J2ME.
(Debido a la extensión de este API se recomienda consultar la versión HTML
del mismo para más información).

Compilación y depuración
La fase de compilación se deberá efectuar bajo el entorno del : Wireless Toolkit
. Este entorno ofrece una serie de posibilidades de depuración y emulación
que dependen de la versión instalada.
Una vez creados los ficheros fuentes y colocados en el directorio VUF
anteriormente comentado se pulsará el botón Build de la pantalla principal. En
ese momento se realiza la compilación, preverificación de clases y
empaquetamiento de todos los recursos (clases, imágenes, datos, etc..)
necesarios para la ejecución. Los ficheros resultantes son dos: fichero.jar y
fichero.jad.
El primero es propiamente el fichero que contiene la aplicación en sí. El
segundo contiene la definición de los datos existentes en el anterior fichero.

Las siguientes aplicaciones son un ejemplo de las facilidades que permite Java
para dispositivos móviles:

Ejemplo 01: Visor de Imágenes.


La siguiente aplicación consiste en un visor de imágenes en formato PNG.
Estas imágenes las obtiene de la URL que le especifiquemos, haciendo una
conexión y descargando la imagen para visualizarla.
El código fuente de esta aplicación es el siguiente:

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.io.*;
import java.io.*;
/*--------------------------------------------------
* Main class definition
*-------------------------------------------------*/
public class pngViewer extends MIDlet implements CommandListener
{
private Display display;
private TextBox tbxMain;
private Form frmViewPng;
private Command cmdExit;
private Command cmdView;
private Command cmdBack;
/*--------------------------------------------------
* Constructor for the class.
*-------------------------------------------------*/
public pngViewer()
{
display = Display.getDisplay(this);
// Create the Main textbox with a maximum of 50 characters
tbxMain = new TextBox("Enter png url",
"http://www.corej2me.com/scratch/spin.png", 50, 0);
// Create commands and add to textbox
cmdView = new Command("View", Command.SCREEN, 1);
cmdExit = new Command("Exit", Command.SCREEN, 1);
tbxMain.addCommand(cmdView );
tbxMain.addCommand(cmdExit);
// Set up a listener to "capture" button presses
tbxMain.setCommandListener(this);
// ---------------------------------------
// Create the form that will hold the png image
frmViewPng = new Form("Png Image");
// Create commands and add to form
cmdBack = new Command("Back", Command.BACK, 1);
frmViewPng.addCommand(cmdBack);
// Set up a listener to "capture" button presses
frmViewPng.setCommandListener(this);
}
/*--------------------------------------------------
* Called by the Application Manager on the device
* to start the MIDlet.
*-------------------------------------------------*/
public void startApp()
{
// Display the Main textbox
display.setCurrent(tbxMain);
}
/*--------------------------------------------------
* A required method.
* Does nothing in this MIDlet
*-------------------------------------------------*/
public void pauseApp()
{}
/*--------------------------------------------------
* A required method.
* Does nothing in this MIDlet

*-------------------------------------------------*/
public void destroyApp(boolean unconditional)
{}
/*--------------------------------------------------
* Process events
*-------------------------------------------------*/
public void commandAction(Command c, Displayable s)
{
// If the Command button pressed was "Exit"
if (c == cmdExit) {
destroyApp(false);
notifyDestroyed();
} else if (c == cmdView) { // If the Command button pressed was "View"
// Remove anything that may be on the form
if (frmViewPng.size() > 0)
for (int i = 0; i < frmViewPng.size(); i++)
frmViewPng.delete(i);
// Get the image from the web and append to the form
Image img;
if ((img = getImage(tbxMain.getString())) != null)
frmViewPng.append(img);
// Display the form with the image
display.setCurrent(frmViewPng);
} else if (c == cmdBack) { // If the Command button pressed was "Back"
display.setCurrent(tbxMain);
}
}
/*--------------------------------------------------
* Open an http connection and download a png file
* into a byte array.
*-------------------------------------------------*/
private Image getImage(String imageStr)
{
try
{
HttpConnection conn = (HttpConnection) Connector.open(imageStr);
// Check to see if we successfully opened the connection
int response = conn.getResponseCode();

if(conn.getResponseCode() == HttpConnection.HTTP_OK )
{
int length = (int) conn.getLength();
if (length > 0)
{
byte imageData[] = new byte[length];
InputStream in = conn.openInputStream();
// Read the png into an array
in.read(imageData);
// Create the image from the byte array
return Image.createImage(imageData, 0, length);
}
}
else
{
frmViewPng.append("Error getting png");
}
}
catch (IOException e)
{
frmViewPng.append("IO Error");
}
return null;
}
}

De la ejecución de esta aplicación se obtiene una serie de pantallas como


estas:

Ejemplo 02: Timer

Esta aplicación consiste en un contador gráfico. Mediante dos barras de


tareas que se desplazan (incremento/decremento) se visualiza un
transcurso temporal.
El código fuente de esta aplicación es el siguiente:

import java.lang.*;
import java.io.*;
import java.util.*;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
/**
* A simple class that shows an example of using a Timer and
* a TimerTask.
*
* This MIDlet creates two gauges. One gauge gaugeOne,
* sets elements from low to high. The other, gaugeTwo,
* set elements from high to low. In effect, this has
* gaugeOne "going up", and gaugeTwo "going down."
*
* The two timers fire at different intervals.
*
* There are two commands on our form:
*
* OK: toggles whether the times are active or not.
* EXIT: exits the MIDlet.
*/
public class TimerMIDlet extends MIDlet implements CommandListener {
// number of elements in gauge
final private static int GAUGE_MAX = 10;
private boolean timersRunning; // tracks state of timers
private Display myDisplay; // handle to the display
private Gauge gaugeOne; // "going up" gauge
private Gauge gaugeTwo; // "going down" gauge
private Form myScreen; // form on which to
// place gauges
15
private Command cmdOK; // OK command
private Command cmdExit; // EXIT command
private Timer timer;
private MyTimerTask timerTaskOne;
private MyTimerTask timerTaskTwo;
/**
* Internal class that provides a TimerTask.
*/
private class MyTimerTask extends TimerTask {
private Gauge myGauge; // reference to gauge
private boolean goUp; // if true, go up
private int num; // number of times called
/**
* Public constructor: stores "direction" and a reference to
* a gauge.
*/
public MyTimerTask(Gauge g, boolean up) {
myGauge = g;
goUp = up;
}
/**
* As the timer fires, this method is invoked. Set gauge
* based on goUp
*/
public void run() {
num++;
myGauge.setValue(goUp ?
GAUGE_MAX -(num % GAUGE_MAX) :
num % GAUGE_MAX);
}
}
/**
* Public constructor: gets handle to display,
* creates form, gauges, and commands.
*/
public TimerMIDlet() {
myDisplay = Display.getDisplay(this);
myScreen = new Form("TimerMIDlet");
gaugeOne = new Gauge("Up Gauge",
false,
GAUGE_MAX,
0);
myScreen.append(gaugeOne);
gaugeTwo = new Gauge("Down Gauge",
16
false,
GAUGE_MAX,
GAUGE_MAX);
myScreen.append(gaugeTwo);
cmdOK = new Command("OK", Command.OK, 1);
cmdExit = new Command("Exit", Command.EXIT, 1);
myScreen.addCommand(cmdOK);
myScreen.addCommand(cmdExit);
myScreen.setCommandListener(this);
}
/**
* Changes the state of timers to/from active to/from
* not-active.
*/
private void flipFlop() {
if (timersRunning) {
timerTaskOne.cancel();
timerTaskTwo.cancel();
timer.cancel();
timersRunning = false;
} else {
timer = new Timer();
timerTaskOne = new MyTimerTask(gaugeOne, false);
timerTaskTwo = new MyTimerTask(gaugeTwo, true);
timer.schedule(timerTaskOne, 0, 1000);
timer.schedule(timerTaskTwo, 0, 1500);
timersRunning = true;
}
}
/**
* Called by the system to start our MIDlet.
* @exception MIDletStateChangeException
*/
protected void startApp() throws MIDletStateChangeException {
myDisplay.setCurrent(myScreen);
flipFlop();
}
/**
* Called by the system to pause our MIDlet.
* No actions required by our MIDLet.
*/
protected void pauseApp() {}
/**
* Called by the system to end our MIDlet.
17
* No actions required by our MIDLet.
*/
protected void destroyApp(boolean unconditional) {}
/***
* Respond to command selections. Process two commands:
*
* OK: flip flop the timers to/from active
* EXIT: exit this MIDlet
*
*/
public void commandAction(Command c, Displayable d) {
if (c == cmdOK) {
flipFlop();
} else if (c == cmdExit) {
destroyApp(false);
notifyDestroyed();
}
}
}

De la ejecución de esta aplicación se obtiene una serie de pantallas como


estas:
Introducción a UI en MIDP

Para finalizar la clase de hoy veremos, en el apartado siguiente, algunas clases


básicas de interfaz de usuario (UI) de MIDP, incluidas todas ellas en el paquete
javax.microedition.lcdui
Displayable y Display
En J2ME, un objeto Displayable contiene la información que va a ser
visualizada, y un objeto Display gestiona qué objeto Displayable se mostrará al
usuario.
En MIDP existen tres categorías de Displayable:
Screen con estructura predefinida: Alert, List y TextBox, que encapsulan
componentes de interfaz complejos y que las aplicaciones no pueden
enriquecer con nuevos componentes.
Screen genérica: Form, las aplicaciones pueden llenar este tipo de pantalla con
texto, imágenes u otros componentes de interfaz de usuario.
Canvas, las aplicaciones tienen control total sobre la aparición de componentes
en el display y puede acceder directamente a eventos de bajo nivel.

La clase Display proporciona los métodos que nos permiten controlar la


visualización de los objetos Displayable y obtener propiedades del display (si
soporta color o no, número de colores,...).
Sólo existe una instancia del objeto Display por MIDlet, y la aplicación obtiene
una referencia a ese objeto realizando una llamada al método getDisplay() que
suele invocarse en el constructor del MIDlet. Para indicar cuál es el objeto
Displayable que se visualiza en el display se utilizan los métodos
setCurrent(Displayable nextDisplayable) y setCurrent(Alert alert, Displayable
nextDisplayable). Fijaros cómo se utilizan en el HelloWorld.
Eventos y su gestión
En MIDP la gestión de eventos sigue el mismo modelo que se usa en AWT en
J2SE, este modelo comprende dos componentes: las fuentes de eventos, que
los generan y los "listeners" de eventos, que son los que los procesan. En
MIDP los "listeners" de eventos van a estar asociadas a objetos Displayables,
que son las fuentes de eventos.

El UI de MIDP a alto nivel utiliza dos tipos de eventos: Command y


ItemStateChanged, cada uno de estos eventos tiene el correspondiente listener
asociado: CommandListener y ItemStateListener, respectivamente. Cualquier
objeto Displayable puede ser fuente de eventos Command mientras que sólo
Form puede ser fuente de ItemStateListener.

A bajo nivel el UI de MIDP permite gestionar un mayor número de eventos,


incluyendo pulsación de cualquier tecla, pantalla táctil,...Para poder capturar
eventos a bajo nivel se deben de utilizar Displayables de bajo nivel, es decir la
clase Canvas o subclases de la misma.

Tanto los eventos a alto nivel, como a bajo nivel tienen una cosa en común: la
gestión de eventos debe de realizarse siempre en el mismo thread en el que se
produce el evento.
Para finalizar esta práctica veremos la clase Command y CommandListener
utilizadas en el ejemplo HelloWorld.

Un objeto Command tiene tres valores importantes:


Label: un String que representa el significado del Command, y es el que la
aplicación muestra a los usuarios
Type: un entero que especifica lo que va a realizar el Command. Los tipos
definidos son BACK, CANCEL, HELP, EXIT, ITEM, OK, SCREEN, y STOP
Priority: un entero que indica la importancia del comando. El que tenga un
número menos será el más importante
Las implementaciones de MIDP mapean estos comandos con lo que se
denominan "soft-button", típicamente los botones que no son numéricos en el
teléfono y que sirven para navegar por los menús.

CommandListener es un interfaz que proporciona el procesamiento de un


evento Command, a través del método commandAction(Command c,
Displayable d) que deberemos implementar con las acciones oportunas.

Вам также может понравиться