Herramientas de programación JAVA de dispositivos móviles
-
Upload
lp2008a9788 -
Category
Documents
-
view
25 -
download
2
Transcript of Herramientas de programación JAVA de dispositivos móviles
Tutorial: Herramientas de
programación JAVA de dispositivos
móviles
Versión: 1.0, Septiembre, 2006
Autor: Manuel Gómez Olmedo Web: http://decsai.ugr.es/~mgomez, Mail: [email protected]
(C) Dpto. de CCIA Web: http://decsai.ugr.es
Introducción
En este tutorial se inicia al alumno en el uso de la herramienta KToolbar, una
de las herramientas disponibles para la realización de aplicaciones para
dispositivos móviles. En ella, una vez escrito el código fuente, puede crearse
un proyecto que permite compilar y preparar el código para su ejecución en un
emulador apropiado. De hecho, el producto final de esta herramienta puede
ser instalado, de forma directa, en el dispositivo móvil en que vaya a
emplearse. Así no tendremos que descargar nada, ni pagar....
Índice
1. Herramientas necesarias. Instalación
2. MIDlets y MIDlet suites
3. Ejecución de MIDlets
4. Uso de KToolbar
Herramientas necesarias. Instalación
Para poder compilar y ejecutar aplicaciones para dispositivos móviles
necesitamos disponer de las siguientes herramientas:
Java 2 SDK, o bien cualquier otro entorno de desarrollo que ofrezca un
compilador en linea de comandos para JAVA. Se recomienda el uso del
SDK de JAVA, ya que los ejemplos vistos en clase se centrarán sobre
esta herramienta. Se puede descargar de la página de SUN, en la
siguiente dirección: http://java.sun.com/javase/downloads/index.jsp.
Nosotros trabajeremos en el aula de prácticas con la versión 5,
actualización 6, aunque ya hay disponibles versiones más recientes
(actualización 8, e incluso verión 6 en modo beta).
Java 2 Micro Edition. Se trata del paquete completo de desarrollo
necesario. Incluye la herramienta KToolbar, junto con el perfil MIDP.
Mediante la herramienta KToolbar se puede compilar código sin
necesidad de interactuar directamente con CLDC, al mismo tiempo que
se dispone de un emulador de terminal telefónico. De esta forma se
puede comprobar el funcionamiento de la aplicación sobre un teléfono
móvil. Se puede descargar en la
direcciónhttp://java.sun.com/javame/downloads/index.jsp. La versión
más reciente es la 2.5, aunque nosotros trabajaremos con la 2.2. Esta
versión puede descargarse
desde http://java.sun.com/products/sjwtoolkit/download-2_2.html.
CLDC 1.1. Esta herramienta sólo se necesita si se trabaja a bajo nivel,
por ejemplo, para incorporar código nativo (en lenguaje C) que se
quiera incorporar a la aplicación. Se trata de la versión más reciente de
CLDC. El software necesario se puede encontrar en la
dirección: http://www.sun.com/software/communitysource/j2me/cldc/d
ownload.xml. Para instalar convenientemente CLDC hemos de seguir
los siguientes pasos (para linux):
1. Una vez descargado el archivo j2me_cldc_1_1-fcs-src-
winunix.zip (se trata de los fuentes del CLDC, comunes para
windows, linux y otras plataformas), procederemos a
descomprimirlo. Supongamos que el directorio donde está
ubicado el zip es $HOME/java. Si aquí se descomprime el
archivo (mediante el comando unzipnombrearchivo ), se generará
el directorio j2me_cldc, donde se extraerán los archivos
integrados en el zip. Uno de los subdirectorios creados
bajo j2me_cldc es build. Bajo el directorio build se pueden
encontrar diversos directorios, relativos a las diferentes
plataformas para las que está disponible CLDC. Mirad si se
encuentra el directorio $HOME/java/j2me_cldc/bin/linux. En
caso afirmativo, aquí termina el proceso de instalación. En caso
contrario es preciso continuar.
2. El siguiente paso a realizar consiste en situarnos en el directorio
asociado a la plataforma para la que se va a hacer la instalación.
En nuestro caso cambiaremos al directorio linux (dentro del
directorio build). El contenido de este directorio es un
archivo Makefile, que contiene las órdenes necesarias para
instalar la versión adecuada de CLDC. Basta ejecutar, en dicho
directorio, el comando make.
3. Así se genera la máquina virtual, en el
directorio $HOME/java/j2me_cldc/bin/linux. La máquina
virtual se denomina kvm.
Netbeans. Se trata de un entorno completo de desarrollo de
aplicaciones JAVA, con módulos especiales para aplicaciones sobre
dispositivos móviles. Dicha herramienta se puede descargar de la
dirección: htpp://www.netbeans.org. Nosotros usaremos la versión 5,
aunque hay disponibles versiones beta más recientes.
MIDlets y MIDlet suites
Las aplicaciones JAVA que se ejecutan en dispositivos que implementan
MIDP se denominan MIDlets. Un MIDlet consta de al menos una clase
JAVA, que debe derivar de la clase base
abstracta javax.microedition.midlet.MIDlet. El tiempo de ejecución de un
MIDlet viene controlado por una serie de métodos definidos en dicha clase y
que, forzosamente, todas las clases derivadas deben implementar.
Un grupo de MIDlets relacionados pueden agruparse en un MIDlet suite.
Todos los MIDlets de un suite se agrupan e instalan en un dispositivo como si
fuesen un único elemento, de forma que sólo pueden desinstalarse y
eliminarse en conjunto. Los MIDlets agrupados en un suite comparten tanto
recursos estáticos como dinámicos:
En tiempo de ejecución, si los dispositivos soportan ejecución
concurrente, todos los MIDlets se ejecutarán en la misma máquina
virtual. Por tanto, todos los MIDlets comparten las mismas instancias
de todas las clases, así como los recursos cargados en la máquina
virtual. Entre otras cosas, esto supone que se pueden compartir datos
entre MIDlets y que las primitivas de sincronización no sólo deben
usarse para proteger frente al acceso concurrente dentro de cada
MIDlet, sino también el producido por otros MIDlets asociados al
mismo suite.
El almacenamiento persistente es gestionado de forma globar para
todos los MIDlets del suite. Por tanto, los MIDlets pueden acceder
tanto a sus propios datos persistente como a los de otras clases del
MIDlet.
Como ejemplo de la forma en que los MIDlets de un suite comparten
recursos, supongamos un suite que contiene una clase denominada Contador,
destinada a mantener la cuenta del número de instancias de MIDlets
del suite que se ejecutan en cada momento.
public class Contador {
// Contador del numero de instancias
private static int instancias;
public static synchronized void incrementar(){
instancias++;
}
public static synchronized void decrementar(){
instancias--;
}
public static int obtener(){
return instancias;
}
}
Una única instancia de esta clase se cargará en la máquina virtual, sin importar
cuántos MIDlets de los que integren el suite están en ejecución en la máquina
virtual. Esto significa que el mismo dato miembro estático instancias será
usado por todos los MIDlets, por lo que los
métodos incrementar y decrementar afectarán al mismo contador. En este
caso es necesaria la sincronización para asegurar que las operaciones de
incremento y decremento sean realmente atómicas.
Es importante indicar que los MIDlets deben empaquetarse antes de poderse
instalar en los dispositivos de destino. Todo lo necesario de un suite debe
empaquetarse en un archivo JAR. La información del paquete debe incluirse
en un archivo de manifiesto. Esta información también estará especificada en
otro archivo denominado descriptor de aplicaciones JAVA (JAD: java
application descriptor), que se mantiene separado del archivo JAR.
Los archivos de manifiesto y JAD son archivos de texto con la siguiente
estructura:
nombre_atributo: valor_atributo
El nombre del atributo y su valor están separados por dos puntos, siendo el
espacio adicional opcional. Todos los atributos que son relevantes para la
instalación de MIDlets comienzan por el prefijo "MIDlet-". Una lista
completa de atributos, junto con una breve descripción de sus valores
asociados, aparece en la tabla siguiente. Los valores en las columnas JAD y
JAR indican que el atributo es obligatorio (M), opcional (O) o ignorado (I).
Nombre de
atributo
JAR JAD Valor y significado
MIDlet-Name M M El nombre del suite integrado en el archivo
JAR. El usuario podrá ver este nombre
MIDlet-
Version
M M El número de versión del suite empaquetado
en el archivo JAR. Los número de versión
tienen la forma a.b.c, donde valores
mayores indican versiones más recientes, teniendo los números de la izquierda mayor
precedencia
MIDlet-
Vendor
M M El nombre del fabricante del suite. Se trata
de texto libre.
MIDlet-n M I Atributo que describe cada uno de los
MIDlets que integran el suite. El valor
numérico n comienza en 1 y sirve para
identidicar cada uno de los MIDlets
MIDlet-Description
O O Una descripción del suite, para servir de información a los usuarios
MIDlet-Icon O O Un icono que representa al suite durante la
instalación o configuración. Se debe tratar
de una imagen en formato png (Portable Network Graphics)
MIDlet-Info-
URL
O O Dirección URL de un archivo que contiene
información adicional sobre el suite. El
contenido del archivo se mostrará al usuario, de forma que éste pueda decidir si desea o
no instalar dicho suite.
MIDlet-Data-
Size
O O Mínima cantidad de espacio de
almacenamiento persistente para que el
suite funcione de forma correcta. Se trata de espacio usado por el suite para almacenar
datos de larga duración. Se espcifica en
bytes. Si no se proporciona este atributo, se
asume que el suite no precisa almacenamiento persistente
MIDlet-Jar-
URL
I M La dirección URL del archivo JAR que
contiene el suite
MIDlet-Jar-
Size
I M El tamaño del JAR que contiene el suite, en
bytes
MIDlet-
Install-Notify
I O Una dirección URL usada para indicar
condiciones de error o de éxito en la
instalación del suite. Se trata de un atributo
no incluido en la especificación MIDP, pero soportado por J2ME.
MIDlet-
Delete-
Confirm
I O Mensaje a mostrar en caso de que el suite
vaya a ser borrado del dispositivo. Con este
atributo ocurre lo mismo que se indicó respecto al anterior: se trata de un atributo
no incluido en la especificación de MIDP
MIDlet-
specific attributes
O O Los desarrollados de MIDlets pueden
proporcionar atributos específicos
MicroEdition-
Profile
M I La versión de especificación MIDP con la que
el suite puede trabajar. Cuando aparecen
varias versiones deben separarse mediante
espacios. Las versiones especificadas en este atributo se comparan con el valor de la
propiedad microedition.profiles para
determinar la compatibilidad del suite con la
versión de MIDP disponible
MicroEdition-
Configuration
M I La configuración J2ME precisada por el suite.
El valor de este atributo se compara con la
propiedad microedition.configurationpara
determinar la compatibilidad
Se aprecia que alguna información aparece duplicada en el archivo de
manifiesto del JAR y en el archivo JAD. Veremos por qué esto es necesario.
La función del archivo de manifiesto es indicar al dispositivo el nombre y
versión del suite almacenado en el JAR, así como indicar cuáles de los
archivos empaquetados se corresponden con cada uno de los MIDlets. Para
usar esta información el dispositivo debe descargar el JAR y extraer el archivo
de manifiesto. Una vez hecho esto, se pueden mostrar los valores de los
atributos MIDlet-Name, MIDlet-Version, MIDlet-Vendor. También de los
atributos opcionales MIDlet-Description y MIDlet-Icon. Estos atributos
permiten al usuario decidir sobre la descarga. No obstante, el archivo JAR
podría ser muy grande, por lo que llevaría mucho tiempo recuperarlo en
situaciones de conexiones lentas, por ejemplo. Para evitar este problema,
algunos de los atributos del manifiesto, con información extra, se duplica en el
archivo JAD. Esto permite descargar inicialmente el archivo JAD en lugar del
JAR. De esta forma, se puede mostrar al usuario la información del suite antes
de haber descargado el archivo de sus clases. El archivo JAD contendrá
información contenida en el manifiesto y alguna particular. Típicamente, los
atributos que aparecen en él son:
MIDlet-Name
MIDlet-Vendor
MIDlet-Version
MIDlet-Description
MIDlet-Icon
MIDlet-Info-URL
MIDlet-Data-Size
MIDlet-Jar-Size
MIDlet-Jar-URL
El objetivo de estos atributos, como se indicó con anterioridad, es ofrecer
información sobre los MIDlets incluidos en el suite. Supongamos que
desarrollamos un suite denominado Notas que permiten al usuario acceso
directo a sus notas desde un dispositivo móvil. El suite contiene dos MIDlets:
uno para ver las notas y otro para enviar información sobre posibles errores en
ellas. Para desarrollar la clase se han usado métodos de utilidad,
pertenecientes a la clase Utilidades. En definitiva, las clases involucradas
serían las siguientes (teniendo en cuenta que forman parte del
paquete desarrollo.moviles):
desarrollo.moviles.VerNotas
desarrollo.moviles.ErrorNotas
desarrollo.moviles.Utilidades
El manifiesto para este suite podría ser el siguiente:
MIDlet-Name: Notas
MIDlet-Vendor: Programas Pepe
MIDlet-Version: 1.0.1
MIDlet-Description: Conjunto de midlets para ver notas
MIDlet-Icon: /desarrollo/moviles/iconos/notas.png
MIDlet-Info-URL: http://www.programaspepe.com/notas/info.html
MIDlet-Data-Size: 512
MicroEdition-Profile: MIDP-1.0
MicroEdition-Configuration: CLDC
MIDlet-1:
Visualizador,/desarrollo/moviles/iconos/ver.png,desarrollo.moviles.Ver
Notas
MIDlet-2:
Errores,/desarrollo/moviles/iconos/error.png,desarrollo.moviles.ErrorN
otas
En el archivo JAR correspondiente, el archivo de manifiesto aparecería como
META.INF/MANIFEST.mf. El archivo JAR también contendría los
siguientes archivos:
/desarrollo/moviles/VerNotas.class
/desarrollo/moviles/ErrorNotas.class
/desarrollo/moviles/Utilidades.class
/desarrollo/moviles/iconos/notas.png
/desarrollo/moviles/iconos/ver.png
/desarrollo/moviles/icones/error.png
Conviene hacer algunos comentarios en relación al valor de los atributos y al
contenido del archivo JAR:
El archivo JAR contiene las clases correspodientes a ambos MIDlets.
Aunque la clase de utilidades se incluye no hay ninguna referencia a
ella en el manifiesto.
El atributo MIDlet-Icon contiene la ruta absoluta del archivo que
contiene el icono del suite.
Asociado a cada MIDlet hay un atributo que describe su nombre y le
asocia un identificador. El valor del atributo incluye nombre, icono y
clase asociada.
El archivo JAD asociado a este MIDlet contendrá la siguiente información:
MIDlet-Name: Notas
MIDlet-Vendor: Programas Pepe
MIDlet-Version: 1.0.1
MIDlet-Description: Conjunto de midlets para ver notas
MIDlet-Info-URL: http://www.programaspepe.com/notas/info.html
MIDlet-Data-Size: 512
MicroEdition-Jar-Size: 10132
MIDlet-Jar-URL: http://www.programaspepe.com/notas/Notas.jar
Este archivo contiene la información que la pantalla del dispositivo mostrará
al usuario, junto con la dirección URL del archivo JAR. En este caso, los
atributos comunes tienen el mismo valor tanto en el archivo de manifiesto
como en el archivo JAD. Para que el suite sea portable, es preciso que el
archivo JAR esté codificado usando la codificación iso-8859-1, ya que se
precisa que todas las implementaciones de MIDP soporten esta codificación.
En tiempo de ejecución los MIDlets pueden acceder a los archivos del JAR
asociado al suite y obtener información sobre los valores de los atributos.
Ejecución de MIDlets
Simplemente, como comentario inicial, aunque se comentará más tarde, los
MIDlets deben derivar de la clase
abstractajavax.microedition.midlet.MIDlet, que contiene métodos
destinados a controlar el tiempo de ejecución de los MIDlets. Todos los
MIDlets deben tener un constructor público predeterminado (es decir, que no
requiera argumentos). La estructura básica de un MIDlet se muestra a
continuación:
public class EjemploMidlet extends MIDlet{
// Constructor: opcional. Bastaría con el constructor por
// defecto
public EjemploMidlet(){
}
// Método que iniciará la ejecución del MIDlet
public void startApp() throws MIDletStateChangeException{
}
// Método que interrumpe la ejecución del MIDlet
public void pauseApp(){
}
// Método para finalización del MIDlet
public void destroyApp(boolean unconditional)
throws MIDletStateChangeException{
}
}
En todo momento, los posibles estados en que podría estar un MIDlet son:
pausa
activo
destruido
Inicialmente, cuando se produce la carga de un MIDlet, éste estará en
estado pausa. Cuando se produce la llamada al métodostartApp() se produce
el paso al estado activo. En cualquier instante, la plataforma MIDP podría
poner a un MIDlet en estado de pausa. Por ejemplo, en los teléfonos móviles
esto ocurrirá cuando se detecta una llamada entrante. Esto se realiza mediante
una llamada al método pauseApp(). La vuelta al estado activo precisa de una
nueva llamada a startApp(). Cuando se precisa la finalización de un MIDlet
se usará una llamada a destroyApp(...). Al producirse esta llamada se liberan
los recursos que el MIDlet pudiera estar usando, siempre que el argumento de
este método sea true. Pero pudiera haber algunas situaciones en que este tipo
de finalización no es conveniente; por ejemplo, por haber datos que aún no se
han almacenado. En este caso, la llamada al método debería hacerse usando
como argumento false. Esto produce el lanzamiento de la excepción
MIDletStateChangeException. El código debería estar preparado para capturar
la excepción y actuar en consecuencia.
Para ilustrar el ciclo de vida un MIDlet y la forma en que se controla, a la vez
que mostrar el funcionamiento de las herramientas de generación de MIDlets,
vamos a considerar un ejemplo sencillo de MIDlet, caracterizado por:
El MIDlet se llamará EjemploMIDlet1. El constructor imprime el
valor de la propiedad color (ya veremos para qué se hace esto) y
muestra un mensaje indicando que el midlet está construido y el valor
de la propiedad.
El método startApp() se encarga de mostrar un mensaje que permita
trazar el ciclo de vida del MIDlet. A continuación se hace lo siguiente:
o Si es la primera vez que se llama al método startApp(), entonces
se crea un objeto auxiliar de la clase Tarea, que permite, en una
hebra aparte, ejecutar una simple cuenta. Después de crear este
objeto se invoca al método start()del mismo, de forma que
empieze a desarrollarse la tarea indicada en el método run() de
la misma. Finalmente se cambiará el valor de la variable
booleana, de forma que la próxima vez que se llame al
método startApp() se sepa que se trata de una llamada
producida al salir de una pausa.
o Si no es la primera vez que se llama al método startApp(),
entonces se prosigue con la ejecución de la tarea realizada por la
hebra, desde el punto en que se quedara parada previamente
como consecuencia de la pausa. Cuando la tarea se finaliza, se
fuerza la destrucción del MIDlet, mediante la llamada
a destroyApp(true). El argumento true pasado
a destroyApp indica que se busca liberar todos los recursos que
el MIDlet pudiera estar usando.
El método pauseApp() se invoca al producirse una llamada telefónica,
por ejemplo. Para forzar este evento hay una opción concreta del menú
MIDlet de KToolbar. Al recibirse la llamada a este método, se muestra
un mensaje para seguir la traza de funcionamiento. Se imprime el
estado de trabajo de la tarea auxiliar (de la cuenta) y se fuerza a que la
hebra deje de trabajar. Este es el objetivo de la
llamada tarea.interrumpir().
Como no se sabe aún lo suficiente como para construir interfaces de usuario
(aunque pronto se sabrá), todos los mensajes se enviarán a la salida estándar.
Se incluye a continuación el código correspondiente, y seguidamente se verá
cómo generar el suite, tanto de forma manual como automática.
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
public class EjemploMIDlet1 extends MIDlet{
Tarea tarea;
boolean primeraVez;
// Constructor por defecto de la clase
public EjemploMIDlet1(){
String color=getAppProperty("color");
System.out.println("\n\n\nConstruido MIDlet con color: "+color);
primeraVez=true;
}
// Metodo para iniciar el funcionamiento del MIDlet
public void startApp() throws MIDletStateChangeException{
System.out.println("Metodo startApp");
if (primeraVez == true){
System.out.println("Ejecucion la primera vez.......");
System.out.println("Se inicia cuenta larga para
permitir pausar");
tarea=new Tarea();
tarea.start();
primeraVez=false;
}
else{
// Se reanuda la ejecucion tras salir de la pausa
System.out.println("Llamada tras pausa..... Valor de i:
"+tarea.getI());
tarea.continuar();
// Se destruye el midlet cuando la tarea termine
if (tarea.getFinalizado() == true){
destroyApp(true);
}
}
}
// Metodo para detener el funcionamiento del MIDlet
public void pauseApp(){
System.out.println("Metodo pauseApp");
System.out.println("Valor de i en el momento de la pausa:
"+tarea.getI());
tarea.interrumpir();
}
// Metodo para destruir el MIDlet
public void destroyApp(boolean condition){
System.out.println("Metodo destroyApp. Condicion: "+condition);
if (condition == true){
// Se indica la finalizacion del midlet
notifyDestroyed();
}
}
}
class Tarea extends Thread{
int i;
boolean interrumpido;
boolean finalizado;
Tarea(){
i=0;
interrumpido=false;
finalizado=false;
}
public void run(){
for(; i < 9000000; ){
if (interrumpido == false){
i++;
}
else{
try{
sleep(100);
}
catch(InterruptedException e){
System.out.println("Problema al dormir hebra....");
}
}
//System.out.println("Valor de i: "+i);
}
// Se finaliza la tarea
finalizado=true;
}
// Metodo para obtener el valor de i
int getI(){
return i;
}
// Metodo para interrumpir
void interrumpir(){
interrumpido=true;
}
// Metodo para continuar
void continuar(){
interrumpido=false;
}
// Metodo para acceder al valor de finalizado
boolean getFinalizado(){
return finalizado;
}
}
El código completo de este MIDlet puede descargarse directamente desde
aquí: EjemploMIDlet1.java Se trata de un MIDlet muy sencillo, que permitirá
practicar con los procedimientos de generación de MIDlets, así como los
posibles estados en que puede encontrarse un MIDlet en ejecución: pausa,
activo y destruido.
Uso de KToolbar
Seguiremos el proceso completo de trabajo sobre el MIDlet incluido
anteriormente. El primer paso consistirá en ejecutar la herramienta KToolbar.
Esta aplicación se encuentra en la instalación de Wireless Toolkit. Para
ejecutarla haremos lo siguiente (si no funciona, avisad al profesor.......).
ktoolbar
La ventana principal de KToolbar tiene la siguiente aparencia:
Crearemos un proyecto de suite, en el que incluiremos el MIDlet generado
con anterioridad. Para ello se pulsa en el botón New Project. Al pulsar sobre
él aparecerá la siguiente ventana:
Como se ve, hemos rellenado la información de ambos campos de texto.
Como nombre del proyecto podemos elegir cualquiera, sin necesidad de
coincidir con el nombre de la clase principal del MIDlet. En el segundo campo
de texto hemos de especificar el nombre de la clase principal del suite que
queremos ejecutar en el emulador. En este caso es EjemploMIDlet1. En
cuanto se pulsa el botón Create Project aparecerá una nueva ventana donde
aparecen informaciones relativas al MIDlet.
Al mismo tiempo, en la ventana principal de KToolbar han aparecido varios
mensajes:
Estos mensajes indican que se ha creado la estructura de directorios necesaria
para el proyecto, y que las clases que queramos formen parte del MIDleet
habrá que ubicarlas en el directorio src; recursos adicionales (como iconos)
irán en el directorio res y las librerías (si las hubiera) en el directorio lib.
Como se ve, el directorio del proyecto se crea en el directorio de instalación
de la herramienta, bajo el subdirectorio apps. En nuestro caso, la ruta
completa será $HOME/java/WTK2.2/apps/ejemplo1. Nuestro primer
MIDlet usará un icono muy sencillo (descargadlo aquí: iconoPeq.png).
Por tanto, lo primero que haremos será copiar el archivo con la clase asociada
al MIDlet en el directorio$HOME/java/WTK2.2/apps/ejemplo1/src/. El
icono se ubicará en el directorio $HOME/java/WTK2.2/apps/ejemplo1/res/.
Dentro de este directorio crearemos a su vez el directorio icons. Y en él será
donde se guarde el archivo png del icono. Para indicar que el icono del
MIDlet es este, debe modificarse la información sobre el icono. Para ello se
pulsa el botón Settings deKToolbar. Aparecerá la venta siguiente:
Aprovechamos ahora para indicar que deseamos que el MIDlet sea conforme
a MIDP1.0. Para ello se selecciona esta opción de las disponibles al pulsar
sobre Target Platform. Para indicar el icono asociado, se selecciona la
pestaña MIDlets. Una vez hecho esto aparecerá
Para poder cambiar el icono (el valor presente en la figura anterior se
introduce por defecto), basta con seleccionar la línea con los datos (la fila que
aparece rellena), con lo que se marcará con un color diferente para indicarnos
que está seleccionada:
Ahora basta con pulsar sobre el botón Edit, lo que dará lugar a la aparición de
la ventana de edición:
Sobre esta ventana, en el recuadro Icon escribiremos /icons/iconoPeq.png, tal
y como se aprecia a continuación:
Al finalizar se pulsa sobre el botón Aceptar de la ventana de edición. Con
esto queda registrado el cambio de la propiedad correspondiente al icono del
MIDlet:
Y pulsando sobre el botón OK desaparece la ventana de propiedades. Esto es
todo lo necesario para poder generar y ejecutar el MIDlet. En primer lugar,
procedemos a generar las clases a partir del código fuente. Para ello se pulsa
el botón Build. Si todo ha ido bien, aparecerá un mensaje indicado que la
generación se realizó de forma correcta. En caso de haber errores, se
mostrarán en la ventana principal de KToolbar.
En cuanto se ha generado el MIDlet, podemos ejecutar mediante el
botón Run. Al pulsarlo, aparecerá el emulador con el MIDlet listo para
ejecución.
Para lanzar la ejecución del MIDlet se pulsa sobre la tecla bajo el
mensaje Launch. En cuanto se produce esto el MIDlet se crea y el dispositivo
invoca al método startApp(). Esto explica los mensajes que se aprecian en la
consola de KToolbar:
Se muestra el mensaje de traza puesto en el constructor, indicando que la
propiedad color no está definida. Arreglar esto se deja para más adelante.
También se aprecia la traza ubicada a la entrada del método startApp(), que
ha sido invocado por el sistema de gestión de ejecución de MIDlets del
dispositivo móvil. Los dos mensajes que aparecen a continuación son trazas
que muestran que el MIDlet se ejecuta por primera vez.
Para pausar el MIDlet, tras unos segundos de funcionamiento, basta con
actuar sobre el menú MIDlet del emulador telefónico y seleccionar la
opción Pause. Al hacerlo el emulador queda de la forma siguiente:
A su vez, en la consola de KToolbar veremos los siguientes mensajes:
Las nuevas líneas de traza indican que se ha invocado al método pauseApp().
Como comentamos previamente, esto ocurrirá al producirse una llamada de
teléfono sobre el móvil, por ejemplo. Se observa el valor de la cuenta en el
momento en que se produjo la pausa. Para continuar ejecutando el MIDlet (lo
que ocurriría al finalizar la llamada), forzamos la salida del modo de pausa.
Para ello volvemos a actuar sobre el menú MIDlet, seleccionado la
opción Resume. Esto hace que aparezcan nuevas líneas de traza indicando
que se ha producido una nueva llamada al método startApp(), pero sin
tratarse de la primera llamada al mismo.
Por su parte, del emulador desaparece la indicación de llamada entrante:
Si se observa el código del método startApp(), se aprecia que la destrucción
del MIDlet sólo se producirá en el caso en que ya haya finalizado la tarea de
cuenta. Para asegurarnos que esto ocurre, tras la salida del modo de pausa
esperaremos unos segundos, se genera una nueva pausa (pulsando, como se
indicón previamente, sobre la opción Pause del menú MIDlet) para, a
continuación forzar, mediante Resume (en el menú MIDlet), una nueva
llamada a startApp() una vez finalizada la cuenta. Cuando esto ocurra,
tendremos:
Sólo cuando el MIDlet haya sido destruido de forma completa podrá volver a
lanzarse de forma correcta.
EJERCICIO 1: probad qué ocurre cuando se intenta lanzar de nuevo la
ejecución del MIDlet antes de que haya finalizado completamente la tarea de
cuenta. Justificad el comportamiento observado.
Cuando se usa destroyApp(false) permite que el método compruebe si se
cumplen las condiciones necesarias para finalizar o no. En caso de no
cumplirse, puede generar una excepción del
tipo MIDletStateChangeException, lo que genera a su vez una nueva
llamada startApp().
EJERCICIO 2: se propone que modifiquéis el código del MIDlet anterior de
la forma siguiente:
Montad un nuevo proyecto, ejemplo2, para trabajar sobre esta variante.
La clase del MIDlet se denominará EjemploMIDlet2. Podéis partir de
la clase EjemploMIDlet1 y modificarla.
En el método startApp(), en caso de no ser la primera llamada, después
de la sentencia tarea.continuar(), se realiza la llamada
a destroyApp(false). Esta llamada habrá que encerrarla en un
bloque try-catch, ya que el método destroyApp()podría decidir
generar la excepción si considera que el MIDlet no debe finalizar.
Modificad el método destroyApp(), de forma que en caso de recibir
como argumento false, compruebe si la tarea ha finalizado o no. Si no
ha finalizado, lanza una excepción del
tipo MIDletStateChangeException, para dar tiempo a que la tarea de
conteo finalice. Si la tarea ha finalizado, se llama al
método notifyDestroyed(), con lo que el MIDlet indica que desea
finalizar.
En nuestro caso, el MIDlet usa un valor de atributo (color). Si se observa el
código, se comprobará que al imprimir su valor se muestra null. Si se intenta
manejar esta propiedad, sin haberla especificado de forma explícita, puede
ocurrir un error como el mostrado a continuación:
Pero, ¿cómo se define este atributo?. Para ello usaremos el botón Settings.
Cuando aparezca la ventana de propiedades del MIDlet, seleccionaremos la
opción User Defined, que permitirá definir atributos propios. Sobre esta
ventana, pulsaremos el botón Add.
Al pulsar sobre Add aparecerá la ventana que hemos de usar para definir el
valor de la propiedad deseada:
Se escribe el nombre de la propiedad (color) y se pulsa sobre Aceptar. Con
esto la ventana de propiedades queda de la siguiente forma:
Se pincha sobre el campo de texto en blanco y se introduce el valor deseado:
Pulsamos OK y ya podemos volver a ejecutar el MIDlet. Ahora la traza inicial
indica:
EJERCICIO 3: probad con los MIDlets de demo que vienen con la
herramienta. Activad la monitorización, activando las preferencias (Edit +
Preferences + Monitor) deseadas. Con esto podéis haceros una idea de la
capacidad de la plataforma de desarrollo. Haced un pequeño guión con
indicaciones sobre vuestra opinión al respecto: demos más interesantes,
limitaciones, puntos fuertes, etc.