Professional Documents
Culture Documents
Configurations
Configuración es una especificación que cubre una gama de equipos con características similares,
en ella se define las clases mínimas que esos equipos pueden usar. Define los requerimientos del
VM (Virtual Machine: intérprete de java) y de las clases principales. Para J2ME CLDC y CDC. Sun
ha desarrollado KVM y CVM para CLDC y CDC respectivamente, CLDC es la que nos interesa a
nosotros. El Nokia 6600 posee una nueva version de VM (intérprete de Java) que hace que
muchos de los programas que funcionan en versiones anteriores de Series 60 no funcionen en
este modelo.
CLDC
Connected Limited Device Configuration que cubre las necesidades de pequeños aparatos con
limitadas posibilidades en cuanto a interfaz de usuario, poder de proceso, etc etc.
• java.lang.*
• java.io.*
• java.util.*
• java.microedition.io.*
Importante: El verificador de J2SE es demasiado grande para ser incluido con el CLDC, de hecho
es mas grande que el KVM, por lo cual debemos verificar los archivos antes de mandarlos al
equipo donde queremos que se ejecuten. Para esta tarea, los SDKs poseen herramientas que nos
ayudaran en su proceso y no será necesario realizarlo manualmente.
Profiles
Un perfil es una especificación de las APIs de java, que funciona en conjunción de la capa de
configuración. Añaden nuevas clases a las que venían con la configuración.
Hay muchos perfiles, pero los mas importantes en referencia a J2ME son Personal Profile,
Foundation Profile y MID Profile.
MIDP
El ciclo de vida de un MIDP esta muy bien definido ya que ayuda al MIDlet a coexistir con otros
programas en el MIDP. Las fases del ciclo de vida son:
• Retrieval
• Installation
• Launching
• Version Management
• Removal
Retreival
El teléfono consigue la aplicación desde la fuente, puede ser vía IRDA, Bluetooth o Internet. En
este momento el MIDlet y MID establecen una comunicación para intercambiar información sobre
el sistema y la aplicación y decidir así si se procede a instalarlo o no.
Installation
Launching
El usuario ejecuta la aplicación. En esta fase, el MIDlet se ejecuta en la KVM y los métodos de
ciclos de vida del MIDlet son ejecutados.
Version management
El teléfono mantiene una base de datos sobre que programas han sido instalados y su versión.
Así, usando la descripción (descriptor) del MIDlet puede ser actualizado si aparece una nueva
versión
Renoval
Hay muchos conceptos básicos que serian importantes conocer para familiarizarse con los MIDlets,
como son el ciclo de vida, interfaz de usuario, instalación, timers, redes, etc.
• startApp()
o método setCurrent() debería ser llamado aquí si no fue llamado antes.
setCurrent() define que display será visible al usuario, solo un display puede ser
visible al mismo tiempo.
o Puede ser ejecutado mas de una vez, así que es mejor no poner ninguna
inicialización aquí
• pauseApp()
o cuando una aplicación es reactivada, puede aparecer con otro display usando el
método setCurrent()
• destroyApp()
o libera y destruye todos los recursos usados por la aplicaciones, incluidos los
componentes del interfaz de usuario
Aplicación mínima
import javax.microedition.midlet.*;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class HelloMIDlet extends MIDlet implements CommandListener {
private Command exitCommand;
private Display display;
public HelloMIDlet() {
display = Display.getDisplay(this);
exitCommand = new Command("Exit", Command.SCREEN, 1);
}
display.setCurrent(t);
}
notifyDestroyed();
}
}
}
Interfaz de Usuario
Antes de empezar a desarrollar nuestro interfaz de usuario, hay ciertos conceptos que se hacen
necesarios para poder adaptarnos más rápidamente a su desarrollo. A partir de este momento me
referiré a “Interfaz de usuario” como UI. Para una referencia mejor a los métodos de cada
componente es necesario mirar la especificación de J2ME, que viene generalmente con el SDK, o
en java.sun.com.
Respecto a los programas que se encuentran en las diferentes partes del tutorial, algunos han sido
recopilados de varios libros, siendo imposible ahora saber de donde vienen exactamente, otros sin
embargo, son de desarrollo personal.
El UI de MIDP tiene APIs de alto nivel y de bajo nivel. Las clases de la API de alto nivel, como
Alert, Form, List… son extensiones de la clase abstracta Screen. La API de bajo nivel se basa en la
clase abstracta Canvas.
La API de alto nivel presenta clases que permite un alto grado de portabilidad entre los diferentes
aparatos que soportan J2ME. La API de bajo nivel permite una manipulación más directa y por
ello, mayor control del UI, ya que implementa varios eventos de la pulsación de las teclas y/o
pantalla táctil. En este caso se pueden producir errores de portabilidad si los aparatos no tienen
las mismas teclas, por ejemplo.
Display
Una aplicación puede tener un cierto número de displays, pero solo uno de ellos puede ser visible.
En cualquier caso es muy fácil cambiar el display que se esta mostrando con el comando:
Display.getDisplay(this).setCurrent(nombre_de_Display);
La clase Display implementa la Displayable y con los métodos getDisplay() para saber que display
esta en pantalla en ese momento y setCurrent() para cambiar el Display.
• Genérico (Form) donde se pueden poner diferentes clases de alto nivel, texto, imágenes…
• Un componente de alto nivel ocupa toda el display (List, TextBox…)
• Bajo nivel display, subclase de la clase Canvas
Comandos
Toda interacción entre el usuario y el programa se realiza a través de los comandos. Estos
funcionan de forma parecida que J2SE., mediante un CommandListener que recibe el comando y
la pantalla de donde viene. Para implementar un comando se usa el método addCommand().
Ejemplo:
myDisplay.addCommand(OK_CMD);
List
Una lista de opciones. Es posible añadir, insertar en medio o borrar opciones. Las opciones pueden
poseer texto y/o una imagen.
TextBox
Un TextBox que ocupa toda la pantalla, que puede incluir también un titulo. El textbox puede
tener las siguientes restricciones:
Form
Form es un display que se usa como base de una serie de elementos. Los elementos anteriores
ocupan toda la pantalla del teléfono, sin embargo, usando la clase Form, podemos tener diferentes
elementos, estos pueden ser:
Alerts
• ALERT
• CONFIRMATION
• ERROR
• INFO
• WARNING
Timers
Ejemplos
Canvas
Para realizar un juego o una aplicación con cierta movilidad, no podemos usar los componentes
antes mencionados. Para ello haremos uso del Canvas. Canvas posee un submetodo paint() que
es llamado cuando el Canvas tiene que ser dibujado.
También posee los métodos getHeigh() y getWidth() para saber el tamaño del canvas y poder
adaptar nuestras aplicación a distintos teléfonos.
Algo muy común al empezar el método paint() es limpiar la pantalla para no dibujar sobre el
anterior grafico, el siguiente código produce el efecto deseado, si el fondo es blanco:
g.setGrayScale (255);
g.fillRect (0, 0, getWidth (), getHeight ());
g.setGrayScale (0);
Nokia posee una versión especial, llamada FullCanvas que ocupa toda la pantalla, mientras que
Canvas, deja la barra de titulo y otras partes de la aplicación visibles.
Además de paint(), canvas posee otros métodos, como getGameAction(int keyCode) que registra
el uso de las teclas por parte del usuario. Otros métodos que canvas facilita al programador
cuando suceden ciertos eventos son:
En el método paint, la clase Graphics proporciona los siguientes métodos para dibujar:
Coordenadas
El sistema de coordenadas no apunta a un pixel en concreto, sino al espacio entre dos pixels, por
este motivo, un rectángulo es un pixel mas alto y ancho que un rectángulo relleno.
El punto 0,0 se refiere a la esquina superior izquierda, entonces los números negativos indican
hacia arriba e izquierda. Un buen ejemplo es el ClipCanvas
Font
En canvas no es posible escribir, en este caso hay que ”dibujar” el texto. Los métodos más
importantes son:
• drawstring()
• createFont()
• setFont()
Simple animación
Canvas permite realizar animaciones sincronizando la aplicación para que repinte el canvas usando
serviceRepaints() o callSerially(Runnable)
Canvas.callSerially() hace que se llame el método run() y puede ser utilizada desde diferentes
threads
Ejemplos de canvas
MID no permite el acceso a ficheros, ni por lo tanto, crear archivos nuevos. Como hacer entonces
para guardar la lista de mejores puntuaciones en un juego? Facil, usando la API rms, en
javax.microedition.rms.
ID Informacion
1 Info
2 Info
... ...
Esta base de datos solo puede ser usada por nuestra aplicación, solo puede ser compartida con
otras aplicaciones, si estas, se encuentran empaquetadas en el mismo MIDlet suite, o lo que es lo
mismo, en el mismo .jar (java archive file).
Así que, como saber si han sido borrados registros sin llevar un control en otra base de datos?
Muy fácil, usando la clase RecordEnumeration que veremos mas adelante.
RecordStore
Esta clase proporciona una forma para crear o abrir el registro de datos mediante
openRecordStore(). Tambien facilita otros metodos, como closeRecordStore() o
deleteRecordStore(), para cerrar y borrar respectivamente. Nota: no se puede borrar un
RecordStore si se esta usando, o lo que es lo mismo, hay que cerrarlo para borrarlo.
• getVersion()
• getLastModified()
• getSizeAvailable()
• getSize()
• listRecordStores()
Como muchos otros componentes, RecordStore posee un listener para saber cuando se ha
modificado (RecordListener) usando los métodos:
• addRecordListener()
• removeRecordListener()
RecordFilter
Permite realizar una búsqueda usando nuestro propio criterio de búsqueda usando el método
matches().
RecordComparator
RecordEnumerator
Muy útil ya que facilita como una segunda base de datos totalmente secuencial a partir de nuestro
RecordStore original, pudiendo así hacer un for loop y por ejemplo, mostrar todos los registros. A
continuación, un ejemplo:
try {
System.out.println("Numero de registros: " + recStore.getNumRecords());
if (recStore.getNumRecords() > 0) {
RecordEnumeration re = recStore.enumerateRecords(null, null, false);
while (re.hasNextElement()) {
String str = new String(re.nextRecord());
Ejemplo:
Este ejemplo hace uso del RMS, es un pequeño memorando. Permite registrar texto, con distinto
tipo de letra, y luego muestra todos los registros en un canvas. Como el canvas no tiene barras de
desplazamiento, solo muestra aquellas que caben.
J2ME y redes
MIDP presenta una implementación del protocolo HTTP, que puede ser usada para realizar
conexiones a internet y redes usando TCP/IP y protocolos que no usan IP, como WAP o I-mode
usando un gateway que facilita su acceso a servidores http.
El uso de sockets y datagrams, hace que nuestra aplicación sea menos portable ya que no todas
redes y teléfonos hace uso de ellos, así que es especialmente recomendable evitar su uso. XML y
PHP pueden ser usados para encapsular información y acceder a ella usando HTTP request.
Generis Connecition Framework hace uso de la clase Connector para abrir o crear una conexión a
Internet:
o) HTTP
Connection hc = Connector.open("http://www.todosymbian.com")
o) Socket:
Connection sc = Connector.open("socket://localhost:9000")
o) Datagram
o) Puerto Serie:
Connection cc = Connector.open("comm:0;baudrate=9000")
o) Fichero I/O:
Connection fc = Connector.open("file:/archivo.dat")
Como se ha indicado antes, MIDP 1.0 solo implementa el protocolo HTTP. Ademas, SDKs como el
the SUN no permiten el uso de los otros tipos de comunicación. Para cambiar esta opcion, hay que
crear una variable de ambiente: ENABLE_CLDC_PROTOCOLS=INTUITIVE_TOOLKIT
No he probado todavía si esto es todavía asi en el nuevo SDK que soporta MIDP 2.0
HttpConnection
Una vez creada una conexión a HTTP, esta puede tener 3 estados:
• Setup
o La conexión todavía no ha sido realizada
o Llama a los metodos setRequestMethod() (POST, GET o HEAD) y
setRequestProperty()
• Connected
o La conexión se ha realizado con éxito y se espera una respuesta.
o El cambio de estado Setup a Connected se puede producir debido a cualquiera de
estos métodos
openInputStream()
openDataInputStream()
openOutputStream()
openDataOutputStream()
oetLength()
oetType()
oetEncoding()
getDate()
getExpiration()
getLastModified()
getHeaderField()
getHeaderFieldKey()
getResponseCode()
getResponseMessage()
getHeaderFieldInt()
getHeaderFieldDate()
• Closed
o La conexion se ha cerrado, si se produce el uso de cualquier método, IOException
dará un error.
Los siguientes metodos se pueden usar en cualquiera de los tres estados
• close()
• getRequestMethod()
• getRequestProperty()
• getURL()
• getProtocol()
• getHost()
• getFile()
• getRef()
• getPort()
• getQuery()
Metodos de peticion
Hemos dicho que los métodos de petición pueden ser GET, HEAD y POST.
o) POST enviá información a Internet, normalmente a un programa CGI, de hecho GET también
puede ser usado para mandar información en variables insertadas en la URL, en cambio POST
enviá la información en forma de un stream.
Ejemplos
Los ejemplos anteriores muestran como realizar GET, HEAD y POST peticiones, es posible que sea
necesario cambiar las URLs usadas, pero deberían dar al lector una ayuda de cómo usar estas
peticiones.
Otros ejemplos:
o) SendMail: manda un email a través de un servidor de email. Se necesita las APIs Java Mail que
pueden ser bajadas de SUN web site.
Otras tecnologías
Además de usar J2ME, podemos usar otros lenguajes combinándolos con J2ME. Aquí simplemente
veremos un par de ejemplos de cómo combinar J2ME con PHP y con J2SE.
SERVlet es un programa que corre en un servidor. Básicamente es como un programa CGI pero en
Java. Para hacer que un SERVlet funcione en el servidor, necesitarás instalar un programa, por
ejemplo, si el servidor es un Apache, en su Web tiene un programa llamado Tomcat. Pero eso es
otra historia.
En el apartado de redes, hemos visto que con el método GET se pueden mandar variables
insertadas en la URL. Esta es la forma que el SERVlet usa para recibir información, y luego enviá
una respuesta al MIDlet.
Como ejemplo, el programa que enviá un email en la parte de redes, lo tenemos ahora en versión
SERVlet. El MIDlet enviá el cuerpo del mensaje y email al SERVlet, y este se encarga de contactar
con el servidor de email
o) SendMail
PHP
Exactamente lo mismo pasa con PHP, podemos usar el método GET y enviar información para
hacer algo en el programa PHP.
Ejemplos
o) GetPHP hace uso de GET para obtener una respuesta del programa PHP.
o) GetImage, envía datos binarios, como una imagen, o un PDF y si el telefono puede ver este tipo
de datos, lo abrirá.
Nokia APIs
Nokia ha desarrollado unas APIs especiales, que por supuesto solo funcionan en sus propios
teléfonos. Estas APIs incluyen soporte para gráficos y sonido, entre otras cosas. Aquí veremos
rápidamente las características mas importantes de las APIs.
• com.nokia.mid.ui
o DeviceControl: vibracion y luz
o DirectUtils: graficos
o FullCanvas
o DirectGraphics
• com.nokia.mid.sound.Sound
Clase Sound
• Tone-base (FORMAT_TONE)
tono.setGain(255);
tono.play(1);
La clase Sound viene con un listener para saber cuando ha cambiado el estado del audio, si ha
dejado de tocar, ha empezado, etc.
tono.setSoundListener(this);
FullCanvas
Un canvas que ocupa toda la pantalla. En este canvas no es posible implementar comandos. Así
que es necesario tratar los comandos como teclas normales usando los eventos keyPressed() o
keyReleased(). commandAction() no se usa.
DirectGraphics
Es una extensión de MIDP UI Graphics, que incluyes metodos extras para dibujar poligonos y rotar
imágenes. Tambien soporta los colores ARGB (Alpha Channel) para hacer transparente una
imagen, por ejemplo.
SMS APIs
Para MIDP 1.0, las APIs de Nokia para SMS solo funcionan en las Series 30. Ahora MIDP 2.0
implementa un listener para SMS recibidos y unas nuevas APIs. Desafortunadamente no las he
probado nunca, así que no se funcionan o no en otros teléfonos, por ejemplo, Series 60.
Cualquier pregunta que tengas, publicala en el foro, ya que así, además de responderte a tí,
responderé a todos los demás usuarios que estén interesados en el tema.
Autor:
Juan de Miguel Hernández
chili_fi