Teniendo un midlet en forma de archivo .jar se puede obtener el código fuente mediante un descompilador. Este proceso analiza bytecode y convierte los archivos .class a .java.
Existen varios descompiladores de java, en este ejemplo se utilizará Jode.
Los pasos para descompilar el bytecode de un jar son:
1. Descargar Jode
Buscar y descargar el archivo jode-1.1.2-pre1.jar del proyecto jode en sourceforge.
2. Determinar las versiones de CLCD y MIDP del jar
Abrir el archivo .jar con una aplicación que maneje archivos zip.
Dentro del archivo en la carpeta META-INF se encuentra el archivo MANIFEST.MF, extraer y abrirlo con un editor de texto.
Tomar nota de las versiones.
3. Configurar la variable classpath
Se debe configurar esta variable para incluir la referencia a las clases que se determinó en el paso 2.
Si está instalado Java Sun Wireless Toolkit y el midlet utiliza CLDC 1.0 y MIDP 2.0 sería por ejemplo:
set CLASSPATH=C:\Documents and Settings\Luis\My Documents\jode-1.1.2-pre1.jar;C:\WTK2.5.2\lib\cldapi10.jar;C:\WTK2.5.2\lib\midpapi20.jar
4. Ejecutar jode
Para ejecutar el descompilador se utiliza la sintaxis:
java jode.decompiler.Main --dest srcdir program.jar
Esto dejará el código fuente original en el directorio srcdir. Cuando el midlet recurra a algún paquete opcional se debe incluir también en el classpath.
Este instructivo debería ser suficiente para las aplicaciones más sencillas, en algunos casos estos pasos no logran recontruir el código fuente completo.
sábado, 5 de abril de 2008
Cómo obtener el código fuente partiendo del jar
martes, 18 de marzo de 2008
Problema con backCommand en Netbeans Mobility Pack
Una de las funcionalidades más interesante de esta herramienta es el editor visual del flujo.
Permite rápidamente manejar el cambio de pantallas y la navegación.
Sin embargo los comandos "Back" agregados con este método tienen un comportamiento que puede no ser el deseado.
Cada vez que se cambia de pantalla, el midlet guarda la pantalla a la que se va a acceder y la que se está dejando en una HashTable.
Al ejecutar un comando "Back" se llama a switchToPreviousDisplayable(), el cual recupera para la pantalla actual cual fue la anterior.
El problema es que cuando ejecuta switchToPreviousDisplayable() también escribe en la HashTable de manera que queda switcheando en forma permanente entre dos pantallas.
Es decir
1) Se ingresa a la pantalla A
2) Se ingresa a la pantalla B
3) Se ingresa a la pantalla C
4) Se presiona back y se regresa a la pantalla B
5) Se presiona back y se direcciona a la pantalla C de nuevo!
De esta forma el flujo no vuelve a la pantalla A y si se presiona Back queda alternando siempre entre B y C.
En muchos casos sería preferible que al presionar back sucesivamente llevara a todas las pantallas recorridas en la forma explicada al final de Uso de la clase java.util.Stack
Lamentablemente tanto el código de switchToPreviousDisplayable() como switchDisplayable() no se puede modificar desde el editor.
La mejor solución sería cambiar el comportamiento de NetBeans para que genere otro código. Y la solución más rápida sin perder la funcionalidad del editor de flujo es sobreescribir la HashTable para que no considere los cambios hechos por switchToPreviousDisplayable() .
public void switchDisplayable(Alert alert, Displayable nextDisplayable) {
// write pre-switch user code here
Displayable onePrevious = null;
Displayable twoPrevious = null;
try {
Displayable current = getDisplay().getCurrent();
onePrevious = (Displayable)__previousDisplayables.get(current);
twoPrevious = (Displayable)__previousDisplayables.get(onePrevious);
} catch(Exception e) {
}
Display display = getDisplay();
Displayable __currentDisplayable = display.getCurrent();
if (__currentDisplayable != null && nextDisplayable != null) {
__previousDisplayables.put(nextDisplayable, __currentDisplayable);
}
if (alert == null) {
display.setCurrent(nextDisplayable);
} else {
display.setCurrent(alert, nextDisplayable);
}
// write post-switch user code here
if (onePrevious != null) {
if (nextDisplayable == onePrevious) {
if (twoPrevious != null) {
__previousDisplayables.put(nextDisplayable, twoPrevious);
}
}
}
}
Lo que hace es antes de salir del procedimiento "restaurar" la referencia original si es que se está volviendo a una pantalla anterior.Notese que en realidad no captura el comando "Back" si no que lo deduce cuando la pantalla a la que se va a acceder coincide con la previa. Esto puede no aplicar en el caso en que se acceda a una misma pantalla más de una vez en un mismo flujo de navegación.
Otra solución sería encapsular todo el código de este método en un if (1==2) y reescribirlo a gusto.
Problema con ChoiceGroup en Netbeans Mobility Pack
Me topé con un inconveniente al usar Netbeans Mobility Pack. La causa es el código que genera cuando creamos una lista en el editor visual de pantallas.
Cuando agregamos elementos a un ChoiceGroup se genera el siguiente código
public ChoiceGroup getCgToAccount() {
if (cgToAccount == null) {
// write pre-init user code here
cgToAccount = new ChoiceGroup("To Account", Choice.POPUP);
cgToAccount.append("Choice Element 1", null);
cgToAccount.append("Choice Element 2", null);
cgToAccount.setFitPolicy(Choice.TEXT_WRAP_DEFAULT);
cgToAccount.setSelectedFlags(new boolean[] { false, false });
cgToAccount.setFont(0, null);
cgToAccount.setFont(1, null);
// write post-init user code here
}
return cgToAccount;
}
Si más tarde debemos modificar la lista de valores con el método
append(value, null)
, la aplicación falla mostrando :
java.lang.ArrayIndexOutOfBoundsException
at javax.microedition.lcdui.ChoiceGroup.insertImpl(ChoiceGroup.java:1377)
at javax.microedition.lcdui.ChoiceGroup.append(+25)
Esto aparentemente sería un bug de Java, el cual al llamar a .setFont de alguna forma "congela" el tamaño de la lista y no pueden agregarse nuevos elementos sin recibir el error. Hay un tema en el foro de SDN que explica este bug en detalle: CLDC and MIDP - Problem in changing List control's font.
Por suerte el problema no se presenta si no existe una llamada a .setFont así es que para el caso de NetBeans la solución es borrar todos los elementos del ChoiceGroup y agregarlos por código. Esto por supuesto en el caso de que necesitemos modificarlos durante la ejecución.
sábado, 15 de marzo de 2008
Netbeans + Mobility Pack
Después de haber practicado un poco con Sun Java Wireless Toolkit, decidí buscar un reemplazo para el bloc de notas como editor.
Las opciones de IDE más mencionadas en la web para desarrollar en J2ME son Netbeans y Eclipse. Después de revisar varios foros decidí comenzar con Netbeans y su Mobility Pack.
Buscaba un editor que me permita diseñar las pantallas y formularios más rápido y/o más comodamente.
Me impresionó su editor visual que permite no solo manejar la interfaz si no también el flujo de la aplicación.
Permite crear los formularios, asignarles comandos, y acciones a esos comandos. Con todo lo diseñado va creando el código del midlet dejando protegidas las líneas generadas y dejando zonas libres para insertar el código propio. De esta forma libera en gran medida del trabajo repetitivo.
Otras funciones interesantes son:
- Agrega automáticamente las cláusulas "import" con el botón derecho.
- Permite renombrar y mover de paquetes a clases, métodos, etc. con la opción de "Refactoring", que cambia el nombre en todas las partes del código donde existan referencias.
Acostumbrado a trabajar con otro tipo de herramientas quede sorprendido por este IDE.
Dejo el link a una presentación para ver lo cómodo que resulta:
Visual Mobile Designer and Web Services in NetBeans IDE 6.0