Durante los últimos años hemos visto como han ido evolucionando los teléfonos móviles, pasando de ser simplemente teléfonos a ser pequeños ordenadores en los que tenemos disponibles una serie de aplicaciones preinstaladas (mensajería, registro de llamadas, agenda, calculadora, juegos, etc).
Un paso importante en esta evolución ha sido la posibilidad de que estos dispositivos se conecten a Internet. Esto permitirá que accedan a información disponible en la red, a aplicaciones corporativas utilizando algún front-end, o descargar nuevas aplicaciones para nuestro móvil.
De esta forma vemos que se podrán incluir nuevas aplicaciones en cada dispositivo, adecuándose a las necesidades de cada usuario. Estas aplicaciones podrán ser tanto front-ends que nos permitan acceder a aplicaciones de empresa residentes en algún servidor de Internet, como aplicaciones locales para utilizar en nuestro móvil.
Nos interesará contar con un amplio repertorio de aplicaciones disponibles, y con la posibilidad de que las empresas puedan desarrollar fácilmente software para los móviles que se adapte a sus aplicaciones. Por lo tanto surge la necesidad de que los desarrolladores puedan realizar estas aplicaciones de forma rápida y con el menor coste posible, sin tener que conocer los detalles de la especificación de cada modelo concreto de móvil.
Vamos primero a estudiar las distintas eras en la evolución de Internet, según el tipo de dispositivos que se conectan a esta red, para ver el momento en el que se introducen este tipo de dispositivos y la problemática que plantean. A continuación estudiaremos las características de este tipo de dispositivos, y por último analizaremos de forma general las distintas APIs ofrecidas por la plataforma J2ME para la programación de dispositivos móviles.
Hasta hace poco hemos visto la red Internet como una red en la que se encuentran conectados ordenadores de todo el mundo. Sin embargo, durante los últimos años estamos entrando en una segunda era de Internet, en la que se están conectando a la red diferentes tipos de dispositivos heterogéneos como por ejemplo teléfonos móviles o PDAs.
En esta primera era tenemos conectados a Internet ordenadores que cuentan con una interfaz común y una capacidad mínima suficiente. La información que obtenemos de la red se obtiene normalmente en forma de páginas web escritas en HTML, diseñadas para mostrarse en dispositivos gráficos con resoluciones por encima de 640x480 pixels y con monitores de por lo menos 14".
Figura 1. El Internet de los ordenadores
Asumiendo que los clientes cuentan con esta configuración mínima, podemos elaborar páginas que se visualicen correctamente en ellos. Es decir, parte de la capa de presentación residirá en el servidor, ya que estas páginas HTML definirán el formato con el que se mostrará la información. Los navegadores en las máquinas cliente deberán ser capaces de interpretar el código HTML y mostrar en pantalla las páginas web.
Al incorporarse distintos tipos de dispositivos a Internet, cada uno de ellos con interfaces y capacidad totalmente distinta, ya no va a ser posible definir una presentación única en el lado del servidor, ya que ésta no va a poder ser visualizada correctamente por todos los clientes.
Figura 2. El Internet de los dispositivos
Estos dispositivos llevan ordenadores embebidos, en muchos casos con grandes limitaciones en su interfaz y baja capacidad, debido a su reducido tamaño o a la escasa necesidad de incorporar un ordenador mayor que encarecería el producto. Deberán conectarse a Internet utilizando estos ordenadores, por lo que el acceso será distinto dependiendo del dispositivo del que se trate.
Una posible solución es definir un nuevo tipo de documento, adaptado a la reducida interfaz de estos dispositivos. Este es el caso por ejemplo de los documentos WML para los teléfonos móviles WAP. El problema es que si definimos esta presentación en el servidor para todos los móviles, tendremos que definirla de forma que sea compatible con todos los modelos existentes que soporten esta tecnología. Conforme mejoran los modelos de móviles, podríamos visualizar en ellos aplicaciones más ricas, pero el tener que utilizar un formato compatible para todos los móviles nos obligará a definir un documento bastante más pobre que sea soportado por todos ellos.
Por ello en esta segunda era surgen nuevos paradigmas para la programación web. La información se empezará a ofrecer en forma de servicios, en lugar de documentos. Es decir, obtendremos de Internet únicamente la información, pero no la presentación. Por ejemplo, esta información puede estar codificada en lenguaje XML siguiendo un determinado estándar, de forma que cualquier aplicación sea capaz de entenderla, o bien utilizar nuestra propia codificación. De esta forma, cada cliente (móvil) tendrá aplicaciones adaptadas a sus características, que obtendrán de Internet únicamente la información a la que necesitan acceder.
Nos vamos a centrar en la programación de este tipo de aplicaciones para dispositivos móviles. Estas aplicaciones se alojarán y se ejecutarán de forma local en el dispositivo. Será deseable que la API (Interfaz de Programación de Aplicaciones) que ofrezca cada dispositivo para programar en él nos permita utilizar todas las características del mismo, y establecer conexiones de red para obtener la información necesaria de Internet.
En una futura era de Internet, podrá formar parte de Internet cualquier cosa. Podremos de esta forma tener conectada a la red ropa, productos de alimentación o cualquier otra cosa que incorpore un chip capaz de conectarse y ofrecer información sobre el producto. Con esto se disparará el número de elementos conectados a la red.
Figura 3. El Internet de las cosas
Por ejemplo, la tecnología Auto ID consiste en un pequeño chip transmisor (del tamaño de la cabeza de un alfiler) que podrá ser incluido en los artículos. Este chip vendrá a sustituir en el futuro al código de barras, ya que además de ofrecernos toda la información sobre el producto, nos permitirá conocer su localización. Para comunicarse emitirán una señal de radio, que será recibida por un receptor conectado a un ordenador que nos ofrezca la información sobre estas "cosas" conectadas.
De esta forma podremos saber fácilmente si en nuestra tienda tenemos un determinado tipo de productos, o si se han agotado y tenemos que realizar un pedido. También podremos saber si alguien se lleva un producto de nuestra tienda, lo cuál será útil para evitar robos. O incluso ver si en nuestra tienda tenemos productos que hayan caducado, y descubrir dónde están estos productos para poder retirarlos de la venta.
Vemos que esta tecnología tiene multitud de posibles aplicaciones. Como inconveniente, tenemos la presunta violación de la intimidad de los consumidores al poder estos chips ofrecer información sobre los artículos que han adquirido.
Hemos visto como en la segunda era de Internet surgen los Servicios Web como alternativa a los documentos web (como las páginas HTML y WML por ejemplo). Podemos definir un servicio como la interfaz que nos da acceso a un módulo de funcionalidad.
Por ejemplo, podemos tener un servicio que nos permita acceder a información
sobre cambio de monedas. Este servicio nos ofrecerá una operación
cambioVenta(moneda_origen, moneda_destino)
que nos devolverá
el cambio actual entre dos monedas, para la venta, y otra operación análoga
cambioCompra(moneda_origen, moneda_destino)
para obtener esta información
en el caso de la compra.
Un Servicio Web será un servicio al que podamos acceder mediante protocolos web estándar. Se utilizará lenguaje XML para codificar el mensaje de invocación de las operaciones del servicio, y la respuesta que nos haya devuelto la operación. De esta forma podremos invocar servicios a través de Internet.
Los documentos web mezclan la información y la presentación. Normalmente la información que ofrecen está escrita en lenguaje natural y formateada de forma que los humanos la podamos entender fácilmente. Sin embargo, esto será difícilmente entendible por una aplicación. Los Servicios Web nos ofrecen únicamente la información que nos ha devuelto la operación invocada. Por ello podemos ver estos Servicios Web como la web para aplicaciones, frente a los documentos web que serían la web para humanos. Serán las aplicaciones instaladas en el cliente, que invocan los Servicios Web, las encargadas de dar formato y presentar al usuario la información obtenida.
En la actualidad podemos encontrar algunos Servicios Web ofrecidos por una serie de proveedores. En el futuro Internet será como un gran Sistema Operativo distribuido, en el que haya disponibles un gran número de servicios que puedan ser utilizados por cualquier máquina conectada a la red. De esta forma las aplicaciones se encontrarán distribuidas en Internet, es decir, estarán formadas por módulos que podrán residir en distintos lugares del mundo. La cuestión es quién se hará con el control de este gran Sistema Operativo, ¿Microsoft con .NET o Sun con las tecnologías Java?.
Vamos a ver los distintos tipos de dispositivos con ordenadores embebidos que podemos encontrar, así como sus características, para luego centrarnos en los dispositivos móviles de información (Mobile Information Devices, MIDs) que son los que trataremos con mayor detalle.
Podemos encontrar distintos dispositivos con ordenadores embebidos que van introduciéndose en nuestros hogares. Por un lado tenemos los teléfonos móviles y las agendas electrónicas o PDAs. Estos dispositivos son conocidos como dispositivos móviles de información (MIDs). Incorporan un reducido Sistema Operativo y una serie de aplicaciones que se ejecutan sobre él (Agenda, Notas, Mensajes, etc) adaptadas a la interfaz de estos dispositivos, de forma que se puedan visualizar correctamente en su pequeña pantalla y que se puedan manejar usando el teclado del teléfono o el puntero del PDA por ejemplo.
A parte de los MIDs encontramos más tipos de dispositivos, cuyo número crecerá conforme pase el tiempo. Tenemos por ejemplo los descodificadores de televisión digital (set top boxes). Las plataformas de televisión digital, tanto por satélite, por cable, o terrestre, ofrecen una serie de servicios accesibles desde estos descodificadores, como por ejemplo servicios de teleguía, juegos, etc. Para ello deberemos tener aplicaciones que se ejecuten en estos dispositivos.
Los electrodomésticos también siguen esta tendencia y ya podemos encontrar por ejemplo frigoríficos o lavadoras con un pequeño computador capaz de conectarse a la red doméstica. La idea es integrar todos estos dispositivos es nuestra red para construir un sistema domótico. Para ello todos los dispositivos que queramos integrar deberán ser capaces de conectarse a la red.
Hablamos de dispositivos conectados para referirnos a cualquier dispositivo capaz de conectarse a la red. Podemos tener distintos tipos de dispositivos conectados, con grandes diferencias de capacidad. Un subgrupo de estos dispositivos conectados son los MIDs de los que hemos hablado previamente.
Vamos a centrarnos en el estudio de los MIDs. Para ello vamos a ver las características de una serie de modelos actuales con lo que podremos hacernos una idea del rango de memoria y los tipos de interfaz con los que vamos a tener que trabajar.
Nokia 8310 |
Nokia 3410 |
Nokia 6100 |
Nokia 3650 |
|
Interfaz | 84x48 Monocromo |
96x65 Monocromo |
128x128 12bits (4096 colores) |
176x208 12 bits (4096 colores) |
Memoria | - | Heap 164 KB Shared 150 KB JAR 50 KB |
Heap 200 KB Shared 725 KB (625 KB en 6610, 7210) (4,6 MB en 7250) (4,5 MB en 3300) JAR 64 KB |
Heap 1,4 MB (2,4 MB en N-Gage) Shared 3,4 MB (4 MB en 7650, N-Gage) JAR 4 MB |
APIs | - | CLDC 1.0 MIDP 1.0 WMA Nokia UI Nokia SMS |
CLDC 1.0 MIDP 1.0 Nokia UI WMA (3300) |
CLDC 1.0 MIDP 1.0 WMA (N-Gage, 3650) MMAPI (N-Gage, 3650) Nokia UI SO Symbian |
Otros | HSCSD GPRS (8310) CSD (3330) WAP 1.2.1 (8310) WAP 1.1 (3330) IrDA (8310) |
CSD WAP 1.1 |
HSCSD GPRS WAP 1.2.1 USB IrDA Cámara (7250) |
HSCSD |
SL45i |
C55 |
SL55 |
|
Interfaz |
101x80
Monocromo |
101x64 Monocromo |
101x80 12 bits (4096 colores) (256 colores en S55) |
Memoria |
Heap
147 KB Flex 0,2 MB JAR 70 KB |
Heap
150 KB Flex 0,5 MB (0,2 MB en M50) JAR 70 KB |
Heap
365 KB (560 KB en M55) Flex 1,6 MB (1 MB en S55) JAR 70 KB |
APIs |
MIDP
1.0 |
MIDP
1.0 |
MIDP
1.0 |
Otros |
WAP
1.1 IrDA |
GPRS WAP 1.2.1 |
GPRS WAP 1.2.1 IrDA (S55, SL55) Bluetooth (S55) Cámara (SL55) |
Nokia 9210 |
Sharp Zaurus SL-5500 |
Palm Tungsten |
HP iPAQ Pocket PC H1930 |
|
Interfaz |
640x200 12 bits (4096 colores) |
240x320 16 bits (65536 colores) |
240x320
Color |
240x320
Color |
Memoria |
8
MB SD-RAM 18 MB disponibles 14 MB aplicaciones |
64
MB RAM |
16
MB RAM |
64
MB SDRAM |
APIs |
PersonalJava JavaPhone SO Symbian |
SO
Linux 2.4 |
SO
Palm |
SO
Windows Pocket PC 2003 Professional |
Otros |
HSCSD WAP 1.1 HTML 3.2 IrDA Cable serie |
IrDA USB |
IrDA Bluetooth USB |
IrDA USB |
Podemos ver que las características de los móviles varían bastante, tanto a nivel de memoria como de interfaz entre los diferentes modelos disponibles. Además, a medida que aparezcan modelos nuevos encontraremos mayor diferencia entre los modelos antiguos y los más recientes. Es difícil realizar una aplicación que se adapte perfectamente al modelo utilizado. Por eso normalmente lo que se hará será realizar distintas versiones de una misma aplicación para distintos conjuntos de móviles con similares características. El coste de hacer una aplicación capaz de adaptarse sería mayor que el de hacer varias versiones de la aplicación, intentando siempre hacerlo de forma que tenga que modificarse la menor cantidad de código posible.
Tenemos además un problema adicional, y es que cada móvil puede tener su propia API. Distintos modelos de móviles, tanto de marcas distintas como de la misma marca, pueden incluir Sistemas Operativos diferentes y por lo tanto una interfaz diferente para programar aplicaciones (API). Esto nos obligará a tener que modificar gran parte del código para portar nuestras aplicaciones a diferentes modelos de móviles. Dado el creciente número de dispositivos disponibles esto será un grave problema ya que será difícil que una aplicación esté disponible para todos los modelos.
Aquí es donde aparece la conveniencia de utilizar tecnologías Java para programar este tipo de dispositivos tan heterogéneos. Sun ha apostado desde hace tiempo por las aplicaciones independientes de la plataforma con su tecnología Java. Esta independencia de la plataforma cobra un gran interés en este caso, en el que tenemos un gran número de dispositivos heterogéneos.
Con la edición Micro Edition de Java 2, se introduce esta plataforma en los dispositivos. De esta forma podremos desarrollar aplicaciones Java que puedan correr en todos los dispositivos que soporten las APIs de J2ME. Al ser estas APIs un estándar, los programas que escribamos en Java que las utilicen serán portables a todos estos dispositivos.
Es más, no será necesario recompilar la aplicación para cada tipo de dispositivo. Las aplicaciones Java corren sobre una máquina virtual Java, que deberá estar instalada en todos los dispositivos que soporten Java. Las aplicaciones Java se compilan a un tipo de código intermedio (conocido como bytecodes) que es capaz de interpretar la máquina virtual. De esta forma, nuestra aplicación una vez compilada podrá ejecutarse en cualquier dispositivo que tenga una máquina virtual Java, ya que esta máquina virtual será capaz de interpretar el código compilado de la aplicación sin necesidad de compilarla otra vez. Incluso si aparece un nuevo modelo de dispositivo con soporte para Java después de que nosotros hayamos publicado una aplicación, esta aplicación funcionará en este modelo.
Es por esta razón que las tecnologías Java se han impuesto en el mercado de programación de dispositivos móviles, teniendo prácticamente todos los modelos de móviles que aparecen en la actualidad soporte para Java.
Centrándonos en los teléfonos móviles celulares, vamos a ver las distintas generaciones de estos dispositivos según la red de comunicaciones utilizada.
Se denominan celulares porque la zona de cobertura se divide en zonas de menor tamaño llamadas células. Cada célula tendrá un transmisor que se comunicará con los dispositivos dentro del área de dicha célula mediante señales de radio, operando en una determinada banda de frecuencias. Dentro de esta banda de frecuencias, tendremos un determinado número de canales a través de los cuales se podrán comunicar los móviles de dicha zona.
Este número de canales estará limitado por la banda de frecuencias utilizada, lo que limitará el número de usuarios que puedan estar conectados simultáneamente a la red. Al dividir la cobertura en células permitimos que en distintas células se reutilicen las mismas frecuencias, por lo que este número limitará sólo los usuarios conectados dentro de una misma célula, que es un área pequeña donde habrá menos usuarios, y no de toda la zona global de cobertura.
Primera generación (1G): Red analógica
Los primeros teléfonos móviles que aparecieron utilizaban una red analógica para comunicarse. La información analógica se transfiere por ondas de radio sin ninguna codificación, por frecuencia modulada (FM). Este tipo de redes permiten únicamente comunicaciones de voz. Un ejemplo de red analógica es la red TACS, que opera en la banda de frecuencias entorno a los 900MHz. Al ser analógica hace un uso poco eficiente del espectro, por lo que tendremos menos canales disponibles y por lo tanto será más fácil que la red se sature.
Esta es la red analógica que se utiliza en España para telefonía móvil, basada en la Estadounidense AMPS (Advanced Mobile Phone System). En EEUU además de esta podemos encontrar bastantes más tipos de redes analógicas.
Un gran inconveniente de estas redes analógicas es que existen numerosos tipos de redes, y cada país adoptó una distinta. Esto dificulta la itinerancia (o roaming), ya que no posibilita que utilicemos nuestro dispositivo en otros países con redes diferentes.
Segunda generación (2G): Red digital
La segunda generación de móviles consiste en aquellos que utilizan una red digital para comunicarse. En Europa se adoptó como estándar la red GSM (Global System for Mobile communications). Se trata de una red inicialmente diseñada para voz, pero que también puede transferir datos, aunque es más apropiada para voz. Digitaliza tanto la voz como los datos para su transmisión. Esta red es la que ha producido un acercamiento entre la telefonía móvil y la informática. En Japón se utiliza una red diferente con características similares a GSM, llamada PDC.
La red GSM se implanta como estándar en Europa y desplaza rápidamente a los analógicos. En una primera fase opera en los 900MHz. Una vez saturada la banda de los 900MHz empieza a funcionar en 1800MHz. Los móviles capaces de funcionar en ambas bandas (dualband) tendrán una mayor cobertura, ya que si una banda esta saturada podrán utilizar la otra. En EEUU se utiliza la banda 1900MHz. Hay móviles tribanda que nos permitirán conectarnos en cualquiera de estas 3 bandas, por lo que con ellos tendremos cobertura en EEUU, Europa y Asia.
Una característica de los dispositivos GSM es que los datos relevantes del usuario se almacenan en una tarjeta de plástico extraíble (SIM, Suscriber Identification Module), lo cual independiza la identificación del usuario (número de teléfono y otros datos) del terminal móvil, permitiendo llevar esta tarjeta de un terminal a otro sin tener que cambiar el número.
Opera por conmutación de circuitos (CSD, Circuit Switched Data), es decir, se establece un circuito permanente de comunicación. Con esta tecnología se consigue una velocidad de 9,6kbps, siendo el tiempo de establecimiento de conexión de unos 10 segundos. Los inconvenientes de esta tecnología son:
Más adelante se desarrolla la tecnología HSCSD (High Speed Circuit Switched Data), que consigue una velocidad de 56Kbps sobre la misma red GSM. Para conseguir esta alta velocidad, esta tecnología utiliza varios canales de comunicación simultáneamente, cada uno de los cuales funciona a una velocidad de 9'6Kbps físicos de forma similar a como se hacía con CSD (se puede conseguir aumentar a 14'4kbps utilizando métodos de compresión por software). Al transmitir por 4 canales se consigue esta mayor velocidad, pero tenemos el gran inconveniente de tener 4 circuitos establecidos de forma permanente, por lo que el coste de la conexión se multiplicará por 4, tarificándose por tiempo de conexión igual que ocurría en el caso anterior. Otro inconveniente es que sigue sin ser compatible con IP.
Paso intermedio (2,5G): GPRS
Hemos visto que con las tecnologías anteriores de portadoras de datos (CSD y HSCSD) tenemos los problemas de la baja velocidad, tarificación por tiempo y el no ser una red IP. Surge aquí la necesidad de implantar un método de transmisión por paquetes que no requiera ocupar un canal de forma permanente, sino que envíe los datos fraccionados en paquetes IP independientes. De esta forma surge GPRS, que se considera como un paso intermedio entre la segunda (2G) y tercera (3G) generación.
GPRS (General Packet Radio Service) es una evolución de las redes GSM y funciona sobre estas mismas redes, por lo que no será necesario realizar una gran inversión en infraestructuras, simplemente se deberá actualizar la red GSM para que soporte la transmisión de paquetes.
Esta tecnología realiza una transmisión inalámbrica de datos basada en paquetes. Puede alcanzar una velocidad de hasta 144kbps teóricamente, aunque en la práctica no suele pasar de los 40Kbps por limitaciones de los dispositivos. La información se fragmenta en paquetes que se envían mediante el protocolo IP por distintos canales de forma independiente y se reconstruye en destino. Al seguir el protocolo IP, podremos acceder a todos los recursos de la red Internet.
Un canal no tendrá que estar dedicado a la comunicación exclusivamente de un punto a otro, es decir, no mantiene una conexión abierta de forma permanente, conecta solo para transmitir datos (paquetes). Por esta razón se aprovecharán mejor los canales de comunicación, ya que sólo se ocupan cuando es necesario y se optimiza así el uso de la red. El tiempo de establecimiento de conexión es de aproximadamente 1 segundo. De esta forma se paga por información transmitida, y no por tiempo de conexión. Esto nos permite que podamos estar siempre conectados a Internet, ya que mientras no se transfieran paquetes no estaremos ocupando los canales de comunicación y por lo tanto no se nos estará cobrando.
Los dispositivos cuentan con varios canales para transmitir (a 10Kbps cada uno), tanto para enviar como para recibir. Por ejemplo podemos tener dispositivos (2+1), con 2 canales para recibir y 1 para enviar, por lo que recibirán datos a 20Kbps y enviarán a 10Kbps. Se pueden tener hasta un máximo de 8 canales. Esto nos permite tener simultaneidad de voz y datos.
En Japón, de forma similar, se tiene la red PDC-P que es una extensión de la anterior red PDC para trabajar mediante transmisión por paquetes a una velocidad de 28.8Kbps.
Tercera generación (3G): Banda ancha
La tercera generación de telefonía móvil viene con la red UMTS (Universal Mobile Telephony System). Con esta nueva tecnología de radio se pretende buscar un estándar mundial para las redes de telefonía móvil, de forma que podemos movernos a cualquier parte del mundo sin que nuestro móvil deje de funcionar.
Además con ella se pretende dar acceso a servicios multimedia, como videoconferencia, ver la TV a través del móvil, oír música, etc. Para ello esta red proporciona un ancho de banda mucho mayor que las redes de segunda generación, teniendo velocidades de transferencia entre 384kbps y 2Mbps. Al igual que ocurría con GPRS la información se enviará por paquetes, por lo que se cobrará por información transmitida, lo que nos permitirá estar conectados permanentemente.
Esta red tiene el inconveniente de que para implantarla es necesario realizar una fuerte inversión en infraestructuras. Es compatible con GSM y funciona en la frecuencia 2GHz.
En la arquitectura de capas de las redes móviles, denominamos capa portadora (bearer) a aquella que se va a utilizar para transferir los datos a través de la red. Distintas tecnologías que podemos utilizar como portadoras para enviar o recibir datos a través de la red son:
Debemos distinguir claramente las tecnologías portadoras de las tecnologías para desarrollar aplicaciones. Podemos desarrollar aplicaciones para dispositivos móviles utilizando diferentes tecnologías, y para acceder a una aplicación podremos utilizar diferentes portadores.
Las aplicaciones web normalmente se desarrollan pensando en ser vistas en las pantallas de nuestro PCs, con una resolución de unos 800x600 pixels y navegar en ellas mediante el puntero del ratón. Por lo tanto, estas aplicaciones no se podrán mostrar correctamente en las reducidas pantallas de los dispositivos móviles. Además, en gran parte de los dispositivos móviles (como por ejemplo los teléfonos) no tenemos ningún dispositivo de tipo puntero, por lo que deberemos realizar páginas en las que se pueda navegar fácilmente utilizando el reducido teclado de estos dispositivos.
Han surgido diferentes tecnologías diseñadas para ofrecer contenidos aptos para este tipo de dispositivos. Entre ellas destacamos las siguientes:
Figura 3. Arquitectura WAP
Debido a que la red móvil puede no ser una red IP, se introduce un elemento intermediario: el gateway WAP. Este gateway traduce entre el protocolo WSP (perteneciente a WAP) de la red móvil y el protocolo TCP/IP de Internet.
Figura 4. Gateway WAP
Los documentos web se escriben en lenguaje WML (Wireless Markup Language), que forma parte del protocolo WAP. Se trata de un lenguaje de marcado para definir documentos web que puedan ser visualizados en pantallas pequeñas, usando navegadores WML. Como inconvenientes de este lenguaje encontramos la pobreza de los documentos que podemos generar con él, ya que para asegurarse de funcionar en todos los dispositivos debe ser muy restrictivo, y también el ser un lenguaje totalmente distinto a HTML, que obligará a los desarrolladores a tener que aprender otro lenguaje y escribir desde cero una nueva versión de las aplicaciones.
Con estas tecnologías podemos desarrollar aplicaciones web para acceder desde dispositivos móviles. Sin embargo, en este tipo de dispositivos donde muchas veces la conexión es lenta, cara e inestable es conveniente poder trabajar con las aplicaciones de forma local. Además las aplicaciones que instalemos en el dispositivo podrán estar hechas a medida para nuestro modelo de dispositivo concreto y de esta manera adaptarse mejor a las posibilidades que ofrece.
Vamos a ver qué tecnologías podemos utilizar para desarrollar estar aplicaciones. Los dispositivos tendrán instalado un sistema operativo. Existen diferentes sistemas operativos disponibles para este tipo de dispositivos, entre los que destacamos los siguientes:
Podemos programar aplicaciones utilizando la API de estos SO, pero estas aplicaciones sólo funcionarán en dispositivos que cuenten con dicho SO. Si además accedemos directamente al hardware del dispositivo en nuestros programas, entonces sólo podemos confiar en que sea compatible con el modelo concreto para el que lo hayamos desarrollado.
Debido al gran número de dispositivos distintos existentes con diferentes sistemas operativos, programar a bajo nivel (es decir, utilizando directamente la API del SO) no será conveniente ya que será muy complicado portar nuestro programas a otros dispositivos distintos. Por ello adquiere especial interés en el campo de la programación de dispositivos móviles el tener aplicaciones independientes de la plataforma.
Para tener esta independencia de la plataforma deberemos tener instalado en los dispositivos un entorno de ejecución que sea capaz de interpretar estas aplicaciones multiplataforma. Existen diferentes tecnologías que nos permitirán crear este tipo de aplicaciones, como son las siguientes:
Hemos hablado de que estos dispositivos son capaces de conectarse. Vamos a ver las posibles formas de conectar estos dispositivos móviles para obtener datos, aplicaciones o intercambiar cualquier otra información. Una primera forma de conectarlos consiste en establecer una conexión a Internet desde el móvil a través de la red GSM. Sin embargo, esta conexión cuesta dinero, por lo que será interesante tener otros mecanismos de conexión directa de nuestro móvil para poder copiar en él las aplicaciones que estemos desarrollando para hacer pruebas, gestionar nuestros datos, o intercambiar información con otros usuarios.
La plataforma J2ME nos ofrece una serie de APIs con las que desarrollar las aplicaciones en lenguaje Java. Una vez tengamos la aplicación podremos descargarla en cualquier dispositivo con soporte para J2ME y ejecutarla en él.
J2ME soporta una gran variedad de dispositivos, no únicamente MIDs. Actualmente define APIs para dar soporte a los dispositivos conectados en general, tanto aquellos con una gran capacidad como a tipos más limitados de estos dispositivos.
Hemos visto que existen dispositivos de tipos muy distintos, cada uno de ellos con sus propias necesidades, y muchos con grandes limitaciones de capacidad. Si obtenemos el máximo común denominador de todos ellos nos quedamos prácticamente con nada, por lo que es imposible definir una única API en J2ME que nos sirva para todos.
Por ello en J2ME existirán diferentes APIs cada una de ellas diseñada para una familia de dispositivos distinta. Estas APIs se encuentras arquitecturadas en dos capas: configuraciones y perfiles.
Figura 5. Arquitectura de J2ME
Configuraciones
Las configuraciones son las capas de la API de bajo nivel, que residen sobre la máquina virtual y que están altamente vinculadas con ella, ofrecen las características básicas de todo un gran conjunto de dispositivos. En esta API ofrecen lo que sería el máximo denominador común de todos ellos, la API de programación básica en lenguaje Java.
Encontramos distintas configuraciones para adaptarse a la capacidad de los dispositivos. La configuración CDC (Connected Devices Configuration) contiene la API común para todos los dispositivos conectados, soportada por la máquina virtual Java.
Sin embargo, para algunos dispositivos con grandes limitaciones de capacidad esta máquina virtual Java puede resultar demasiado compleja. Hemos de pensar en dispositivos que pueden tener 128 KB de memoria. Es evidente que la máquina virtual de Java (JVM) pensada para ordenadores con varias megas de RAM instaladas no podrá funcionar en estos dispositivos.
Por lo tanto aparece una segunda configuración llamada CLDL (Connected Limited Devices Configuration) pensada para estos dispositivos con grandes limitaciones. En ella se ofrece una API muy reducida, en la que tenemos un menor número de funcionalidades, adaptándose a las posibilidades de estos dispositivos. Esta configuración está soportada por una máquina virtual mucho más reducida, la KVM (Kilobyte Virtual Machine), que necesitará muchos menos recursos por lo que podrá instalarse en dispositivos muy limitados.
Vemos que tenemos distintas configuraciones para adaptarnos a dispositivos con distinta capacidad. La configuración CDC soportada por la JVM (Java Virtual Machine) funcionará sólo con dispositivos con memoria superior a 1 MB, mientras que para los dispositivos con memoria del orden de los KB tenemos la configuración CLDC soportada por la KVM, de ahí viene el nombre de Kilobyte Virtual Machine.
Perfiles
Como ya hemos dicho, las configuraciones nos ofrecen sólo la parte básica de la API para programar en los dispositivos, aquella parte que será común para todos ellos. El problema es que esta parte común será muy reducida, y no nos permitirá acceder a todas las características de cada tipo de dispositivo específico. Por lo tanto, deberemos extender la API de programación para cada familia concreta de dispositivos, de forma que podamos acceder a las características propias de cada familia.
Esta extensión de las configuraciones es lo que se denomina perfiles. Los perfiles son una capa por encima de las configuraciones que extienden la API definida en la configuración subyacente añadiendo las operaciones adecuadas para programar para una determinada familia de dispositivos.
Por ejemplo, tenemos un perfil MIDP (Mobile Information Devices Profile) para programar los dispositivos móviles de información. Este perfil MIDP reside sobre CLDC, ya que estos son dispositivos bastante limitados a la mayoría de las ocasiones.
Paquetes opcionales
Además podemos incluir paquetes adicionales, como una tercera capa por encima de las anteriores, para dar soporte a funciones concretas de determinados modelos de dispositivos. Por ejemplo, los móviles que incorporen cámara podrán utilizar una API multimedia para acceder a ella.
La configuración CDC se utilizará para dispositivos conectados con una memoria de por lo menos 1 MB (se recomiendan al menos 2 MB para un funcionamiento correcto). Se utilizará en dispositivos como PDAs de gama alta, comunicadores, descodificadores de televisión, impresoras de red, routers, etc.
CDC se ha diseñado de forma que se mantenga la máxima compatibilidad posible con J2SE, permitiendo de este modo portar fácilmente las aplicaciones con las que ya contamos en nuestros ordenadores a CDC.
La máquina virtual utilizada, la CVM, cumple con la misma especificación que la JVM, por lo que podremos programar las aplicaciones de la misma forma que lo hacíamos en J2SE. Existe una nueva máquina virtual para soportar CDC, llamada CDC Hotspot, que incluye diversas optimizaciones utilizando la tecnología Hotspot.
La API que ofrece CDC es un subconjunto de la API que ofrecía J2SE, optimizada para este tipo de dispositivos que tienen menos recursos que los PCs en los que utilizamos J2SE. Se mantienen las clases principales de la API, que ofrecerán la misma interfaz que en su versión de J2SE.
CDC viene a sustituir a la antigua API PersonalJava, que se aplicaba al mismo tipo de dispositivos. La API CDC, a diferencia de PersonalJava, está integrada dentro de la arquitectura de J2ME.
Tenemos diferentes perfiles disponibles según el tipo de dispositivo que estemos programando: Foundation Profile (FP), Personal Basis Profile (PBP) y Personal Profile (PP).
Foundation Profile
Este es el perfil básico para la programación con CDC. No incluye ninguna API para la creación de una interfaz gráfica de usuario, por lo que se utilizará para dispositivos sin interfaz, como por ejemplo impresoras de red o routers.
Los paquetes que se incluyen en este perfil son:
java.io java.lang java.lang.ref java.lang.reflect java.net java.security java.security.acl java.security.cert java.security.interfaces java.security.spec java.text java.util java.util.jar java.util.zip
Vemos que incluye todos los paquetes del núcleo de Java, para la programación
básica en el lenguaje (java.lang
), para manejar la entrada/salida
(java.io
), para establecer conexiones de red (java.net
),
para seguridad (java.security
), manejo de texto (java.text
)
y clases útiles (java.util
). Estos paquetes se incluyen
en su versión integra, igual que en J2SE. Además incluye un paquete
adicional que no pertenece a J2SE:
javax.microedition.io
Este paquete pertenece está presente para mantener la compatibilidad con CLDC, ya que pertenece a esta configuración, como veremos más adelante.
Personal Basis Profile
Este perfil incluye una API para la programación de la interfaz gráfica de las aplicaciones. Lo utilizaremos para dispositivos en los que necesitemos aplicaciones con interfaz gráfica. Este es el caso de los descodificadores de televisión por ejemplo.
Además de los paquetes incluidos en FP, añade los siguientes:
java.awt java.awt.color java.awt.event java.awt.image java.beans java.rmi java.rmi.registry
Estos paquetes incluyen un subconjunto de las clases que contenían en
J2SE. Tenemos el paquete AWT (java.awt
) para la creación
de la interfaz gráfica de las aplicaciones. Este paquete sólo
incluye soporte para componentes ligeros (aquellos que definen mediante código
Java la forma de dibujarse), y no incluye ningún componente de alto nivel
(como botones, campos de texto, etc). Tendremos que crear nosotros nuestros
propios componentes, definiendo la forma en la que se dibujará cada uno.
También incluye un soporte limitado para beans (java.beans
)
y objetos distribuidos RMI (java.rmi
).
Además podemos encontrar un nuevo tipo de componente no existente en J2SE, que son los Xlets.
javax.microedition.xlet javax.microedition.xlet.ixc
Estos xlets son similares a los applets, son componentes que se ejecutan dentro de un contenedor que controla su ciclo de vida. En el caso de los applets este contenedor era normalmente el navegador donde se cargaba el applet. Los xlets se ejecutan dentro del xlet manager. Los xlets pueden comunicarse entre ellos mediante RMI. De hecho, la parte de RMI incluida en PBP es únicamente la dedicada a la comunicación entre xlets.
Los xlets se diferencian también de los applets en que tienen un ciclo de vida definido más claramente, y que no están tan vinculados a la interfaz (AWT) como los applets. Por lo tanto podremos utilizar tanto xlets con interfaz gráfica, como sin ella.
Estos xlets se suelen utilizar en aplicaciones de televisión interactiva, instaladas en los descodificadores (set top boxes).
Personal Profile
Este perfil incluye soporte para applets e incluye la API de AWT íntegra. De esta forma podremos utilizar los componentes pesados de alto nivel definidos en AWT (botones, menús, campos de texto, etc). Estos componentes pesado utilizan la interfaz gráfica nativa del dispositivo donde se ejecutan. De esta forma, utilizaremos este perfil cuando trabajemos con dispositivos que disponen de su propia interfaz gráfica de usuario (GUI) nativa.
Incluye los siguientes paquetes:
java.applet java.awt java.awt.datatransfer
En este caso ya se incluye íntegra la API de AWT (java.awt
)
y el soporte para applets (java.applet
). Este paquete es el más
parecido al desaparecido PersonalJava, por lo que será el más
adecuado para migrar las aplicaciones PersonalJava a J2ME.
Paquetes opcionales
En CDC se incluyen como paquetes opcionales subconjuntos de otras APIs presentes en J2SE: la API JDBC para conexión a bases de datos, y la API de RMI para utilizar esta tecnología de objetos distribuidos.
Además también podremos utilizar como paquete opcional la API Java TV, adecuada para aplicaciones de televisión interactiva (iTV), que pueden ser instaladas en descodificadores de televisión digital. Incluye la extensión JMF (Java Media Framework) para controlar los flujos de video.
Podremos utilizar estas APIs para programar todos aquellos dispositivos que las soporten.
La configuración CLDC se utilizará para dispositivos conectados con poca memoria, pudiendo funcionar correctamente con sólo 128 KB de memoria. Normalmente la utilizaremos para los dispositivos con menos de 1 ó 2 MB de memoria, en los que CDC no funcionará correctamente. Esta configuración se utilizará para teléfonos móviles (celulares) y PDAs de gama baja.
Esta configuración se ejecutará sobre la KVM, una máquina
virtual con una serie de limitaciones para ser capaz de funcionar en estas configuraciones
de baja memoria. Por ejemplo, no tiene soporte para tipos de datos float
y double
, ya que estos dispositivos normalmente no tienen unidad
de punto flotante.
La API que ofrece esta configuración consiste en un subconjunto de los paquetes principales del núcleo de Java, adaptados para funcionar en este tipo de dispositivos. Los paquetes que ofrece son los siguientes:
java.lang java.io java.util
Tenemos las clases básicas del lenguaje (java.lang
), algunas
clases útiles (java.util
), y soporte para flujos de entrada/salida
(java.io
). Sin embargo vemos que no se ha incluido la API de red
(java.net
). Esto es debido a que esta API es demasiado compleja
para estos dispositivos, por lo que se sustituirá por una API de red
propia más reducida, adaptada a sus necesidades de conectividad:
javax.microedition.io
En la actualidad encontramos únicamente un perfil que se ejecuta sobre CLDC. Este perfil es MIDP (Mobile Information Devices Profile), y corresponde a la familia de dispositivos móviles de información (teléfonos móviles y PDAs).
Los dispositivos iMode utilizan una API de Java propietaria de NTT DoCoMo, llamada DoJa. Esta API se construye sobre CLDC, pero no es un perfil pertenecienta a J2ME. Simplemente es una extensión de CLDC para teléfonos iMode.
Mobile Information Devices Profile
Utilizaremos este perfil para programar aplicaciones para MIDs. En los siguientes capítulos nos centraremos en la programación de aplicaciones para móviles utilizando este perfil, que es el que más protagonismo ha cobrado tras la aparición de los últimos modelos de móviles que incluyen soporte para esta API.
La API que nos ofrece MIDP consiste, además de los paquetes ofrecidos en CLDL, en los siguientes paquetes:
javax.microedition.lcdui javax.microedition.lcdui.game javax.microedition.media javax.microedition.media.control javax.microedition.midlet javax.microedition.pki javax.microedition.rms
Las aplicaciones que desarrollaremos para estos dispositivos se llaman MIDlets.
El móvil actuará como contenedor de este tipo de aplicaciones,
controlando su ciclo de vida. Tenemos un paquete con las clases correspondientes
a este tipo de componentes (javax.microedition.midlet
). Además
tendremos otro paquete con los elementos necesarios para crear la interfaz gráfica
en la pantalla de los móviles (javax.microedition.lcdui
),
que además nos ofrece facilidades para la programación de juegos.
Tenemos también un paquete con clases para reproducción de músicas
y tonos (javax.microedition.media
), para creación de certificados
por clave pública para controlar la seguridad de las aplicaciones (javax.microedition.pki
),
y para almacenamiento persistente de información (javax.microedition.rms
).
Paquetes opcionales
Como paquetes opcionales tenemos:
JWTI (Java Technology for Wireless Industry) es una especificación que trata de definir una plataforma estándar para el desarrollo de aplicaciones para móviles. En ella se especifican las tecnologías que deben ser soportadas por los dispositivos móviles:
De esta forma se pretende evitar la fragmentación de APIs, proporcionando un estándar que sea aceptado por la gran mayoría de los dispositivos existentes. El objetivo principal de esta especificación es aumentar la compatibilidad e interoperabilidad, de forma que cualquier aplicación que desarrollemos que cumpla con JTWI pueda ser utilizada en cualquier dispositivo que soporte esta especificación.
En ella se especifica el conjunto de APIs que deben incorporar los teléfonos JTWI, de forma que podremos confiar en que cuando utilicemos estas APIs, la aplicación va a ser soportada por todos ellos. Además con esta especificación se pretende evitar el uso de APIs opcionales no estándar que producen aplicaciones incompatibles con la mayoría de dispositivos.
Hay aspectos en los que las especificaciones de las diferentes APIs (MIDP, CLDC, etc) no son claras del todo. Con JTWI también se pretende aclarar todos estos puntos, para crear un estándar que se cumpla al 100% por todos los fabricantes, consiguiendo de esta forma una interoperabilidad total.
También se incluyen recomendaciones sobre las características mínimas que deberían tener todos los dispositivos JTWI.
En este tema vamos a ver cómo construir aplicaciones J2ME a partir del código fuente de forma que estén listas para ser instaladas directamente en cualquier dispositivo con soporte para esta tecnología.
Vamos a estudiar la creación de aplicaciones para MIDs, que serán normalmente teléfonos móviles o algunos PDAs. Por lo tanto nos centraremos en el perfil MIDP.
Para comenzar vamos a ver de qué se componen las aplicaciones MIDP que podemos instalar en los móviles (ficheros JAD y JAR), y cómo se realiza este proceso de instalación. A continuación veremos como crear paso a paso estos ficheros de los que se componen estas aplicaciones, y como probarlas en emuladores para no tener que transferirlas a un dispositivo real cada vez que queramos hacer una prueba. En el siguiente punto se verá cómo podremos facilitar esta tarea utilizando los kits de desarrollo que hay disponibles, y algunos entornos integrados (IDEs) para hacer más cómodo todavía el desarrollo de aplicaciones para móviles.
Para distribuir e instalar las aplicaciones J2ME en los dispositivos utilizaremos ficheros de tipos JAR y JAD. Las aplicaciones estarán compuestas por un fichero JAR y un fichero JAD.
Los MIDlets son las aplicaciones Java desarrolladas con MIDP que se pueden ejecutar en los MIDs. Los ficheros JAD y JAR contienen un conjunto de MIDlets, lo que se conoce como suite. Una suite es un conjunto de uno o más MIDlets empaquetados en un mismo fichero. De esta forma cuando dicha suite sea instalada en el móvil se instalarán todas las aplicaciones (MIDlets) que contenga.
El fichero JAR será el que contendrá las aplicaciones de la suite. En él tendremos tanto el código compilado como los recursos que necesite para ejecutarse (imágenes, sonidos, etc). Estos ficheros JAR son un estándar de la plataforma Java, disponibles en todas las ediciones de esta plataforma, que nos permitirán empaquetar una aplicación Java en un solo fichero. Al ser un estándar de la plataforma Java será portable a cualquier sistema donde contemos con esta plataforma.
Por otro lado, el fichero JAD (Java Application Descriptor) contendrá una descripción de la suite . En él podremos encontrar datos sobre su nombre, el tamaño del fichero, la versión, su autor, MIDlets que contiene, etc. Además también tendrá una referencia al fichero JAR donde se encuentra la aplicación.
De esta forma cuando queramos instalar una aplicación deberemos localizar su fichero JAD. Una vez localizado el fichero JAD, deberemos indicar que deseamos instalar la aplicación, de forma que se descargue e instale en nuestro dispositivo el fichero JAR correspondiente. Además el fichero JAD localizado nos permitirá saber si una aplicación ya está instalada en nuestro dispositivo, y de ser así comprobar si hay disponible una versión superior y dar la opción al usuario de actualizarla. De esta forma no será necesario descargar el fichero JAR entero, cuyo tamaño será mayor debido a que contiene toda la aplicación, para conocer los datos de la aplicación y si la tenemos ya instalada en nuestro móvil.
Un posible escenario de uso es el siguiente. Podemos navegar con nuestro móvil mediante WAP por una página WML. En esa página puede haber publicadas una serie de aplicaciones Java para descargar. En la página tendremos los enlaces a los ficheros JAD de cada aplicación disponible. Seleccionando con nuestro móvil uno de estos enlaces, accederá al fichero JAD y nos dará una descripción de la aplicación que estamos solicitando, preguntándonos si deseamos instalarla. Si decimos que si, descargará el fichero JAR asociado en nuestro móvil e instalará la aplicación de forma que podemos usarla. Si accedemos posteriormente a la página WML y pinchamos sobre el enlace al JAD de la aplicación, lo comparará con las aplicaciones que tenemos instaladas y nos dirá que la aplicación ya está instalada en nuestro móvil. Además, al incluir la información sobre la versión podrá saber si la versión que hay actualmente en la página es más nueva que la que tenemos instalada, y en ese caso nos dará la opción de actualizarla.
Los dispositivos móviles contienen lo que se denomina AMS (Application Management Software), o software gestor de aplicaciones en castellano. Este software será el encargado de realizar el proceso de instalación de aplicaciones que hemos visto en el punto anterior. Será el que controle el ciclo de vida de las suites:
Los ficheros JAD son ficheros ASCII que contienen una descripción de la suite. En él se le dará valor a una serie de propiedades (parámetros de configuración) de la suite. Tenemos una serie de propiedades que deberemos especificar de forma obligatoria en el fichero:
MIDlet-Name |
Nombre de la suite. |
MIDlet-Version |
Versión de la suite. La versión se compone de 3 número
separados por puntos: <mayor>.<menor>.<micro> ,
como por ejemplo 1.0.0 |
MIDlet-Vendor |
Autor (Proveedor) de la suite. |
MIDlet-Jar-URL |
Dirección (URL) de donde obtener el fichero JAR con la suite. |
MIDlet-Jar-Size |
Tamaño del fichero JAR en bytes. |
Además podemos incluir una serie de propiedades adicionales de forma optativa:
MIDlet-Icon |
Icono para la suite. Si especificamos un icono éste se mostrará junto al nombre de la suite, por lo que nos servirá para identificarla. Este icono será un fichero con formato PNG que deberá estar contenido en el fichero JAR. |
MIDlet-Description |
Descripción de la suite. |
MIDlet-Info-URL |
Dirección URL donde podemos encontrar información sobre la suite. |
MIDlet-Data-Size |
Número mínimo de bytes que necesita la suite
para almacenar datos de forma persistente. Por defecto este número
mínimo se considera 0 . |
MIDlet-Delete-Confirm |
Mensaje de texto con el que se le preguntará al usuario si desea desinstalar la aplicación. |
MIDlet-Delete-Notify |
URL a la que se enviará una notificación de que el usuario ha desinstalado nuestra aplicación de su móvil. |
MIDlet-Install-Notify |
URL a la que se enviará una notificación de que el usuario ha instalado nuestra aplicación en su móvil. |
Estas son propiedades que reconocerá el AMS y de las que obtendrá la información necesaria sobre la suite. Sin embargo, como desarrolladores puede interesarnos incluir una serie de parámetros de configuración propios de nuestra aplicación. Podremos hacer eso simplemente añadiendo nuevas propiedades con nombres distintos a los anteriores al fichero JAR. En el capítulo 4 veremos como acceder a estas propiedades desde nuestras aplicaciones.
Un ejemplo de fichero JAD para una suite de MIDlets es el siguiente:
MIDlet-Name: SuiteEjemplos MIDlet-Version: 1.0.0 MIDlet-Vendor: Universidad de Alicante MIDlet-Description: Aplicaciones de ejemplo para moviles. MIDlet-Jar-Size: 16342 MIDlet-Jar-URL: ejemplos.jar
En el fichero JAR empaquetaremos los ficheros .class
resultado
de compilar las clases que componen nuestra aplicación, así como
todos los recursos que necesite la aplicación, como pueden ser imágenes,
sonidos, músicas, videos, ficheros de datos, etc.
Para empaquetar estos ficheros en un fichero JAR, podemos utilizar la herramienta
jar
incluida en J2SE. Más adelante veremos como hacer esto.
Además de estos contenidos, dentro del JAR tendremos un fichero MANIFEST.MF
que contendrá una serie de parámetros de configuración
de la aplicación. Se repiten algunos de los parámetros especificados
en el fichero JAD, y se introducen algunos nuevos. Los parámetros requeridos
son:
MIDlet-Name |
Nombre de la suite. |
MIDlet-Version |
Versión de la suite. |
MIDlet-Vendor |
Autor (Proveedor) de la suite. |
MicroEdition-Profile |
Perfil requerido para ejecutar la suite. Podrá tomar el
valor MIDP-1.0 ó MIDP-2.0 , según
las versión de MIDP que utilicen las aplicaciones incluidas. |
MicroEdition-Configuration |
Configuración requerida para ejecutar la suite. Tomará
el valor CLDC-1.0 para las aplicaciones que utilicen esta configuración. |
Deberemos incluir también información referente a cada MIDlet contenido en la suite. Esto lo haremos con la siguiente propiedad:
MIDlet-<n> |
Nombre, icono y clase principal del MIDlet número n |
Los MIDlets se empezarán a numerar a partir del número 1, y deberemos incluir una línea de este tipo para cada MIDlet disponible en la suite. Daremos a cada MIDlet un nombre para que lo identifique el usuario, un icono de forma optativa, y el nombre de la clase principal que contiene dicho MIDlet.
Si especificamos un icono, deberá ser un fichero con formato PNG contenido dentro del JAR de la suite. Por ejemplo, para una suite con 3 MIDlets podemos tener la siguiente información:
MIDlet-Name: SuiteEjemplos MIDlet-Version: 1.0.0 MIDlet-Vendor: Universidad de Alicante MIDlet-Description: Aplicaciones de ejemplo para moviles. MicroEdition-Configuration: CLDC-1.0 MicroEdition-Profile: MIDP-1.0 MIDlet-1: Snake, /icons/snake.png, es.ua.j2ee.serpiente.SerpMIDlet MIDlet-2: TeleSketch, /icons/ts.png, es.ua.j2ee.ts.TeleSketchMIDlet MIDlet-3: Panj, /icons/panj.png, es.ua.j2ee.panj.PanjMIDlet
Además tenemos las mismas propiedades optativas que en el fichero JAD:
MIDlet-Icon |
Icono para la suite. |
MIDlet-Description |
Descripción de la suite. |
MIDlet-Info-URL |
Dirección URL con información |
MIDlet-Data-Size |
Número mínimo de bytes para datos persistentes. |
En este fichero, a diferencia del fichero JAD, no podremos introducir propiedades propias del usuario, ya que desde dentro de la aplicación no podremos acceder a los propiedades contenidas en este fichero.
Vamos a ver los pasos necesarios para construir una aplicación con J2ME a partir del código fuente, obteniendo finalmente los ficheros JAD y JAR con los que podremos instalar la aplicación en dispositivos móviles.
El primer paso será compilar las clases, obteniendo así el código intermedio que podrá ser ejecutado en una máquina virtual de Java. El problema es que este código intermedio es demasiado complejo para la KVM, por lo que deberemos realizar una preverificación del código, que simplifique el código intermedio de las clases y compruebe que no utiliza ninguna característica no soportada por la KVM. Una vez preverificado, deberemos empaquetar todos los ficheros de nuestra aplicación en un fichero JAR, y crear el fichero JAD correspondiente. En este momento podremos probar la aplicación en un emulador o en un dispositivo real. Los emuladores nos permitirán probar las aplicaciones directamente en nuestro ordenador sin tener que transferirlas a un dispositivo móvil real.
Figura 1. Proceso de construcción de aplicaciones
Necesitaremos tener instalado J2SE, ya que utilizaremos las mismas herramientas para compilar y empaquetar las clases. Además necesitaremos herramientas adicionales, ya que la máquina virtual reducida de los dispositivos CLDC necesita un código intermedio simplificado.
Lo primero que deberemos hacer es compilar las clases de nuestra aplicación.
Para ello utilizaremos el compilador incluido en J2SE, javac
, por
lo que deberemos tener instalada esta edición de Java.
Al compilar, el compilador buscará las clases que utilizamos dentro de nuestros programas para comprobar que estamos utilizándolas correctamente, y si utilizamos una clase que no existe, o bien llamamos a un método o accedemos a una propiedad que no pertenece a dicha clase nos dará un error de compilación. Java busca las clases en el siguiente orden:
1. Clases de núcleo de Java (bootstrap)
2. Extensiones instaladas
3. Classpath
Si estamos compilando con el compilador de J2SE, por defecto considerará
que las clases del núcleo de Java son las clases de la API de J2SE. Debemos
evitar que esto ocurra, ya que estas clases no van a estar disponibles en los
dispositivos MIDP que cuentan con una API reducida. Deberemos hacer que tome
como clases del núcleo las clases de la API de MIDP, esto lo haremos
mediante el parámetro bootclasspath
del compilador:
javac -bootclasspath ${ruta_midp}/midpapi.zip <ficheros .java>
Con esto estaremos compilando nuestras clases utilizando como API del núcleo de Java la API de MIDP. De esta forma, si dentro de nuestro programa utilizásemos una clase que no pertenece a MIDP, aunque pertenezca a J2SE nos dará un error de compilación.
Este es un paso opcional, pero recomendable. El código intermedio de Java incluye información sobre los nombres de los constructores, de los métodos y de los atributos de las clases e interfaces para poder acceder a esta información utilizando la API de reflection en tiempo de ejecución.
El contar con esta información nos permite descompilar fácilmente las aplicaciones, obteniendo a partir del código compilado unos fuentes muy parecidos a los originales. Lo único que se pierde son los comentarios y los nombres de las variables locales y de los parámetros de los métodos.
Esto será un problema si no queremos que se tenga acceso al código fuente de nuestra aplicación. Además incluir esta información en los ficheros compilados de nuestra aplicación harán que crezca el tamaño de estos ficheros ocupando más espacio, un espacio muy preciado en el caso de los dispositivos móviles con baja capacidad. Hemos de recordar que el tamaño de los ficheros JAR que soportan está limitado en muchos casos a 64kb o menos.
El proceso de ofuscación del código consiste en simplificar esta información, asignándoles nombres tan cortos como se pueda a las clases e interfaces y a sus constructores, métodos y atributos. De esta forma al descompilar obtendremos un código nada legible con nombres sin ninguna significancia.
Además conseguiremos que los ficheros ocupen menos espacio en disco, lo cuál será muy conveniente para las aplicaciones para dispositivos móviles con baja capacidad y reducida velocidad de descarga.
La ofuscación de código deberemos hacerla antes de la preverificación, dejando la preverificación para el final, y asegurándonos así de que el código final de nuestra aplicación funcionará correctamente en la KVM. Podemos utilizar para ello diferentes ofuscadores, como ProGuard, RetroGuard o JODE. Deberemos obtener alguno de estos ofuscadores por separado, ya que no se incluyen en J2SE ni en los kits de desarrollo para MIDP que veremos más adelante.
Con la compilación que acabamos de realizar hemos generado código intermedio que serán capaces de interpretar las máquinas virtuales Java. Sin embargo, máquina virtual de los dispositivos CLDC, la KVM, es un caso especial ya que las limitaciones de estos dispositivos hacen que tenga que ser bastante más reducida que otras máquinas virtuales para poder funcionar correctamente.
La máquina virtual de Java hace una verificación de las clases que ejecuta en ella. Este proceso de verificación es bastante complejo para la KVM, por lo que deberemos reorganizar el código intermedio generado para facilitar esta tarea de verificación. En esto consiste la fase de preverificación que deberemos realizar antes de llevar la aplicación a un dispositivo real.
Además la KVM tiene una serie de limitaciones en cuanto al código
que puede ejecutar en ella, como por ejemplo la falta de soporte para tipos
de datos float
y double
. Con la compilación
hemos comprobado que no estamos utilizando clases que no sean de la API de MIDP,
pero se puede estar permitiendo utilizar características del lenguaje
no soportada por la KVM. Es el proceso de preverificación el que deberá
detectar el error en este caso.
Para realizar la preverificación necesitaremos la herramienta preverify
.
Esta herramienta no se incluye en J2SE, por lo que deberemos obtenerla por separado.
Podemos encontrarla en diferentes kits de desarrollo o en implementaciones de
referencia de MIDP, como veremos más adelante. Deberemos especificar
como classpath
la API que estemos utilizando para nuestra aplicación,
como por ejemplo MIDP:
preverify -classpath ${ruta_midp}/midpapi.zip -d <directorio destino>
<ficheros .class>
Preverificará los ficheros .class
especificados y guardará
el resultado de la preverificación en el directorio destino que indiquemos.
Las clases generadas en este directorio destino serán las que tendremos
que empaquetar en nuestra suite.
Una vez tenemos el código compilado preverificado, deberemos empaquetarlo
todo en un fichero JAR para crear la suite con nuestra aplicación.
En este fichero JAR deberemos empaquetar todos los ficheros .class
generados, así como todos los recursos que nuestra aplicación
necesite para funcionar, como pueden ser iconos, imágenes, sonidos, ficheros
de datos, videos, etc.
Para empaquetar un conjunto de ficheros en un fichero JAR utilizaremos la herramienta
jar
incluida en J2SE. Además de las clases y los recursos,
deberemos añadir al fichero MANIFEST.MF
del JAR los parámetros
de configuración que hemos visto en el punto anterior. Para ello crearemos
un fichero de texto ASCII con esta información, y utilizaremos dicho
fichero a la hora de crear el JAR. Utilizaremos la herramienta jar
de la siguiente forma:
jar cmf <fichero manifest> <fichero jar> <ficheros a incluir>
Una vez hecho esto tendremos construido el fichero JAR con nuestra aplicación. Ahora deberemos crear el fichero JAD. Para ello podemos utilizar cualquier editor ASCII e incluir las propiedades necesarias. Como ya hemos generado el fichero JAR podremos indicar su tamaño dentro del JAD.
Una vez tengamos los ficheros JAR y JAD ya podremos probar la aplicación transfiriéndola a un dispositivo que soporte MIDP e instalándola en él. Sin embargo, hacer esto para cada prueba que queramos hacer es una tarea tediosa. Tendremos que limitarnos a hacer pruebas de tarde en tarde porque si no se perdería demasiado tiempo. Además no podemos contar con que todos los desarrolladores tengan un móvil con el que probar las aplicaciones.
Si queremos ir probando con frecuencia los avances que hacemos en nuestro programa lo más inmediato será utilizar un emulador. Un emulador es una aplicación que se ejecuta en nuestro ordenador e imita (emula) el comportamiento del móvil. Entonces podremos ejecutar nuestras aplicaciones dentro de un emulador y de esta forma para la aplicación será prácticamente como si se estuviese ejecutando en un móvil con soporte para MIDP. Así podremos probar las aplicaciones en nuestro mismo ordenador sin necesitar tener que llevarla a otro dispositivo.
Además podremos encontrar emuladores que imitan distintos modelos de móviles, tanto existentes como ficticios. Esta es una ventaja más de tener emuladores, ya que si probamos en dispositivos reales necesitaríamos o bien disponer de varios de ellos, o probar la aplicación sólo con el que tenemos y arriesgarnos a que no vaya en otros modelos. Será interesante probar emuladores de teléfonos móviles con distintas características (distinto tamaño de pantalla, colores, memoria) para comprobar que nuestra aplicación funciona correctamente en todos ellos.
Podemos encontrar emuladores proporcionados por distintos fabricantes, como Nokia, Siemens o Sun entre otros. De esta forma tendremos emuladores que imitan distintos modelos de teléfonos Nokia o Siemens existentes. Sun proporciona una serie de emuladores genéricos que podremos personalizar dentro dentro de su kit de desarrollo que veremos en el próximo apartado.
Será importante también, una vez hayamos probado la aplicación en emuladores, probarla en un dispositivo real, ya que puede haber cosas que funcionen bien en emuladores pero no lo hagan cuando lo llevamos a un dispositivo móvil de verdad. Los emuladores pretenden imitar en la medida de lo posible el comportamiento de los dispositivos reales, pero siempre hay diferencias, por lo que será importante probar las aplicaciones en móviles de verdad antes de distribuir la aplicación.
La forma más directa de probar la aplicación en dispositivos móviles es conectarlos al PC mediante alguna de las tecnologías disponibles (bluetooth, IrDA, cable serie o USB) y copiar la aplicación del PC al dispositivo. Una vez copiada, podremos instalarla desde el mismo dispositivo, y una vez hecho esto ya podremos ejecutarla.
Por ejemplo, los emuladores funcionan bien con código no preverificado, o incluso muchos de ellos funcionan con los ficheros una vez compilados sin necesidad de empaquetarlos en un JAR.
Entendemos por despliegue de la aplicación la puesta en marcha de la misma, permitiendo que el público acceda a ella y la utilice. Para desplegar una aplicación MIDP deberemos ponerla en algún lugar accesible, al que podamos conectarnos desde los móviles y descargarla.
Podremos utilizar cualquier servidor web para ofrecer la aplicación en Internet, como puede ser por ejemplo el Tomcat. Deberemos configurar el servidor de forma que reconozca correctamente los tipos de los ficheros JAR y JAD. Para ello asociaremos estas extensiones a los tipos MIME:
.jad |
text/vnd.sun.j2me.app-descriptor |
.jar |
application/java-archive |
Además en el fichero JAD, deberemos especificar como URL la dirección de Internet donde finalmente hemos ubicado el fichero JAR.
Para simplificar la tarea de desarrollar aplicaciones MIDP, tenemos disponibles distintos kits de desarrollo proporcionados por distintos fabricantes, como Sun o Nokia. Antes de instalar estos kits de desarrollo deberemos tener instalado J2SE. Estos kits de desarrollo contienen todos los elementos necesarios para, junto a J2SE, crear aplicaciones MIDP:
Vamos a centrarnos en estudiar cómo trabajar con el kit de desarrollo de Sun, ya que es el más utilizado por ser genérico y el que mejor se integra con otros entornos y herramientas. Este kit recibe el nombre de Wireless Toolkit (WTK). Existen diferentes versiones de WTK, cada una de ellas adecuada para un determinado tipo de aplicaciones:
Hemos visto en el punto anterior los pasos que deberemos seguir para probar nuestras aplicaciones MIDP: compilar, preverificar, empaquetar, crear el archivo JAD y ejecutar en un emulador.
Normalmente, mientras escribimos el programa querremos probarlo numerosas veces para comprobar que lo que llevamos hecho funciona correctamente. Si cada vez que queremos probar el programa tuviésemos que realizar todos los pasos vistos anteriormente de forma manual programar aplicaciones MIDP sería una tarea tediosa. Además requeriría aprender a manejar todas las herramientas necesarias para realizar cada paso en la línea de comando.
Por ello los kits de desarrollo, y concretamente WTK, proporcionan entornos
para crear aplicaciones de forma automatizada, sin tener que trabajar directamente
con las herramientas en línea de comando. En el caso de WTK, esta herramienta
recibe el nombre de ktoolbar
:
Este entorno nos permitirá construir la aplicación a partir del código fuente, pero no proporciona ningún editor de código fuente, por lo que tendremos que escribir el código fuente utilizando cualquier editor externo. Otra posibilidad es integrar WTK en algún entorno de desarrollo integrado (IDE) de forma que tengamos integrado el editor con todas las herramientas para construir las aplicaciones facilitando más aun la tarea del desarrollador. En el siguiente punto veremos como desarrollar aplicaciones utilizando un IDE.
Directorio de aplicaciones
Este entorno de desarrollo guarda todas las aplicaciones dentro de un mismo directorio de aplicaciones. Cada aplicación estará dentro de un subdirectorio dentro de este directorio de aplicaciones, cuyo nombre corresponderá al nombre de la aplicación.
Por defecto, este directorio de aplicaciones es el directorio ${WTK_HOME}/apps
,
pero podemos modificarlo añadiendo al fichero ktools.properties
la siguiente línea:
kvem.apps.dir: <directorio de aplicaciones>
Además, dentro de este directorio hay un directorio lib
,
donde se pueden poner las librerías externas que queremos que utilicen
todas las aplicaciones. Estas librerías serán ficheros JAR cuyo
contenido será incorporado a las aplicaciones MIDP que creemos, de forma
que podamos utilizar esta librería dentro de ellas.
Por ejemplo, después de instalar WTK podemos encontrar a parte del directorio de librerías una serie de aplicaciones de demostración instaladas. El directorio de aplicaciones puede contener por ejemplo los siguientes directorios (en el caso de WTK 2.1):
audiodemo
demos FPDemo
games
JSR172Demo lib mmademo
NetworkDemo
photoalbum SMSDemo
tmplib UIDemo
Tendremos por lo tanto las aplicaciones games
, demos
,
photoalbum
, y UIDemo
. El directorio tmplib
lo utiliza el entorno para trabajar de forma temporal con las librerías
del directorio lib
.
NOTA: Dado que se manejan gran cantidad de herramientas y emuladores independientes en el desarrollo de las aplicaciones MIDP, es recomendable que el directorio donde está instalada la aplicación (ni ninguno de sus ascendientes) contenga espacios en blanco, ya que algunas aplicaciones puede fallar en estos casos.
Estructura de las aplicaciones
Dentro del directorio de cada aplicación, se organizarán los distintos ficheros de los que se compone utilizando la siguiente estructura de directorios:
bin lib res src classes tmpclasses tmplib
Deberemos crear el código fuente de la aplicación dentro del
directorio src
, creando dentro de este directorio la estructura
de directorios correspondiente a los paquetes a los que pertenezcan nuestras
clases.
En res
guardaremos todos los recursos que nuestra aplicación
necesite, pudiendo crear dentro de este directorio la estructura de directorios
que queramos para organizar estos recursos.
Por último, en lib
deberemos poner las librerías
adicionales que queramos incorporar a nuestra aplicación. Pondremos en
este directorio el fichero JAR con la librería de clases que queramos
añadir. Lo que se hará será añadir todas las clases
contenidas en estas librerías, así como las contenidas en las
librerías globales que hemos visto anteriormente, al fichero JAR que
creemos para nuestra aplicación.
NOTA: Si lo que queremos es utilizar en nuestra aplicación una API opcional
soportada por el móvil, no debemos introducirla en este directorio. En
ese caso sólo deberemos añadirla al classpath
a la
hora de compilar, pero no introducirla en este directorio ya que el móvil
ya cuenta con su propia implementación de dicha librería y no
deberemos añadir la implementación de referencia que tenemos en
el ordenador al paquete de nuestra aplicación.
Esto es todo lo que tendremos que introducir nosotros. Todo lo demás
será generado automáticamente por la herramienta ktoolbar
como veremos a continuación. En el directorio classes
se
generarán las clases compiladas y preverificadas de nuestra aplicación,
y en bin
tendremos finalmente los ficheros JAR y JAD para desplegar
nuestra aplicación.
Creación de una nueva aplicación
Cuando queramos crear una nueva aplicación, lo primero que haremos será pulsar el botón "New Project ..." para abrir el asistente de creación de aplicaciones. Lo primero que nos pedirá es el nombre que queremos darla a la aplicación, y el nombre de la clase principal (MIDlet) que vamos a crear:
Debemos indicar aquí un nombre para la aplicación (Project Name), que será el nombre del directorio donde se guardará la aplicación. Además deberemos indicar el nombre de la clase correspondiente al MIDlet principal de la suite (MIDlet Class Name). Es posible que nosotros todavía no hayamos creado esta clase, por lo que deberemos indicar el nombre que le asignaremos cuando la creemos. De todas formas este dato puede ser modificado más adelante.
Una vez hayamos introducido estos datos, pulsamos "Create Project"
y nos aparecerá una ficha para introducir todos los datos necesarios
para crear el fichero JAD y el MANIFEST.MF
del JAR. Con los datos
introducidos en la ventana anterior habrá rellenado todos los datos necesarios,
pero nosotros podemos modificarlos manualmente si queremos personalizarlo más.
La primera ficha nos muestra los datos obligatorios:
Como nombre de la suite y del JAR habrá tomado por defecto el nombre del proyecto que hayamos especificado. Será conveniente modificar los datos del fabricante y de la versión, para adaptarlos a nuestra aplicación. No debemos preocuparnos por especificar el tamaño del JAR, ya que este dato será actualizado de forma automática cuando se genere el JAR de la aplicación.
En la segunda pestaña tenemos los datos opcionales que podemos introducir en estos ficheros:
Estos datos están vacíos por defecto, ya que no son necesarios, pero podemos darles algún valor si lo deseamos. Estas son las propiedades opcionales que reconoce el AMS. Si queremos añadir propiedades propias de nuestra aplicación, podemos utilizar la tercera pestaña:
Aquí podemos añadir o eliminar cualquier otra propiedad que queramos
definir para nuestra aplicación. De esta forma podemos parametrizarlas.
En el ejemplo de la figura hemos creado una propiedad msg.bienvenida
que contendrá el texto de bienvenida que mostrará nuestra aplicación.
De esta forma podremos modificar este texto simplemente modificando el valor
de la propiedad en el JAD, sin tener que recompilar el código.
En la última pestaña tenemos los datos de los MIDlets que contiene la suite. Por defecto nos habrá creado un único MIDlet:
Por defecto le habrá dado a este MIDlet el mismo nombre que a la aplicación, es decir, el nombre del proyecto que hemos especificado, al igual que ocurre con el nombre del icono. Como clase correspondiente al MIDlet habrá introducido el nombre de la clase que hemos especificado anteriormente.
Dado que una suite puede contener más de un MIDlet, desde esta pestaña podremos añadir tantos MIDlets como queramos, especificando para cada uno de ellos su nombre, icono (de forma opcional) y clase.
Una vez terminemos de introducir todos estos datos, pulsamos "OK" y en la ventana principal nos mostrará el siguiente mensaje:
Con este mensaje nos notifica el directorio donde se ha creado la aplicación, y los subdirectorios donde debemos introducir el código fuente, recursos y librerías externas de nuestra aplicación. Se habrá creado la siguiente estructura de directorios en el disco:
En el directorio bin
se habrán creado los ficheros JAD
y MANIFEST.MF
provisionales con los datos que hayamos introducido.
Los demás directorios estarán vacíos, deberemos introducir
en ellos todos los componentes de nuestra aplicación.
Abrir una aplicación ya existente
Si tenemos una aplicación ya creada, podemos abrirla desde el entorno para continuar trabajando con ella. Para abrir una aplicación pulsamos "Open Project ..." y nos mostrará la siguiente ventana con las aplicaciones disponibles:
Podemos seleccionar cualquiera de ellas y abrirla pulsando "Open
Project". Una vez abierta podremos modificar todos los datos que
hemos visto anteriormente correspondientes a los ficheros JAD y MANIFEST.MF
pulsando sobre el botón "Settings ...".
Además podremos compilarla, empaquetarla y probarla en cualquier emulador instalado como veremos a continuación.
Una vez hemos escrito el código fuente de nuestra aplicación
MIDP (en el directorio src
) y hemos añadido los recursos
y las librerías necesarias para ejecutarse dicha aplicación (en
los directorios res
y lib
respectivamente) podremos
utilizar la herramienta ktoolbar
para realizar de forma automatizada
todos los pasos para la construcción de la aplicación. Vamos a
ver ahora como realizar este proceso.
Compilación
Para compilar el código fuente de la aplicación simplemente deberemos
pulsar el botón "Build" o ir a la opción
del menú Project > Build. Con esto compilará
y preverificará de forma automática todas las clases de nuestra
aplicación, guardando el resultado en el directorio classes
de nuestro proyecto.
Para compilar las clases utilizará como classpath la API proporcionada por el emulador seleccionado actualmente. Para los emuladores distribuidos con WTK estas clases serán las API básica de MIDP (1.0 ó 2.0 según la versión de WTK instalada). Sin embargo, podemos incorporar emuladores que soporten APIs adicionales, como por ejemplo MMAPI para dar soporte a elementos multimedia, o APIs propietarias de distintas compañías como Nokia. En caso de tener seleccionado un emulador con alguna de estas APIs adicionales, estas APIs también estarán incluidas en el classpath, por lo que podremos compilar correctamente programas que las utilicen. El emulador seleccionado aparece en el desplegable Device.
Ofuscación
El entorno de desarrollo de WTK también nos permitirá ofuscar el código de forma automática. Este paso es opcional, y si queremos que WTK sea capaz de utilizar la ofuscación deberemos descargar alguno de los ofuscadores soportados por este entorno, como ProGuard (en WTK 2.X) o RetroGuard (en WTK 1.0). Estos ofuscadores son proporcionados por terceros.
Una vez tenemos uno de estos ofuscadores, tendremos un fichero JAR con las
clases del ofuscador. Lo que deberemos hacer para instalarlo es copiar este
fichero JAR al directorio ${WTK_HOME}/bin
. Una vez tengamos el
fichero JAR del ofuscador en este directorio, WTK podrá utilizarlo de
forma automática para ofuscar el código.
La ofuscación la realizará WTK en el mismo paso de la creación del paquete JAR, en caso de disponer de un ofuscador instalado, como veremos a continuación.
Empaquetamiento
Para poder instalar una aplicación en el móvil y distribuirla, deberemos generar el fichero JAR con todo el contenido de la aplicación. Para hacer esto de forma automática deberemos ir al menú Project > Package. Dentro de este menú tenemos dos opciones:
Ambas realizan todo el proceso necesario para crear el paquete de forma automática: compilan los fuentes, ofuscan (sólo en el segundo caso), preverifican y empaquetan las clases resultantes en un fichero JAR. Por lo tanto no será necesario utilizar la opción Build previamente, ya que el mismo proceso de creación del paquete ya realiza la compilación y la preverificación.
Una vez construido el fichero JAR lo podremos encontrar en el directorio bin
de la aplicación. Además este proceso actualizará de forma
automática el fichero JAD, para establecer el tamaño correcto
del fichero JAR que acabamos de crear en la propiedad correspondiente.
Dentro del mismo entorno de desarrollo de WTK podemos ejecutar la aplicación
en diferentes emuladores que haya instalados para probarla. Podemos seleccionar
el emulador a utilizar en el cuadro desplegable Device de la
ventana principal de ktoolbar
.
Para ejecutar la aplicación en el emulador seleccionado solo debemos pulsar el botón "Run" o la opción del menú Project > Run. Normalmente, para probar la aplicación en un emulador no es necesario haber creado el fichero JAR, simplemente con las clases compiladas es suficiente. En caso de ejecutarse sin haber compilado las clases, el entorno las compilará de forma automática.
Sin embargo, hay algunos emuladores que sólo funcionan con el fichero JAR, por lo que en este caso deberemos crear el paquete antes de ejecutar el emulador. Esto ocurre por ejemplo con algún emulador proporcionado por Nokia.
Por ejemplo, los emuladores de teléfonos móviles proporcionados con WTK 2.2 son:
Además de estos, podemos incorporar otros emuladores al kit de desarrollo. Por ejemplo, los emuladores proporcionados por Nokia, imitando diversos modelos de teléfonos móviles de dicha compañía, pueden ser integrados fácilmente en WTK.
Para integrar los emuladores de teléfonos Nokia en WTK simplemente tendremos
que instalar estos emuladores en el directorio ${WTK_HOME}/wtklib/devices
.
Una vez instalados en este directorio, estos emuladores estarán disponibles
dentro del kit de desarrollo, de forma que podremos seleccionarlos en el cuadro
desplegable como cualquier otro emulador.
![]() MinimumPhone |
![]() DefaultColorPhone |
![]() Motorola i85s |
![]() Nokia 6310 |
![]() Nokia 7210 |
![]() Nokia Series 60 |
Podemos encontrar además emuladores proporcionados por otras compañías. WTK también nos permite personalizar los emuladores, cambiando su aspecto y características para adaptarlos a nuestras necesidades.
Optimización
En WTK, además de los emuladores, contamos con herramientas adicionales que nos ayudarán a optimizar nuestras aplicaciones. Desde la ventana de preferencias podemos activar distintos monitores que nos permitirán monitorizar la ocupación de memoria y el tráfico en la red:
Será conveniente utilizar estos monitores para medir el consumo de recursos de nuestra aplicación e intentar reducirlo al mínimo.
En cuanto a la memoria, deberemos intentar que el consumo sea lo menor posible y que nunca llegue a pasar de un determinado umbral. Si la memoria creciese sin parar en algún momento la aplicación fallaría por falta de memoria al llevarla a nuestro dispositivo real.
Es importante también intentar minimizar el tráfico en la red, ya que en los dispositivos reales este tipo de comunicaciones serán lentas y caras.
Desde esta ventana de preferencias podemos cambiar ciertas características de los emuladores, como el tamaño máximo de la memoria o la velocidad de su procesador. Es conveniente intentar utilizar los parámetros más parecidos a los dispositivos para los cueles estemos desarrollando, sobretodo en cuanto a consumo de memoria, para asegurarnos de que la aplicación seguirá funcionando cuando la llevamos al dispositivo real.
Hemos visto como probar la aplicación directamente utilizando emuladores. Una vez generados los ficheros JAR y JAD también podremos copiarlos a un dispositivo real y probarlos ahí.
Sin embargo, cuando un usuario quiera utilizar nuestra aplicación, normalmente lo hará vía OTA (Over The Air), es decir, se conectará a la dirección donde hayamos publicado nuestra aplicación y la descargará utilizando la red de nuestro móvil.
Para desplegar una aplicación de forma que sea accesible vía OTA, simplemente deberemos:
Una vez está desplegada la aplicación vía OTA, el provisionamiento OTA consistirá en los siguientes pasos:
A partir de WTK 2.0 podemos simular en los emuladores el provisionamiento OTA de aplicaciones. Ejecutando la aplicación OTA Provisioning se nos abrirá el emulador que tengamos configurado por defecto y nos dará la opción de instalar aplicaciones (Install Application) vía OTA. Si pulsamos sobre esta opción nos pedirá la URL donde hayamos publicado nuestra aplicación.
De esta forma podremos probar aplicaciones publicadas en algún servidor de Internet. Para probar nuestras aplicaciones utilizando este procedimiento deberemos desplegar previamente nuestra aplicación en un servidor web y utilizar la dirección donde la hayamos desplegados para instalar la aplicación desde ese lugar.
Este procedimiento puede ser demasiado costoso si queremos probar la aplicación repetidas veces utilizando este procedimiento, ya que nos obligaría, para cada nueva prueba que quisiésemos hacer, a volver a desplegar la aplicación en el servidor web.
La aplicación ktoolbar
nos ofrece una facilidad con el
que simular el provisionamiento OTA utilizando un servidor web interno, de forma
que no tendremos que publicar la aplicación manualmente para probarla.
Para ello, abriremos nuestro proyecto en ktoolbar
y seleccionaremos
la opción Project > Run via OTA. Con esto, automáticamente
nos rellenará la dirección de donde queremos instalar la aplicación
con la dirección interna donde está desplegada:
Una vez introducida la dirección del documento web donde tenemos publicada nuestra aplicación, nos mostrará la lista de enlaces a ficheros JAD que tengamos en esa página. Podremos seleccionar uno de estos enlaces para instalar la aplicación. En ese momento descargará el fichero JAD y nos mostrará la información contenida en él, preguntándonos si queremos instalar la aplicación:
Si aceptamos la instalación de la aplicación, pulsando sobre Install, descargará el fichero JAR con la aplicación y lo instalará. Ahora veremos esta aplicación en la lista de aplicaciones instaladas:
Desde esta lista podremos ejecutar la aplicación e instalar nuevas aplicaciones que se vayan añadiendo a esta lista. Cuando no necesitemos esta aplicación desde aquí también podremos desinstalarla.
La herramienta ant
nos permite automatizar tareas como la compilación,
empaquetamiento, despliegue o ejecución de aplicaciones. Es similar a
la herramienta make
, pero con la ventaja de que es totalmente independiente
de la plataforma, ya que en lugar de utilizar comandos nativos utiliza clases
Java para realizar las tareas.
Tiene una serie de tareas definidas, que servirán para compilar clases, empaquetar en ficheros JAR, ejecutar aplicaciones, etc. Todas estas tareas están implementadas mediante clases Java. Además, nos permitirá añadir nuevas tareas, incorporando una librería de clases Java que las implemente.
Antenna es una librería de tareas para ant que nos
permitirán trabajar con aplicaciones MIDP. Entre estas tareas encontramos
la compilación y el empaquetamiento (con preverificación y ofuscación),
la creación de los ficheros JAD y MANIFEST.MF
, y la ejecución
de aplicaciones en emuladores.
Para realizar estas tareas utiliza WTK, por lo que necesitaremos tener este kit de desarrollo instalado. Los emuladores que podremos utilizar para ejecutar las aplicaciones serán todos aquellos emuladores instalados en WTK.
Para utilizar estas tareas deberemos copiar el JAR de Antenna al directorio de librerías de ant, o bien introducir este JAR en el classpath para que esté localizable.
Dentro del fichero build.xml
de ant deberemos especificar
como propiedad wtk.home
el directorio donde tenemos instalado WTK:
<property name="wtk.home" value="c:\WTK104"/>
Además, debemos declarar las tareas de Antenna para poder utilizarlas dentro de dicho fichero:
<taskdef name="wtkjad" classname="de.pleumann.antenna.WtkJad"/> <taskdef name="wtkbuild" classname="de.pleumann.antenna.WtkBuild"/> <taskdef name="wtkpackage" classname="de.pleumann.antenna.WtkPackage"/> <taskdef name="wtkrun" classname="de.pleumann.antenna.WtkRun"/> <taskdef name="wtkpreverify" classname="de.pleumann.antenna.WtkPreverify"/> <taskdef name="wtkobfuscate" classname="de.pleumann.antenna.WtkObfuscate"/>
Para crear el fichero JAD utilizaremos la tarea wtkjad
, a la que
debemos proporcionar la siguiente información:
<wtkjad jadfile="${jad.file}" jarfile="${jar.file}" name="${midlet.name}" vendor="${vendor.name}" version="${midlet.version}"> <midlet name="${midlet.name}" class="${midlet.class}"/> <attribute name="msg.bienvenida" value="Hola mundo"/>
</wtkjad>
Para compilar utilizaremos wtkbuild
. Esta tarea nos permite preverificar,
pero podemos dejar esto para el paso siguiente:
<wtkbuild srcdir="${src.home}" destdir="${build.home}" preverify="false"/>
Para empaquetar utilizaremos wtkpackage
. En este paso podremos
ofuscar y preverificar el código:
<wtkpackage jarfile="${jar.file}" jadfile="${jad.file}" obfuscate="${obfuscate}" preverify="true"> <fileset dir="${build.home}"/> <fileset dir="${res.home}"/> </wtkpackage>
Aquí debemos especificar los ficheros que vamos a incluir en el paquete
JAR mediante las etiquetas fileset
. En este ejemplo estamos incluyendo
todos los ficheros que haya en el directorio de clases compiladas y en el directorio
de recursos. Si queremos incluir librerías JAR (o ZIP) podemos utilizar
las siguientes etiquetas:
<zipfileset src="libreria.zip"/> <zipgroupfileset dir="lib"/>
La primera de ellas (zipfileset
) nos permite especificar una única
librería para incluir. Con la segunda (zipgroupfileset
)
se incluirán todas las librerías del directorio especificado.
Por último, para ejecutar la aplicación en un emulador utilizaremos
la tarea wtkrun
:
<wtkrun jadfile="${jad.file}" heapsize="0" device="${emulator.name}" wait="true"/>
Con esto podremos crear nuestras aplicaciones MIDP utilizando ant,
en lugar de utilizar la aplicación ktoolbar
de WTK.
Vamos a ver un ejemplo completo genérico. Este código podrá ser aprovechado para la mayoría de aplicaciones J2ME, simplemente cambiando las propiedades declaradas al principio del fichero para introducir los datos correspondientes a cada aplicación:
<?xml version="1.0"?> <project name="Prueba" default="run" basedir="."> <!-- Propiedades del MIDlet --> <property name="jad.file" value="aplic.jad"/> <property name="jar.file" value="aplic.jar"/> <property name="vendor.name" value="Miguel Angel"/> <property name="midlet.version" value="1.0.0"/> <property name="midlet.name" value="Prueba"/> <property name="midlet.class" value="es.ua.j2ee.prueba.PrimerMIDlet"/> <!-- Propiedades del entorno --> <property name="emulator.name" value="DefaultColorPhoneEmulator"/> <property name="base.home" value="."/> <property name="src.home" value="${base.home}/src"/> <property name="build.home" value="${base.home}/classes"/> <property name="res.home" value="${base.home}/res"/> <property name="obfuscate" value="true"/> <!-- Establece el directorio de WTK (requerido por Antenna). --> <property name="wtk.home" value="c:\WTK104"/> <!-- Define las tareas de Antenna. --> <taskdef name="wtkjad" classname="de.pleumann.antenna.WtkJad"/> <taskdef name="wtkbuild" classname="de.pleumann.antenna.WtkBuild"/> <taskdef name="wtkpackage" classname="de.pleumann.antenna.WtkPackage"/> <taskdef name="wtkrun" classname="de.pleumann.antenna.WtkRun"/> <taskdef name="wtkpreverify" classname="de.pleumann.antenna.WtkPreverify"/> <taskdef name="wtkobfuscate" classname="de.pleumann.antenna.WtkObfuscate"/> <!-- Crea el fichero JAD. --> <target name="jad"> <wtkjad jadfile="${jad.file}" jarfile="${jar.file}" name="${midlet.name}" vendor="${vendor.name}" version="${midlet.version}"> <midlet name="${midlet.name}" class="${midlet.class}"/> </wtkjad> </target> <!-- Limpia el directorio de compilacion. --> <target name="clean"> <delete dir="${build.home}"/> <mkdir dir="${build.home}"/> </target> <!-- Compila las clases. --> <target name="compile" depends="clean"> <wtkbuild srcdir="${src.home}" destdir="${build.home}" preverify="false"/> </target> <!-- Empaqueta la aplicacion. --> <target name="package" depends="jad,compile"> <wtkpackage jarfile="${jar.file}" jadfile="${jad.file}" obfuscate="${obfuscate}" preverify="true"> <fileset dir="${build.home}"/> <fileset dir="${res.home}"/> </wtkpackage> </target> <!-- Ejecuta el MIDlet en un emulador. --> <target name="run" depends="package"> <wtkrun jadfile="${jad.file}" heapsize="0" device="${emulator.name}" wait="true"/> </target> </project>
Puede ocurrir que una aplicación necesite APIs adicionales para compilarse,
como puede ser MMAPI, WMA u otras APIs opcionales que podamos encontrar en algunos
modelos de teléfonos móviles. Es este caso deberemos especificar
de forma explícita el classpath que vamos a utilizar para la
compilación (wtkbuild
) y el empaquetamiento (wtkpackage
).
Para ello deberemos añadir dentro de cada una de estas tareas el siguiente
atributo:
bootclasspath="<classpath>"
Por ejemplo, si queremos utilizar la API multimedia MMAPI, podemos hacerlo de la siguiente forma:
<!-- Compila las clases. --> <target name="compile" depends="clean"> <wtkbuild srcdir="${src.home}" destdir="${build.home}" bootclasspath="${wtk.home}/lib/midpapi.zip;${wtk.home}/lib/mmapi.jar" preverify="false"> </wtkbuild> </target> <!-- Empaqueta la aplicacion. --> <target name="package" depends="jad,compile"> <wtkpackage jarfile="${jar.file}" jadfile="${jad.file}" obfuscate="${obfuscate}" bootclasspath="${wtk.home}/lib/midpapi.zip;${wtk.home}/lib/mmapi.jar" preverify="true"> <fileset dir="${build.home}"/> <fileset dir="${res.home}"/> </wtkpackage> </target>
Hemos visto que los kits de desarrollo como WTK nos permiten construir la aplicación pero no tienen ningún editor integrado donde podamos escribir el código. Por lo tanto tendríamos que escribir el código fuente utilizando cualquier editor de texto externo, y una vez escrito utilizar WTK para construir la aplicación.
Vamos a ver ahora como facilitar el desarrollo de la aplicación utilizando distintos entornos integrados de desarrollo (IDEs) que integran un editor de código con las herramientas de desarrollo de aplicaciones MIDP. Estos editores además nos facilitarán la escritura del código coloreando la sintaxis, revisando la corrección del código escrito, autocompletando los nombres, formateando el código, etc.
Para desarrollar aplicaciones J2ME podremos utilizar la mayoría de los IDEs existentes para Java, añadiendo alguna extensión para permitirnos trabajar con este tipo de aplicaciones. También podemos encontrar entornos dedicados exclusivamente a la creación de aplicaciones J2ME.
Vamos a centrarnos en dos entornos que tienen la ventaja de ser de libre distribución, y que son utilizados por una gran cantidad de usuarios dadas sus buenas prestaciones. Luego comentaremos más brevemente otros entornos disponibles para trabajar con aplicaciones J2ME.
Eclipse es un entorno de desarrollo de libre distribución altamente modular. Una de sus ventajas es que no necesita demasiados recursos para ejecutarse correctamente, por lo que será adecuado para máquinas poco potentes. Vamos a utilizar como referencia la versión 2.1.1 de este entorno. Algunas características pueden variar si se utiliza una versión distinta.
Este entorno nos permite crear proyectos en Java. Nos ofrece un editor, en el que podemos escribir el código, viendo la sintaxis coloreada para mayor claridad, y notificándonos de los errores que hayamos cometido al escribir el código, como por ejemplo haber escrito mal el nombre de un método, o usar un tipo o número incorrecto de parámetros. Además nos permitirá autocompletar los nombres de los métodos o las propiedades de las clases conforme los escribimos. Si el código ha quedado desordenado, nos permite darle formato automáticamente, poniendo la sangría adecuada para cada línea de código.
Esto nos facilitará bastante la escritura del código fuente. Sin embargo, no nos permitirá crear visualmente la GUI de las aplicaciones, ni el diseño, ni manejará conexiones con BDs ni con servidores de aplicaciones. Esto hace que el entorno sea bastante más ligero que otros entornos, por lo que será más cómodo de manejar si no necesitamos todas estas características. Incluso podemos añadirle muchas de estas funcionalidades que se echan en falta añadiendo módulos (plugins) al entorno.
Podremos compilar las clases del proyecto desde el mismo entorno, y ejecutar la aplicación para probarla utilizando la máquina virtual de Java. Esto será suficiente para aplicaciones J2SE, pero en principio no ofrece soporte directo para J2ME. Podemos optar por diferentes soluciones para crear aplicaciones J2ME con este entorno:
A continuación veremos como crear aplicaciones J2ME paso a paso siguiendo cada uno de estos tres métodos.
Editor de código
Vamos a ver como utilizar Eclipse simplemente para editar el código de las aplicaciones J2ME, dejando las tareas de compilación, empaquetamiento y ejecución para realizarlas de forma externa con WTK.
Lo primero que tenemos que hacer es crear una nueva aplicación utilizando WTK, como hemos visto en el punto anterior, de forma que nos cree la estructura de directorios necesaria en nuestro directorio de proyectos.
Una vez hecho esto, podemos entrar ya en Eclipse para comenzar a escribir código. Crearemos un nuevo proyecto Java, utilizando el comando New:
Elegimos Java Project y pulsamos Next para comenzar el asistente de creación del proyecto:
Debemos darle un nombre al proyecto, y un directorio donde guardar su contenido. Elegiremos la opción Create project at external location para poder elegir como directorio del proyecto el directorio que queramos, y seleccionaremos como tal el directorio que hemos creado previamente con WTK. Pulsamos Next para continuar con el asistente.
Debemos especificar los directorios donde guardar los fuentes del proyecto, y donde se guardarán las clases compiladas. Pulsamos sobre Add Folder ... para seleccionar el directorio donde se encontrarán los fuentes de nuestro proyecto.
Como directorio de fuentes seleccionaremos el subdirectorio src
del directorio de nuestro proyecto, si no estuviese seleccionado ya.
Como directorio de salida (Default output folder) podemos
especificar el directorio classes
.
Ahora pasamos a la pestaña Libraries de esta misma ventana.
En ella por defecto tendremos las librerías de J2SE. Como no queremos
que se utilicen estas librerías en nuestra aplicación, las eliminaremos
de la lista con Remove, y añadiremos la librería
de la API MIDP. Para ello pulsaremos el botón Add External JARs
y seleccionaremos el JAR de MIDP, ubicado normalmente en el directorio ${WTK_HOME}/lib/midpapi.zip
.
Si quisiéramos utilizar otras APIs en nuestra aplicación, como
MMAPI o APIs propietarias, seguiremos el mismo proceso para añadir sus
correspondientes ficheros JAR a la lista.
Como no vamos a utilizar Eclipse para compilar, estas librerías nos servirán simplemente para que Eclipse pueda autocompletar el código que escribamos y detectar errores.
Una vez hemos terminado pulsaremos Finish con lo que terminaremos de configurar el proyecto en Eclipse. Una vez hecho esto, en la ventana del explorador de paquete de Eclipse (Package Explorer) veremos nuestro proyecto ya creado:
Ahora podemos empezar a crear las clases de nuestra aplicación. Para ello pulsaremos sobre New y elegiremos crear una nueva clase Java, con lo que se abrirá la siguiente ventana de creación de la clase:
Aquí deberemos introducir el paquete al que pertenecerá la clase,
y el nombre de la misma. También debemos indicar la superclase y las
interfaces que implementa la clase que vayamos a crear. En caso de querer crear
un MIDlet, utilizaremos como superclase la clase MIDlet
. Para añadir
una superclase podemos pulsar sobre el botón Browse...,
de forma que nos mostrará la siguiente ventana desde la que podremos
buscar clases de las que heredar:
En el campo de texto superior, donde nos dice Choose a type, podremos empezar a escribir el nombre de la clase de la que queramos heredar, y el explorador nos mostrará todas las clases cuyo nombre coincida total o parcialmente con el texto escrito. Seleccionaremos la clase deseada y pulsamos OK.
Si dejamos marcada la casilla Inherited abstract methods, nos creará el esqueleto de la clase con los métodos definidos como abstractos en la superclase que debemos rellenar como vemos a continuación:
Aquí podremos introducir el código necesario en los métodos que nos ha creado. Junto al editor de código en el explorador de paquetes veremos la clase que acabamos de crear:
Aquí podemos ver la estructura de directorios de nuestro proyecto, los paquetes y las clases de nuestra aplicación, y las librerías utilizadas.
Una vez hayamos creado todas las clases necesarias desde Eclipse, y hayamos escrito el código fuente, deberemos volver a WTK para compilar y ejecutar nuestra aplicación.
Integracción con Antenna
Para no tener que utilizar dos herramientas por separado (WTK y Eclipse), podemos aprovechar la integración de ant con Eclipse para compilar y ejecutar las aplicaciones J2ME utilizando las tareas de Antenna.
Para poder utilizar estas tareas deberemos configurar Antenna dentro de Eclipse, para lo cual debemos ir a Window > Preferences, y dentro de la ventana de preferencias seleccionar las preferencias de Runtime de Ant:
Aquí deberemos añadir como entrada adicional de classpath el fichero JAR de Antenna. Una vez hecho esto podremos utilizar las tareas de Antenna dentro de los ficheros de ant.
NOTA: Para que ant funcione correctamente desde dentro de Eclipse
es necesario añadir al classpath de ant (Runtime classpath
de la ventana anterior) la librería tools.jar
que podemos
encontrar dentro del directorio ${JAVA_HOME}$/lib
.
Ahora tenemos que crear el fichero de ant. Para ello seleccionamos
New > File, para crear un fichero genérico. Llamaremos
al fichero build.xml
, y escribiremos en él todas las tareas
necesarias para compilar y ejecutar la aplicación, como vimos en el punto
de Antenna. Una vez escrito este fichero lo grabaremos.
Ahora debemos ir al panel de Ant dentro de Eclipse. Si no tenemos este panel iremos a Window > Show view para mostrarlo. Dentro de este panel pulsaremos sobre el botón para añadir un buildfile, seleccionando el fichero que acabamos de crear, y una vez añadido veremos en ese panel la lista de los posibles objetivos que hay definidos en el fichero. Podremos desde este mismo panel ejecutar cualquiera de los objetivos, pudiendo de esta forma compilar y ejecutar la aplicación directamente desde el entorno.
EclipseME
EclipseME es un plugin realizado por terceros que nos facilitará la creación de aplicaciones J2ME desde Eclipse.
Lo primero que debemos hacer es instalar el plugin, descomprimiéndolo
en el directorio ${ECLIPSE_HOME}/plugins
. Una vez hecho esto, deberemos
reiniciar el entorno, y entonces deberemos ir a Window > Preferences
para configurar el plugin:
En el apartado de configuración de J2ME, dentro del subapartado Platform Components, deberemos especificar el directorio donde tenemos instalado WTK. Para ello pulsamos con el botón derecho del ratón sobre Wireless Toolkits y seleccionamos la opción Add Wireless Toolkit. Nos mostrará la siguiente ventana, en la que deberemos seleccionar el directorio donde se encuentra WTK:
Una vez añadido un toolkit, se mostrarán los componentes añadidos en la ventana de configuración:
De esta forma vemos que al añadir WTK 2.1 hemos añadido soporte para los perfiles MIDP 1.0 y 2.0, y para las configuraciones CLDC 1.0 y 1.1. Podremos configurar varios toolkits. Por ejemplo, podemos tener configuradas las distintas versiones de WTK (1.0, 2.0, 2.1 y 2.2) para utilizar la que convenga en cada momento. Una vez hayamos terminado de configurar los toolkits, pulsaremos OK para cerrar esta ventana.
Una vez configurado, podremos pulsar sobre New, donde encontraremos disponibles asistentes para crear aplicaciones J2ME:
Lo primero que haremos será crear la suite (proyecto). Seleccionamos J2ME Midlet Suite y pulsamos Next para comenzar con el asistente de creación de la suite J2ME:
Deberemos darle un nombre al proyecto que estamos creando. En este caso podemos utilizar el directorio por defecto, ya que no vamos a utilizar WTK para construir la aplicación, la construiremos directamente desde Eclipse. Una vez asignado el nombre pulsamos sobre Next para ir a la siguiente ventana:
Aquí podemos elegir la versión de MIDP para la que queremos programar, siempre que tengamos instalado el WTK correspondiente para cada una de ellas. Una vez elegida la versión para la que queremos desarrollar pulsamos Finish, con lo que habremos terminado de configurar nuestro proyecto. En este caso no hace falta que especifiquemos las librerías de forma manual, ya que el asistente las habrá configurado de forma automática.
Una vez creado el proyecto, podremos añadir MIDlets u otras clases Java. Pulsando sobre New veremos los elementos que podemos añadir a la suite:
Si queremos crear un MIDlet, podremos utilizar la opción J2ME Midlet y pulsar Next, con lo que se mostrará la siguiente ventana para introducir los datos del MIDlet:
Aquí deberemos dar el nombre del paquete y el nombre de la clase de nuestro MIDlet. Pulsando sobre Finish creará el esqueleto de la clase correspondiente al MIDlet, donde nosotros podremos insertar el código necesario.
En el explorador de paquetes podemos ver las clases creadas, la librería utilizada y el fichero JAD del proyecto. Pinchando sobre el fichero JAD se mostrará en el editor la siguiente ficha con los datos de la suite:
Aquí deberemos introducir la información necesaria, sobre los datos de la suite (Required) y los MIDlets que hayamos creado en ella (en la pestaña Midlets). Podemos ver que, cuando creemos un MIDlet mediante el asistente que acabamos de utilizar para la creación de MIDlets, los datos del MIDlet creado se añaden automáticamente al JAD.
No es necesario compilar el proyecto manualmente, ya que Eclipse se ocupará de ello. Cuando queramos ejecutarlo, podemos seleccionar en el explorador de paquetes el MIDlet que queramos probar y pulsar sobre el botón Run > Emulated J2ME Midlet:
Esto abrirá nuestro MIDlet en el emulador que se haya establecido como emulador por defecto del toolkit utilizado. Si queremos tener un mayor control sobre cómo se ejecuta nuestra aplicación, podemos utilizar la opción Run... que nos mostrará la siguiente ventana:
En esta ventana pulsaremos sobre Wireless Toolkit Emulator y sobre New para crear una nueva configuración de ejecución sobre los emuladores de J2ME. Dentro de esta configuración podremos seleccionar el emulador dentro de la pestaña Device, y una vez seleccionado ya podremos pulsar sobre Run para ejecutar la aplicación.
Con Eclipse hemos visto un entorno bastante ligero para la escritura del código. Vamos a ver ahora un entorno más completo también de libre distribución. Se trata de NetBeans, versión de libre distribución del entorno de Sun Forte for Java, también conocido como Sun One Studio.
NetBeans además del editor integrado de código, nos permitirá crear la GUI de las aplicaciones de forma visual, crear elementos para aplicaciones J2EE, como servlets, JSPs y beans, manejar conexiones a BDs, e integra su propio servidor de aplicaciones para poder probar las aplicaciones web entre otras cosas. El contar con todas estas características le hace ser un entorno bastante más pesado que el anterior, que necesitará un mayor número de recursos para ejecutarse correctamente.
Al igual que Eclipse, el editor también nos permite autocompletar el código, colorea la sintaxis para una mayor claridad y detecta algunos fallos conforme vamos escribiendo.
Respecto a las aplicaciones MIDP, podemos encontrar plugins oficiales para desarrollar este tipo de aplicaciones desde el entorno. Además, incluirá un depurador (debugger) con el que podremos depurar las aplicaciones para móviles, cosa que no podemos hacer simplemente con WTK o con Eclipse.
Tenemos una serie de plugins para añadir los asistentes y soporte necesario para los componentes MIDP y para instalar una versión de WTK integrada en el mismo entorno, por lo que no necesitaríamos instalar una versión externa. También disponemos de plugins con distintos ofuscadores, que podemos instalar de forma opcional, de forma que podamos ofuscar el código desde el mismo entorno.
Una vez instalados estos plugins, pulsando sobre New... podemos crear diferentes elementos para las aplicaciones MIDP:
Vamos a comenzar creando la suite. Para ello seleccionamos MIDletSuite y pulsamos sobre Next para continuar con el asistente de creación de la suite:
Debemos especificar un nombre para la suite. Escribiremos el nombre que queramos y pulsamos sobre Next para pasar a la siguiente ficha:
Aquí podremos crear nuestro MIDlet principal para incluir en la suite si no tenemos ningún MIDlet creado todavía. Existen diferentes plantillas para MIDlets, que introducen cierta parte del código por nosotros. Podemos seleccionar la plantilla MIDlet si queremos que se genere el esqueleto vacío de un MIDlet, o HelloMIDlet si queremos que se genere un MIDlet de ejemplo que contenga el código para mostrar el mensaje "Hola mundo", cosa que nos puede servir para probar estas aplicaciones sin tener que introducir código fuente nosotros. Deberemos además darle un nombre al MIDlet que creemos, que debe constar del nombre del paquete y nombre de la clase. Pulsamos sobre Next para continuar:
Ahora deberemos introducir el nombre que queremos darle al MIDlet, y de forma opcional el icono con el que se identificará el MIDlet. Una vez hecho esto ya podremos pulsar sobre Finish con lo que habremos terminado de crear la suite. Podremos ver en el explorador de NetBeans los elementos que se han creado.
Dentro del entorno tenemos tres pestañas como las siguientes:
Para editar el código utilizaremos la vista de edición, teniendo seleccionada la primera pestaña (Editing). La segunda (GUI Editing) nos servirá para crear de forma visual la GUI de las aplicaciones AWT y Swing, por lo que no nos servirá para el desarrollo de aplicaciones J2ME. La tercera (Debugging) la utilizaremos cuando estemos depurando el código, tal como veremos más adelante.
Vamos a ver como trabajar en vista de edición para editar y probar nuestra aplicación. En esta vista se mostrará en la parte izquierda de la pantalla el explorador, donde podemos ver los elementos que hemos creado:
Haciendo doble click sobre el elemento correspondiente a la suite podremos modificar sus propiedades. Se abrirá la siguiente ventana:
Aquí podremos modificar la lista de MIDlets que vamos a incluir en la suite. En la pestaña Jar Contents podremos seleccionar todos los elementos que vamos a introducir en el JAR de la suite, como recursos, clases y librerías externas.
En la parte inferior el explorador tenemos el inspector de propiedades, donde podemos consultar o modificar las propiedades del elemento seleccionado actualmente en el explorador. Si tenemos seleccionado el elemento correspondientes a la suite, veremos las siguientes propiedades:
Aquí podremos modificar distintas propiedades de la suite,
correspondientes a los datos que se incluirán en los ficheros JAD y MANIFEST.MF
.
Además, en la pestaña Execution podremos seleccionar
el emulador en el que se va a ejecutar esta suite cuando la probemos.
Tendremos disponibles los mismos emuladores que contenga el WTK, y podremos
especificar la versión de WTK de la que queremos que coja los emuladores.
Para ejecutar la suite en el emulador pulsaremos con el botón derecho sobre el elemento correspondiente a dicha suite en el explorador, y seleccionamos la opción Execute, con lo que la ejecutará en el emulador seleccionado:
Otra forma de ejecutar la suite es, teniendo seleccionada la suite en el explorador, pulsar el botón de ejecución (ó F6):
Depuración
En lugar de simplemente ejecutar la aplicación para probarla, si queremos localizar fallos en ella, podemos utilizar el depurador que lleva integrado NetBeans. Podemos establecer puntos de ruptura (breakpoints) en el código para que cuando la ejecución llegue a ese lugar se detenga, permitiéndonos ejecutar paso a paso y ver detenidamente lo que ocurre. Para establecer un punto de ruptura pincharemos sobre la banda gris a la izquierda de la línea donde queremos que se detenga, quedando marcada de la siguiente forma:
Para ejecutar la aplicación en modo depuración utilizaremos los siguientes botones:
El primero de ellos nos servirá para comenzar la ejecución hasta que llegue un punto de ruptura. Una vez se produzca se detendrá el programa y podremos ir ejecutando instrucciones paso a paso utilizando el botón correspondiente en la barra de botones anterior. Se mostrará con una flecha verde la línea que se va a ejecutar en cada momento, como se muestra a continuación:
Mientras se ejecuta el programa podemos ver el estado de la memoria y de las llamadas a métodos en la ventana del depurador. Para ello tendremos que estar en vista de depuración (pestaña Debugger del entorno). Veremos la siguiente información:
Aquí podremos ver los valores que toma cada variable conforme se ejecuta el código, lo cual nos facilitará la detección de fallos en nuestro programas.
Librerías adicionales
Las librerías que se utilizan al compilar y ejecutar las aplicaciones MIDP son las librerías que aporte el emulador seleccionado, al igual que ocurría con WTK. Sin embargo, conforme editamos el código sólo cuenta con que estemos utilizando la API de MIDP básica, por lo que todos los elementos que incluyamos de librerías adicionales nos los marcará como erróneos, y no nos permitirá autocompletar los nombres para ellos.
Para que reconozca estos elementos correctamente deberemos añadir estas librerías a los sistemas de ficheros montados en el entorno. Para ello seleccionamos montar un sistema de ficheros desde un archivo, como vemos en la siguiente figura, de forma que nos permita seleccionar el fichero JAR correspondiente a la librería que queremos añadir.
Una vez montada la librería JAR, podremos verla en el explorador. Ahora considerará que esa librería está en el classpath y nos permitirá utilizar sus elementos en el editor de código sin mostrar errores. Podremos navegar por los elementos de la librería dentro de explorador:
Esto será suficiente si la librería corresponde a una API disponible en el teléfono móvil, como puede ser MMAPI, WMA y APIs propietarias de Nokia.
Si lo que queremos es añadir una librería al fichero JAR de la aplicación para introducirla en el móvil junto a la aplicación, lo primero que haremos es montarla como acabamos de ver. Una vez montada, podemos ir a la ventana de edición de la suite como hemos visto antes (haciendo doble click sobre la suite), y en la pestaña Jar Contents podremos añadir las librerías montadas a nuestro JAR.
A parte de los entornos que hemos visto, existen numerosos IDEs para desarrollo con J2ME, la mayoría de ellos de pago. A continuación vamos a ver brevemente los más destacados.
Sun One Studio ME
Se trata de la versión ME (Micro Edition) del entorno de desarrollo de Sun, Sun One Studio, anteriormente llamado Forte for Java. Esta versión ME está dirigida a crear aplicaciones J2ME, e incluye todo el software necesario para realizar esta tarea, no hace falta instalar por separado el WTK ni otras herramientas.
El entorno es muy parecido a NetBeans. Podemos descargar una versión de prueba sin ninguna limitación. Una ventaja de este entorno es que podemos integrarlo con otros kits de desarrollo como por ejemplo el kit de desarrollo de Nokia.
JBuilder y MobileSet
Podemos utilizar también el entorno de Borland, JBuilder, con la extensión MobileSet. A partir de la versión 9 de JBuilder tenemos una edición Mobile para trabajar con aplicaciones J2ME directamente sin tener que instalar ninguna extensión. Podemos descargar de forma gratuita la versión personal del entorno JBuilder, pero tiene el inconveniente de estar bastante más limitada que las versiones de pago.
Este entorno puede también integrarse con el kit de desarrollo de Nokia. Además como característica adicional podremos crear de forma visual la GUI de las aplicaciones móviles. Esta característica no está muy extendida por este tipo de entornos debido a la simplicidad de las GUIs para móviles.
JDeveloper y J2ME Plugin
El entorno de desarrollo de Oracle, JDeveloper, está dedicado principalmente a la creación de aplicaciones J2EE, permitiéndonos crear un gran número de componentes Java, como servlets, JSPs, EJBs, servicios web, etc. Para facilitar la tarea de creación de estos componentes, automatizando todo lo posible, utiliza APIs propietarias de Oracle.
Podemos trabajar directamente en vista de diseño, utilizar distintos patrones de diseño para desarrollar las aplicaciones web, etc. Tiene integrado un servidor de aplicaciones propio para probar las aplicaciones en modo local, y nos permite establecer conexiones a BDs y a servidores de aplicaciones para realizar el despliegue de estas aplicaciones.
Aunque está principalmente dedicado para aplicaciones web con J2EE, también podemos utilizarlo para aplicaciones J2SE. Además también podemos encontrar un plugin para realizar aplicaciones J2ME, permitiéndonos crear MIDlets y suites mediante asistentes, y ejecutar las aplicaciones directamente en emuladores.
Podemos descargar de forma gratuita una versión de prueba de este entorno de la web sin limitaciones.
Websphere Studio Device Developer
Se trata de un entorno de IBM basado en Eclipse, por lo que tiene una interfaz similar. Este entorno esta dedicado a la programación de aplicaciones para dispositivos móviles. Integra los asistentes necesarios para la creación de los componentes de aplicaciones MIDP, así como las herramientas de desarrollo necesarias y nos permite probar la aplicación directamente en emuladores desde el mismo entorno.
Podemos encontrar en la web una versión de prueba sin limitaciones para descargar.
Codewarrior Wireless Studio
Este es otro entorno bastante utilizado también para el desarrollo de aplicaciones para móviles. Está desarrollado por Metrowerks y se puede encontrar disponible para un gran número de plataformas distintas. Existe una versión de evaluación limitada a 30 días de uso que puede ser encargada desde la web.