Práctica 4: J2ME/JavaME

IMPORTANTE: esta práctica es OPTATIVA. Ver al final del enunciado el baremo de puntuación.

ACLARACIÓN: J2ME es el antiguo nombre de JavaME, lo veréis todavía referenciado así en muchos libros y artículos (aparte de en esta página :) ).

En esta práctica implementaremos una aplicación J2ME que nos permita capturar imágenes con la cámara del móvil y subirlas directamente a una nueva entrada del blog realizado en prácticas anteriores.

Documentación

Como en clase se ha visto muy poco sobre J2ME, necesitaréis más información si queréis implementar la práctica. Tened presente que la dificultad de la práctica es que tendréis que aprender J2ME por vosotros mismos. En concreto debéis saber:

Como fuentes de información sobre J2ME en general podéis bajaros los siguientes libros

Software

Para la realización de esta práctica, además del software utilizado en la anterior práctica, deberemos instalar:

Requerimientos

Vamos a realizar una aplicación cliente en J2ME que nos permitirá publicar entradas en el foro, incluyendo como imagen fotografías tomadas con la cámara del móvil. Esta aplicación tendrá un menú principal con las siguientes opciones:

Al pulsar sobre Subir imagen se nos mostrará una pantalla en la que veremos el video capturado por la cámara del móvil. En esta pantalla tendremos dos comandos:

Si se pulsa sobre el comando Cancelar se detendrá el video y se volverá al menú principal. Si se pulsa sobre el comando Capturar foto se nos llevará a una pantalla en la que veremos la imagen capturada y se nos pedirán los datos necesarios para publicar la entrada. Los datos que deberemos introducir son:

En esta pantalla tendremos dos posibles comandos:

NOTA: Al probar la captura de video en un emulador veremos un patrón de rectángulos en movimiento y un contador. En un móvil real si que se vería el video capturado por su cámara.

 

Implementación

Para la implementación de la práctica utilizaremos las librerías CLDC 1.0, MIDP 2.0 y MMAPI. Deberemos especificar estas librerías en el buildpath del proyecto de Eclipse (y eliminar de él la librería del JRE) para que no aparezcan errores de código en el editor.

Captura de la imagen

Podemos capturar una imagen utilizando la API Multimedia (MMAPI) de J2ME. Para ello deberemos crear un reproductor (Player) que utilice como fuente la cámara del móvil (capture://video):

	VideoControl vc;
Player p;

// Crea reproductor
p = Manager.createPlayer("capture://video");
p.realize();

// Crea control de video
vc = (VideoControl)p.getControl("VideoControl");
vc.initDisplayMode(VideoControl.USE_DIRECT_VIDEO, this);
vc.setDisplayLocation(0,0);
vc.setDisplaySize(this.getWidth(), this.getHeight());
vc.setVisible(true);

En este fragmento de código se ha especificado con setDisplaySize que el tamaño del video capturado se ajuste a las dimensiones de la pantalla del móvil.

NOTA: En móviles con pantalla grande se podrían tener problemas de memoria al capturar la imagen. Por ello es recomendable utilizar un emulador como el MediaControlSkin.

Para empezar a reproducir el video capturado de la cámara utilizaremos el método start del reproductor:

	p.start();

Durante la reproducción, podemos capturar el fotograma actual de la siguiente forma:

	byte [] datosImagenPng = vc.getSnapshot(null);

Esto nos devuelve los bytes de la imagen en formato PNG (tal como se almacenaría en un fichero).

NOTA: La captura de la imagen es una operación costosa, por lo que siempre deberemos realizarla desde un hilo para no bloquear el hilo de eventos de la aplicación.

Una vez hayamos capturado la imagen de la cámara, deberemos detener la reproducción. Primero detendremos la reproducción de la fuente de video, y a continuación liberamos los recursos:

	p.stop();
p.deallocate();

Si queremos mostrar la imagen capturada en la interfaz del móvil (antes de enviarla al servidor), deberemos crear un objeto Image a partir de los bytes del PNG:

	Image img = Image.createImage(datos,0,datos.length);

Comunicación cliente-servidor

Para enviar los datos del cliente al servidor utilizaremos el bloque de contenido del mensaje de petición HTTP. En este bloque de contenido escribiremos toda la información necesaria en binario. En el lado del servidor tendremos un JSP que se encargará de leer este bloque de contenido y creará una nueva entrada a partir de los datos leídos.

En el cliente deberemos definir la dirección del servidor a la que subiremos la imagen y el resto de datos de la entrada. Por ejemplo:

	private final static String UPLOAD_URL = "http://localhost:8080/BlogTW/uploadImagen.jsp";

Podemos enviar estos datos al servidor de la siguiente forma:

	HttpConnection con = null;

try {
con = (HttpConnection) Connector.open(UPLOAD_URL);

// Envia datos al servidor
DataOutputStream dos = con.openDataOutputStream();
dos.writeUTF(login);
dos.writeUTF(password);
dos.writeUTF(titulo);
dos.writeUTF(texto);
dos.writeInt(imagen.length);
for(int i=0;i<imagen.length;i++) {
dos.write(imagen[i]);
}

dos.flush();
dos.close();

// Recibe respuesta del servidor
if(con.getResponseCode()!=200) {
throw new IOException("Error en la comunicación con el servidor");
}

} finally {
if(con!=null) {
con.close();
}
}

Por otro lado, el JSP en el servidor puede leer los datos codificados con este formato en el bloque de contenido de la petición de la siguiente forma:

	DataInputStream dis = new DataInputStream(request.getInputStream());

String login = dis.readUTF();
String password = dis.readUTF();
String titulo = dis.readUTF();
String texto = dis.readUTF();

if(<el usuario (login,password) está registrado>) {
int imgSize = dis.readInt();
byte [] imagen = new byte[imgSize];
for(int i=0;i<imagen.length;i++) {
imagen[i] = (byte)dis.read();
}

<Registrar la nueva entrada en la BD>
String filename = application.getRealPath("/imagenes") + File.separator + <nombre imagen> + ".png";
FileOutputStream fos = new FileOutputStream(filename);

for(int i=0;i<imagen.length;i++) {
fos.write(imagen[i]);
}
fos.flush();
fos.close();
}

El método application.getRealPath("/imagenes") obtiene la ruta absoluta en el sistema de ficheros correspondiente al directorio /imagenes relativo al directorio raíz de nuestro sitio web, suponiendo que las imágenes del blog se guarden en un directorio con este nombre. Si tuviese un nombre distinto, se deberá modificar este fragmento de código para especificar el nombre correcto. Si el directorio especificado no existiese, nos daría un error al crear el fichero.

NOTA: Deberemos modificar la aplicación web para que muestre las imágenes PNG (y no las JPEG como hacía anteriormente). Para simplificar podemos asumir que todas las imágenes que se subirán al servidor van a estar en este formato.

Puntuación

Al ser la práctica optativa, se establece un baremo distinto al resto. La práctica se puntuará de 0 a 1 puntos, añadiéndose a la nota media del resto de prácticas (es decir, que si tenéis un 7 de media en las tres primeras prácticas y hacéis esta correctamente, tendréis un 8). La entrega de la práctica se podrá realizar hasta el 11 de febrero a través de la zona restringida de la web del DCCIA.
©2006/2007 Pilar Arques, Otto Colomina,  Javier Montoyo, Miguel Ángel Lozano