<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-2550663013446902023</id><updated>2012-01-27T09:33:55.547-08:00</updated><title type='text'>Guish Movil</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://guish-movil.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2550663013446902023/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://guish-movil.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Guish</name><uri>http://www.blogger.com/profile/05180896173942041876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>12</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-2550663013446902023.post-5319793130762584557</id><published>2010-04-04T08:57:00.000-07:00</published><updated>2010-04-04T09:18:20.767-07:00</updated><title type='text'>Exception at TimerTask.run()java.lang.RuntimeException: pushModalScreen called by a non-event thread</title><content type='html'>Tratando de abrir una ventana de diálogo desde un thread en una aplicación para Blackberry, fallaba con:&lt;br /&gt;Exception at TimerTask.run()java.lang.RuntimeException: pushModalScreen called by a non-event thread&lt;br /&gt;&lt;br /&gt;El código que lo provocaba era:&lt;br /&gt;&lt;blockquote&gt;public class RemindTask extends TimerTask {&lt;br /&gt;        public void run() {&lt;br /&gt;            try {&lt;br /&gt;                currentTime = currentTime - 1;&lt;br /&gt;                System.out.println("currentTime = " + currentTime);&lt;br /&gt;                countdown.setDate(currentTime);&lt;br /&gt;                if (currentTime &lt;= 0) {&lt;br /&gt;                    oneTimer.cancel();&lt;br /&gt;                    Dialog.alert("Countdown completed");&lt;br /&gt;                }&lt;br /&gt;            } catch (Exception e) {&lt;br /&gt;                System.out.println("Exception at TimerTask.run()" + e.toString());&lt;br /&gt;                e.printStackTrace();&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;La solución es incorporar esa acción dentro del thread de Eventos, de esta forma:&lt;br /&gt;&lt;blockquote&gt;public class RemindTask extends TimerTask {&lt;br /&gt;        public void run() {&lt;br /&gt;            try {&lt;br /&gt;                currentTime = currentTime - 1;&lt;br /&gt;                System.out.println("currentTime = " + currentTime);&lt;br /&gt;                countdown.setDate(currentTime);&lt;br /&gt;                if (currentTime &lt;= 0) {&lt;br /&gt;                    oneTimer.cancel();&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;                    UiApplication.getUiApplication().invokeLater(new Runnable() {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;                        public void run() {&lt;/span&gt;&lt;br /&gt;                            Dialog.alert("Countdown completed");           &lt;br /&gt;               &lt;span style="color: rgb(255, 0, 0); font-weight: bold;"&gt;         }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0); font-weight: bold;"&gt;                    });&lt;/span&gt;&lt;br /&gt;                   &lt;br /&gt;                }&lt;br /&gt;            } catch (Exception e) {&lt;br /&gt;                System.out.println("Exception at TimerTask.run()" + e.toString());&lt;br /&gt;                e.printStackTrace();&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;/blockquote&gt;&lt;br /&gt;La solución la obtuve del foro &lt;a href="http://supportforums.blackberry.com/t5/Java-Development/java-lang-RuntimeException-pushModalScreen-called-by-a-non-event/m-p/284430"&gt;java.lang.RuntimeException:pushModalScreen called by a non-event thread&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Tambien se pueden consultar estas referencias&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.blackberry.com/developers/docs/5.0.0api/UI-summary.html"&gt;http://www.blackberry.com/developers/docs/5.0.0api/UI-summary.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.thinkingblackberry.com/archives/182"&gt;http://www.thinkingblackberry.com/archives/182&lt;/a&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2550663013446902023-5319793130762584557?l=guish-movil.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://guish-movil.blogspot.com/feeds/5319793130762584557/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2550663013446902023&amp;postID=5319793130762584557' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2550663013446902023/posts/default/5319793130762584557'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2550663013446902023/posts/default/5319793130762584557'/><link rel='alternate' type='text/html' href='http://guish-movil.blogspot.com/2010/04/exception-at-timertaskrunjavalangruntim.html' title='Exception at TimerTask.run()java.lang.RuntimeException: pushModalScreen called by a non-event thread'/><author><name>Guish</name><uri>http://www.blogger.com/profile/05180896173942041876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2550663013446902023.post-763568531816670298</id><published>2008-04-05T11:44:00.000-07:00</published><updated>2008-04-12T16:55:41.500-07:00</updated><title type='text'>Cómo obtener el código fuente partiendo del jar</title><content type='html'>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.&lt;br /&gt;&lt;br /&gt;Existen varios descompiladores de java, en este ejemplo se utilizará &lt;a href="http://jode.sourceforge.net/"&gt;Jode&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Los pasos para descompilar el bytecode de un jar son:&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;1. Descargar Jode&lt;/span&gt;&lt;br /&gt; Buscar y descargar el archivo     jode-1.1.2-pre1.jar del proyecto&lt;a href="http://sourceforge.net/project/showfiles.php?group_id=3790"&gt; jode en sourceforge&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;2. Determinar las versiones de CLCD y MIDP del jar&lt;/span&gt;&lt;br /&gt; Abrir el archivo .jar con una aplicación que maneje archivos zip.&lt;br /&gt; Dentro del archivo en la carpeta META-INF se encuentra el archivo MANIFEST.MF, extraer y abrirlo con un editor de texto.&lt;br /&gt; Tomar nota de las versiones.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;3. Configurar la variable classpath&lt;/span&gt;&lt;br /&gt;Se debe configurar esta variable para incluir la referencia a las clases que se determinó en el paso 2.&lt;br /&gt; Si está instalado Java Sun Wireless Toolkit y el midlet utiliza CLDC 1.0 y MIDP 2.0 sería por ejemplo:&lt;br /&gt;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&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;4. Ejecutar jode&lt;/span&gt;&lt;br /&gt;Para ejecutar el descompilador se utiliza la sintaxis:&lt;span style="font-family:monospace;"&gt;&lt;br /&gt;&lt;/span&gt;java jode.decompiler.Main --dest srcdir program.jar&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2550663013446902023-763568531816670298?l=guish-movil.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://guish-movil.blogspot.com/feeds/763568531816670298/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2550663013446902023&amp;postID=763568531816670298' title='4 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2550663013446902023/posts/default/763568531816670298'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2550663013446902023/posts/default/763568531816670298'/><link rel='alternate' type='text/html' href='http://guish-movil.blogspot.com/2008/04/cmo-obtener-el-cdigo-fuente-partiendo.html' title='Cómo obtener el código fuente partiendo del jar'/><author><name>Guish</name><uri>http://www.blogger.com/profile/05180896173942041876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2550663013446902023.post-1491980137551137196</id><published>2008-03-18T13:01:00.000-07:00</published><updated>2008-03-18T13:23:39.727-07:00</updated><title type='text'>Problema con backCommand en Netbeans Mobility Pack</title><content type='html'>Una de las funcionalidades más interesante de esta herramienta es el editor visual del flujo.&lt;br /&gt;&lt;br /&gt;Permite rápidamente manejar el cambio de pantallas y la navegación.&lt;br /&gt;&lt;br /&gt;Sin embargo los comandos "Back" agregados con este método tienen un comportamiento que puede no ser el deseado.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;Al ejecutar un comando "Back" se llama a switchToPreviousDisplayable(), el cual recupera para la pantalla actual cual fue la anterior.&lt;br /&gt;El problema es que cuando ejecuta switchToPreviousDisplayable() también escribe en la HashTable de manera que queda switcheando en forma permanente entre dos pantallas.&lt;br /&gt;&lt;br /&gt;Es decir&lt;br /&gt;1) Se ingresa a la pantalla A&lt;br /&gt;2) Se ingresa a la pantalla B&lt;br /&gt;3) Se ingresa a la pantalla C&lt;br /&gt;4) Se presiona back y se regresa a la pantalla B&lt;br /&gt;5) Se presiona back y se direcciona a la pantalla C de nuevo!&lt;br /&gt;&lt;br /&gt;De esta forma el flujo no vuelve a la pantalla A y si se presiona Back queda alternando siempre entre B y C.&lt;br /&gt;&lt;br /&gt;En muchos casos sería preferible que al presionar back sucesivamente llevara a todas las pantallas recorridas en la forma explicada al final de &lt;a href="http://guish-movil.blogspot.com/2008/03/uso-de-la-clase-javautilstack.html"&gt;Uso de la clase java.util.Stack&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Lamentablemente tanto el código de switchToPreviousDisplayable() como switchDisplayable() no se puede modificar desde el editor.&lt;br /&gt;&lt;br /&gt;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() .&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;  public void switchDisplayable(Alert alert, Displayable nextDisplayable) {&lt;br /&gt;      // write pre-switch user code here&lt;br /&gt;      Displayable onePrevious = null;&lt;br /&gt;      Displayable twoPrevious = null;&lt;br /&gt;      try {&lt;br /&gt;          Displayable current = getDisplay().getCurrent();&lt;br /&gt;          onePrevious = (Displayable)__previousDisplayables.get(current);&lt;br /&gt;          twoPrevious = (Displayable)__previousDisplayables.get(onePrevious);&lt;br /&gt;      } catch(Exception e) {&lt;br /&gt;        &lt;br /&gt;      }&lt;br /&gt;    &lt;br /&gt;      Display display = getDisplay();&lt;br /&gt;      Displayable __currentDisplayable = display.getCurrent();&lt;br /&gt;      if (__currentDisplayable != null  &amp;amp;&amp;amp;  nextDisplayable != null) {&lt;br /&gt;          __previousDisplayables.put(nextDisplayable, __currentDisplayable);&lt;br /&gt;      }&lt;br /&gt;      if (alert == null) {&lt;br /&gt;          display.setCurrent(nextDisplayable);&lt;br /&gt;      } else {&lt;br /&gt;          display.setCurrent(alert, nextDisplayable);&lt;br /&gt;      }&lt;br /&gt;      // write post-switch user code here&lt;br /&gt;      if (onePrevious != null) {&lt;br /&gt;          if (nextDisplayable == onePrevious) {&lt;br /&gt;              if (twoPrevious != null) {&lt;br /&gt;                  __previousDisplayables.put(nextDisplayable, twoPrevious);&lt;br /&gt;              }&lt;br /&gt;          }&lt;br /&gt;      }&lt;br /&gt;  }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Lo que hace es antes de salir del procedimiento "restaurar" la referencia original si es que se está volviendo a una pantalla anterior.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;Otra solución sería encapsular todo el código de este método en un if (1==2) y reescribirlo a gusto.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2550663013446902023-1491980137551137196?l=guish-movil.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://guish-movil.blogspot.com/feeds/1491980137551137196/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2550663013446902023&amp;postID=1491980137551137196' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2550663013446902023/posts/default/1491980137551137196'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2550663013446902023/posts/default/1491980137551137196'/><link rel='alternate' type='text/html' href='http://guish-movil.blogspot.com/2008/03/problema-con-backcommand-en-netbeans.html' title='Problema con backCommand en Netbeans Mobility Pack'/><author><name>Guish</name><uri>http://www.blogger.com/profile/05180896173942041876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2550663013446902023.post-5027989078662523889</id><published>2008-03-18T12:40:00.000-07:00</published><updated>2008-03-18T13:01:40.232-07:00</updated><title type='text'>Problema con ChoiceGroup en Netbeans Mobility Pack</title><content type='html'>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.&lt;br /&gt;Cuando agregamos elementos a un ChoiceGroup se genera el siguiente código&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;    public ChoiceGroup getCgToAccount() {&lt;br /&gt;        if (cgToAccount == null) {&lt;br /&gt;            // write pre-init user code here&lt;br /&gt;            cgToAccount = new ChoiceGroup("To Account", Choice.POPUP);&lt;br /&gt;            cgToAccount.append("Choice Element 1", null);&lt;br /&gt;            cgToAccount.append("Choice Element 2", null);&lt;br /&gt;            cgToAccount.setFitPolicy(Choice.TEXT_WRAP_DEFAULT);&lt;br /&gt;            cgToAccount.setSelectedFlags(new boolean[] { false, false });&lt;br /&gt;            cgToAccount.setFont(0, null);&lt;br /&gt;            cgToAccount.setFont(1, null);&lt;br /&gt;            // write post-init user code here&lt;br /&gt;        }&lt;br /&gt;        return cgToAccount;&lt;br /&gt;    }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Si más tarde debemos modificar la lista de valores con el método &lt;code&gt;append(value, null)&lt;/code&gt;, la aplicación falla mostrando :&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;java.lang.ArrayIndexOutOfBoundsException&lt;br /&gt;        at javax.microedition.lcdui.ChoiceGroup.insertImpl(ChoiceGroup.java:1377)&lt;br /&gt;        at javax.microedition.lcdui.ChoiceGroup.append(+25)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;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: &lt;a href="http://forum.java.sun.com/thread.jspa?threadID=5235145&amp;messageID=9963384"&gt;CLDC and MIDP - Problem in changing List control's font&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;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.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2550663013446902023-5027989078662523889?l=guish-movil.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://guish-movil.blogspot.com/feeds/5027989078662523889/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2550663013446902023&amp;postID=5027989078662523889' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2550663013446902023/posts/default/5027989078662523889'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2550663013446902023/posts/default/5027989078662523889'/><link rel='alternate' type='text/html' href='http://guish-movil.blogspot.com/2008/03/problema-con-choicegroup-en-netbeans.html' title='Problema con ChoiceGroup en Netbeans Mobility Pack'/><author><name>Guish</name><uri>http://www.blogger.com/profile/05180896173942041876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2550663013446902023.post-674207672105423400</id><published>2008-03-15T17:10:00.000-07:00</published><updated>2008-03-15T17:43:03.836-07:00</updated><title type='text'>Netbeans + Mobility Pack</title><content type='html'>Después de haber practicado un poco con Sun Java Wireless Toolkit, decidí buscar un reemplazo para el bloc de notas como editor.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;Buscaba un editor que me permita diseñar las pantallas y formularios más rápido y/o más comodamente.&lt;br /&gt;&lt;br /&gt;Me impresionó su editor visual que permite no solo manejar la interfaz si no también el flujo de la aplicación.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_cyaTo-JKoJQ/R9xrTmafBuI/AAAAAAAAAAk/dyd7JBQsCEQ/s1600-h/netbeans_mobility.PNG"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp3.blogger.com/_cyaTo-JKoJQ/R9xrTmafBuI/AAAAAAAAAAk/dyd7JBQsCEQ/s320/netbeans_mobility.PNG" alt="" id="BLOGGER_PHOTO_ID_5178131656042546914" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Otras funciones interesantes son:&lt;br /&gt;- Agrega automáticamente las cláusulas "import" con el botón derecho.&lt;br /&gt;- 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.&lt;br /&gt;&lt;br /&gt;Acostumbrado a trabajar con otro tipo de herramientas quede sorprendido por este IDE.&lt;br /&gt;&lt;br /&gt;Dejo el link a una presentación para ver lo cómodo que resulta:&lt;br /&gt;&lt;a href="http://www.netbeans.org/kb/60/mobility/vmd-and-ws-screencast.html"&gt;Visual Mobile Designer and Web Services in NetBeans IDE 6.0&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2550663013446902023-674207672105423400?l=guish-movil.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://guish-movil.blogspot.com/feeds/674207672105423400/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2550663013446902023&amp;postID=674207672105423400' title='1 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2550663013446902023/posts/default/674207672105423400'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2550663013446902023/posts/default/674207672105423400'/><link rel='alternate' type='text/html' href='http://guish-movil.blogspot.com/2008/03/netbeans-mobility-pack.html' title='Netbeans + Mobility Pack'/><author><name>Guish</name><uri>http://www.blogger.com/profile/05180896173942041876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp3.blogger.com/_cyaTo-JKoJQ/R9xrTmafBuI/AAAAAAAAAAk/dyd7JBQsCEQ/s72-c/netbeans_mobility.PNG' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2550663013446902023.post-6959869017611580226</id><published>2008-03-13T13:10:00.000-07:00</published><updated>2008-03-13T13:35:19.004-07:00</updated><title type='text'>Simular un celular con Firefox</title><content type='html'>Muchos sitios tienen un sistema de detección del navegador para mostar el contenido para PCs o celulares según desde donde se acceda. Caso típico es Google, Gmail, etc.&lt;br /&gt;&lt;br /&gt;Esto se consigue examinando la "User Agent String" que una identificación que pasa el navegador al servidor del sitio web.&lt;br /&gt;&lt;br /&gt;Así por ejemplo la de mi Firefox es:&lt;br /&gt;Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3&lt;br /&gt;&lt;br /&gt;La de InternetExplorer puede ser:&lt;br /&gt;Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; InfoPath.1; FDM)&lt;br /&gt;&lt;br /&gt;Mediante esta identificación un sitio puede mostrar características compatibles con tal o cual navegador o puede proveer un versión más reducida para la navegación por celular, etc.&lt;br /&gt;&lt;br /&gt;A veces necesitamos o queremos navegar un sitio desde la PC para acceder al contenido para celulares, por ejemplo para descargar Google Maps para móviles en la PC.&lt;br /&gt;&lt;br /&gt;En esos casos podemos cambiar el user agent string de Firefox para que pretenda ser un teléfono celular.&lt;br /&gt;&lt;br /&gt;Lo primero es obtener un UAS de un teléfono. La del Sony Ericsson w580 es:&lt;br /&gt;SonyEricssonW580i/R6BC Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1&lt;br /&gt;&lt;br /&gt;Para averiguar la cadena de un navegador se puede ingresar a:&lt;br /&gt;&lt;a href="http://www.tarkasys.com/ua/ua.php"&gt;http://www.tarkasys.com/ua/ua.php&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;En ese enlace se muestra solamente la cadena del navegador con el cual accedimos. Si ingresamos a esa página desde el celular nos dirá su cadena.&lt;br /&gt;&lt;br /&gt;Luego en la barra de direcciones de Firefox tenemos que tipear about:config que abre una lista de preferencias.&lt;br /&gt;&lt;br /&gt;Hacer click con el botón derecho en la lista, seleccionar "New", "String" e  ingresar "&lt;img src="file:///C:/DOCUME%7E1/Luis/LOCALS%7E1/Temp/moz-screenshot.jpg" alt="" /&gt;general.useragent.override" como nombre de la preferencia y el User Agent String que queramos en el valor.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_cyaTo-JKoJQ/R9mPoWafBsI/AAAAAAAAAAU/T--w_5h6-qo/s1600-h/2.PNG"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp3.blogger.com/_cyaTo-JKoJQ/R9mPoWafBsI/AAAAAAAAAAU/T--w_5h6-qo/s320/2.PNG" alt="" id="BLOGGER_PHOTO_ID_5177327170013300418" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Con esto convertimos a Firefox en un celular y podemos acceder al contenido móvil como este:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_cyaTo-JKoJQ/R9mP5mafBtI/AAAAAAAAAAc/LA-BSb2R3YQ/s1600-h/1.PNG"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp0.blogger.com/_cyaTo-JKoJQ/R9mP5mafBtI/AAAAAAAAAAc/LA-BSb2R3YQ/s320/1.PNG" alt="" id="BLOGGER_PHOTO_ID_5177327466366043858" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2550663013446902023-6959869017611580226?l=guish-movil.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://guish-movil.blogspot.com/feeds/6959869017611580226/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2550663013446902023&amp;postID=6959869017611580226' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2550663013446902023/posts/default/6959869017611580226'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2550663013446902023/posts/default/6959869017611580226'/><link rel='alternate' type='text/html' href='http://guish-movil.blogspot.com/2008/03/simular-un-celular-con-firefox.html' title='Simular un celular con Firefox'/><author><name>Guish</name><uri>http://www.blogger.com/profile/05180896173942041876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp3.blogger.com/_cyaTo-JKoJQ/R9mPoWafBsI/AAAAAAAAAAU/T--w_5h6-qo/s72-c/2.PNG' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2550663013446902023.post-1583043151649158713</id><published>2008-03-12T11:57:00.000-07:00</published><updated>2008-03-12T13:29:23.609-07:00</updated><title type='text'>Leer y escribir archivos en J2ME</title><content type='html'>En muchos casos se necesita leer y escribir archivos a las unidades de almacenamiento del teléfono. Uno de los escenarios posibles es la exportación e importación de datos.&lt;br /&gt;&lt;br /&gt;En esta nota voy a mostrar breves ejemplos de como realizar estas tareas utilizando la API FileConnection.&lt;br /&gt;&lt;br /&gt;La clase FileConnection forma parte de los paquetes opcionales a J2ME. Por ese motivo al crear un nuevo proyecto en Sun Wireless Toolkit, al momento de elegir la API, debemos marcar:&lt;br /&gt;Target Platform = JTWI y tildar PDA Profile for J2ME (JSR 75)&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_cyaTo-JKoJQ/R9gvZGafBrI/AAAAAAAAAAM/5hPrgOYVj5M/s1600-h/select_sr_75.PNG"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp1.blogger.com/_cyaTo-JKoJQ/R9gvZGafBrI/AAAAAAAAAAM/5hPrgOYVj5M/s320/select_sr_75.PNG" alt="" id="BLOGGER_PHOTO_ID_5176939879927318194" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Hay que destacar que al ser una especificación optativa puede no estar presente en todos los teléfonos o dispositivos. En general todos los teléfonos actuales lo soportan, pero no es así para los modelos viejos.&lt;br /&gt;&lt;br /&gt;En el emulador el sistema de archivos "virtual" se encuentra en la carpeta "..j2mewtk\2.5.2\appdb\DefaultColorPhone\filesystem\".&lt;br /&gt;&lt;br /&gt;Dentro de esta carpeta podemos encontrar otra llamada root1. Cada carpeta en "filesystem" es tomada como una unidad o root por el emulador. En el télefono cada root corresponderá a un dispositivo de almacenamiento diferente, en la mayoría de los casos uno será la memoria interna del teléfono y otro la tarjeta de memoria.&lt;br /&gt;&lt;br /&gt;El primer ejemplo trata de como listar todos los roots disponibles. Esto se logra utilizando la clase FileSystemRegistry:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;public void SelectRoot() {&lt;br /&gt;Enumeration rootListEnum = &lt;span style="font-weight: bold;"&gt;FileSystemRegistry.listRoots()&lt;/span&gt;;&lt;br /&gt;listRoots = new List("Elija el root:", Choice.EXCLUSIVE);&lt;br /&gt;while (rootListEnum.hasMoreElements()) {&lt;br /&gt; String rootName = (String) rootListEnum.nextElement();&lt;br /&gt; listRoots.append(rootName, null);&lt;br /&gt;}&lt;br /&gt;...&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Este fragmento utiliza la función listRoots() que devuelve una lista de los roots y luego la carga en un control de lista para mostrarla en la pantalla.&lt;br /&gt;&lt;br /&gt;Para listar el contenido de un directorio:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;Display.getDisplay(this).setCurrent(WaitForm);&lt;br /&gt;  Thread t = new Thread() {&lt;br /&gt;    public void run() {&lt;br /&gt;      try{&lt;br /&gt;&lt;br /&gt;        &lt;span style="font-weight: bold;"&gt;FileConnection myFc = (FileConnection)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;                               Connector.open("file:///" + currentRoot);&lt;/span&gt;&lt;br /&gt;        Enumeration fileEnum = &lt;span style="font-weight: bold;"&gt;myFc.list("*", false);&lt;/span&gt;&lt;br /&gt;        while(fileEnum.hasMoreElements()) {&lt;br /&gt;          String fileName = (String) fileEnum.nextElement();&lt;br /&gt;          listContents.append(fileName, null);&lt;br /&gt;        }&lt;br /&gt;      } catch (Throwable th) {&lt;br /&gt;        System.out.println(th.toString());&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;  };&lt;br /&gt;  t.start();&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Las tres primeras líneas son obligatorias cuando estemos utilizando un CommandListener por lo expuesto en &lt;a href="http://guish-movil.blogspot.com/2008/03/acceso-archivos-y-threads.html"&gt;Acceso a archivos y threads&lt;/a&gt;, su finalidad es evitar que la aplicación se cuelgue si hay un problema en las operaciones de manejo de archivos.&lt;br /&gt;&lt;br /&gt;En lo demás este caso es similar al de listado de roots, utilizando el método "list".&lt;br /&gt;&lt;br /&gt;Finalmente para escribir un archivo debemos utlizar además un Data Stream:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt; Thread t = new Thread() {&lt;br /&gt;   public void run() {&lt;br /&gt;     try{&lt;br /&gt;    &lt;br /&gt;       &lt;span style="font-weight: bold;"&gt;FileConnection conn = (FileConnection) Connector.open(writeFile, Connector.READ_WRITE);&lt;/span&gt;&lt;br /&gt;       if (&lt;span style="font-weight: bold;"&gt;!conn.exists()&lt;/span&gt;) {&lt;br /&gt;         &lt;span style="font-weight: bold;"&gt;conn.create()&lt;/span&gt;;&lt;br /&gt;       }&lt;br /&gt;       OutputStream outSt = &lt;span style="font-weight: bold;"&gt;conn.openOutputStream()&lt;/span&gt;;&lt;br /&gt;       PrintStream printSt = &lt;span style="font-weight: bold;"&gt;new PrintStream(outSt)&lt;/span&gt;;&lt;br /&gt;       &lt;span style="font-weight: bold;"&gt;printSt.println(writeContents);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;        conn.close();&lt;/span&gt;&lt;br /&gt;   &lt;br /&gt;     } catch(IOException e) {&lt;br /&gt;       System.out.println("IOException in WriteToFile: " + e.toString());&lt;br /&gt;     } catch(SecurityException e) {&lt;br /&gt;       System.out.println("SecurityException in WriteToFile: " + e.toString());&lt;br /&gt;     }&lt;br /&gt;   }&lt;br /&gt; };&lt;br /&gt; t.start();&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;La referencia de este paquete opcional se encuentra en:&lt;br /&gt;&lt;a href="http://jcp.org/aboutJava/communityprocess/final/jsr075/"&gt;JSR-000075 PDA Optional Packages for the J2METM Platform&lt;/a&gt;. Ahí puede descargarse las especificaciones de FileConnection con todas sus clases y métodos.&lt;br /&gt;Y una serie de artículos sobre esto en:&lt;br /&gt;&lt;a href="http://java.sun.com/javame/technology/msa/jsr75.jsp"&gt;Mobile Service Architecture - JSR 75&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;El código completo de esta clase ejemplo es:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;import javax.microedition.midlet.MIDlet;&lt;br /&gt;import javax.microedition.io.file.*;&lt;br /&gt;import java.io.*;&lt;br /&gt;import java.util.*;&lt;br /&gt;import javax.microedition.io.*;&lt;br /&gt;import javax.microedition.lcdui.*;&lt;br /&gt;&lt;br /&gt;public class FileDemo extends MIDlet implements CommandListener {&lt;br /&gt;List listRoots, listContents;&lt;br /&gt;private String currentRoot, currentPath, writeFile, writeContents;&lt;br /&gt;private Command cmOK,cmExit, cmNew;&lt;br /&gt;private Form WaitForm;&lt;br /&gt;&lt;br /&gt;public void FileDemo() {&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public void startApp() {&lt;br /&gt;WaitForm = new Form("Espere por favor...");&lt;br /&gt;WaitForm.setCommandListener(this);&lt;br /&gt;cmExit = new Command("Exit", Command.EXIT, 1);&lt;br /&gt;cmNew = new Command("New", Command.ITEM,2);&lt;br /&gt;SelectRoot();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public void pauseApp() {&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public void destroyApp(boolean condition) {&lt;br /&gt;notifyDestroyed();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public void SelectRoot() {&lt;br /&gt;Enumeration rootListEnum = FileSystemRegistry.listRoots();&lt;br /&gt;listRoots = new List("Elija el root:", Choice.EXCLUSIVE);&lt;br /&gt;while (rootListEnum.hasMoreElements()) {&lt;br /&gt;  String rootName = (String) rootListEnum.nextElement();&lt;br /&gt;  listRoots.append(rootName, null);&lt;br /&gt;}&lt;br /&gt;cmOK = new Command("OK", Command.ITEM, 1);&lt;br /&gt;&lt;br /&gt;listRoots.addCommand(cmOK);&lt;br /&gt;listRoots.addCommand(cmExit);&lt;br /&gt;listRoots.setCommandListener(this);&lt;br /&gt;Display.getDisplay(this).setCurrent(listRoots);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public void ShowContents() {&lt;br /&gt;listContents = new List("Contenidos de " + currentRoot, Choice.EXCLUSIVE);&lt;br /&gt;Display.getDisplay(this).setCurrent(WaitForm);&lt;br /&gt;  Thread t = new Thread() {&lt;br /&gt;    public void run() {&lt;br /&gt;      try{&lt;br /&gt;&lt;br /&gt;        FileConnection myFc = (FileConnection)&lt;br /&gt;                              Connector.open("file:///" + currentRoot);&lt;br /&gt;        Enumeration fileEnum = myFc.list("*", false);&lt;br /&gt;        while(fileEnum.hasMoreElements()) {&lt;br /&gt;          String fileName = (String) fileEnum.nextElement();&lt;br /&gt;          listContents.append(fileName, null);&lt;br /&gt;        }&lt;br /&gt;      } catch (Throwable th) {&lt;br /&gt;        System.out.println(th.toString());&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;  };&lt;br /&gt;  t.start();&lt;br /&gt;listContents.addCommand(cmExit);&lt;br /&gt;listContents.addCommand(cmNew);&lt;br /&gt;listContents.setCommandListener(this);&lt;br /&gt;Display.getDisplay(this).setCurrent(listContents);&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public void WriteToFile(String fileName, String contents) {&lt;br /&gt;writeFile = fileName;&lt;br /&gt;writeContents = contents;&lt;br /&gt;&lt;br /&gt;Thread t = new Thread() {&lt;br /&gt;  public void run() {&lt;br /&gt;    try{&lt;br /&gt;  &lt;br /&gt;      FileConnection conn = (FileConnection) Connector.open(writeFile, Connector.READ_WRITE);&lt;br /&gt;      if (!conn.exists()) {&lt;br /&gt;        conn.create();&lt;br /&gt;      }&lt;br /&gt;      OutputStream outSt = conn.openOutputStream();&lt;br /&gt;      PrintStream printSt = new PrintStream(outSt);&lt;br /&gt;      printSt.println(writeContents);&lt;br /&gt;      conn.close();&lt;br /&gt; &lt;br /&gt;    } catch(IOException e) {&lt;br /&gt;      System.out.println("IOException in WriteToFile: " + e.toString());&lt;br /&gt;    } catch(SecurityException e) {&lt;br /&gt;      System.out.println("SecurityException in WriteToFile: " + e.toString());&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;};&lt;br /&gt;t.start();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public void commandAction(Command cm, Displayable d) {&lt;br /&gt;//System.out.println("En commandAction");&lt;br /&gt;if (cm == cmOK &amp;amp;&amp;amp; d == listRoots) {&lt;br /&gt;  System.out.println("Elegiste: " + listRoots.getString(listRoots.getSelectedIndex()));&lt;br /&gt;  currentRoot = listRoots.getString(listRoots.getSelectedIndex());&lt;br /&gt;  ShowContents();&lt;br /&gt;} else if (cm == cmExit) {&lt;br /&gt;  destroyApp(false);&lt;br /&gt;} else if (cm == cmNew) {&lt;br /&gt;  WriteToFile("file:///" + currentRoot + "newfile.txt","Sample, sample, sample");&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2550663013446902023-1583043151649158713?l=guish-movil.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://guish-movil.blogspot.com/feeds/1583043151649158713/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2550663013446902023&amp;postID=1583043151649158713' title='16 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2550663013446902023/posts/default/1583043151649158713'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2550663013446902023/posts/default/1583043151649158713'/><link rel='alternate' type='text/html' href='http://guish-movil.blogspot.com/2008/03/leer-y-escribir-archivos-en-j2me.html' title='Leer y escribir archivos en J2ME'/><author><name>Guish</name><uri>http://www.blogger.com/profile/05180896173942041876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp1.blogger.com/_cyaTo-JKoJQ/R9gvZGafBrI/AAAAAAAAAAM/5hPrgOYVj5M/s72-c/select_sr_75.PNG' height='72' width='72'/><thr:total>16</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2550663013446902023.post-6843825235634093128</id><published>2008-03-11T21:43:00.000-07:00</published><updated>2008-04-12T11:38:11.077-07:00</updated><title type='text'>Acceso a archivos y threads</title><content type='html'>Corriendo un &lt;a href="http://www.java2s.com/Code/Java/J2ME/FileConnection.htm"&gt;ejemplo de escritura&lt;/a&gt; de archivos en Sun Java Wireless Toolkit sucedía que la aplicación se colgaba al momento de abrir el archivo.&lt;br /&gt;&lt;br /&gt;En la consola se mostraba este mensaje:&lt;br /&gt;&lt;cite&gt;Warning: To avoid potential deadlock, operations that may block, such as&lt;br /&gt;networking, should be performed in a different thread than the&lt;br /&gt;commandAction() handler.&lt;/cite&gt;&lt;br /&gt;&lt;br /&gt;El mismo problema aparecía en el ejemplo de lectura de un directorio que estaba escribiendo. En ambos casos la aplicación se colgaba al llamar a Connector.open.&lt;br /&gt;&lt;br /&gt;La advertencia en cuestión quedaría traducida a:&lt;br /&gt;"Para evitar posibles puntos muertos, las operaciones que pueden bloquear, como conexiones de red, deben ser ejecutadas en un hilo (thread) diferente que el administrador de commandAction()"&lt;br /&gt;&lt;br /&gt;El "commandAction() handler" sería la clase que especificamos para manejar la interacción con el usuario mediante el método setCommandListener.&lt;br /&gt;&lt;br /&gt;Como un conexión de red o un acceso a un archivo puede dejar inutilizable la interfaz  de usuario, debe correrse en un thread separado.&lt;br /&gt;&lt;br /&gt;Una muy buena explicación de esto puede encontrarse en:&lt;br /&gt;&lt;a href="http://developers.sun.com/mobility/midp/articles/threading/"&gt;Networking, User Experience, and Threads&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;En cuanto a la solución de este error en particular fue cambiar este código:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public void ShowContents() {&lt;br /&gt;listContents = new List("Contenidos de " + currentRoot, Choice.EXCLUSIVE);&lt;br /&gt;&lt;br /&gt;     try{&lt;br /&gt;&lt;br /&gt;       FileConnection myFc = (FileConnection)&lt;br /&gt;                             Connector.open("file:///" + currentRoot);&lt;br /&gt;       Enumeration fileEnum = myFc.list("*", false);&lt;br /&gt;       while(fileEnum.hasMoreElements()) {&lt;br /&gt;         String fileName = (String) fileEnum.nextElement();&lt;br /&gt;         listContents.append(fileName, null);&lt;br /&gt;       }&lt;br /&gt;     } catch (Throwable th) {&lt;br /&gt;       System.out.println(th.toString());&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;listContents.addCommand(cmExit);&lt;br /&gt;listContents.setCommandListener(this);&lt;br /&gt;Display.getDisplay(this).setCurrent(listContents);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Por este:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public void ShowContents() {&lt;br /&gt;listContents = new List("Contenidos de " + currentRoot, Choice.EXCLUSIVE);&lt;br /&gt;Display.getDisplay(this).setCurrent(WaitForm);&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;      Thread t = new Thread() {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;        public void run() {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;          try{&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;       FileConnection myFc = (FileConnection)&lt;br /&gt;                             Connector.open("file:///" + currentRoot);&lt;br /&gt;       Enumeration fileEnum = myFc.list("*", false);&lt;br /&gt;       while(fileEnum.hasMoreElements()) {&lt;br /&gt;         String fileName = (String) fileEnum.nextElement();&lt;br /&gt;         listContents.append(fileName, null);&lt;br /&gt;       }&lt;br /&gt;     } catch (Throwable th) {&lt;br /&gt;       System.out.println(th.toString());&lt;br /&gt;     }&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;        }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;      }; &lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;      t.start();&lt;/span&gt;&lt;br /&gt;listContents.addCommand(cmExit);&lt;br /&gt;listContents.setCommandListener(this);&lt;br /&gt;Display.getDisplay(this).setCurrent(listContents);&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;De acuerdo a lo explicado en el artículo citado.&lt;br /&gt;&lt;br /&gt;Para ver un ejemplo de como listar roots y escribir archivos ir a:&lt;br /&gt;&lt;a href="http://guish-movil.blogspot.com/2008/03/leer-y-escribir-archivos-en-j2me.html"&gt;Leer y escribir archivos en J2ME&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2550663013446902023-6843825235634093128?l=guish-movil.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://guish-movil.blogspot.com/feeds/6843825235634093128/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2550663013446902023&amp;postID=6843825235634093128' title='4 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2550663013446902023/posts/default/6843825235634093128'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2550663013446902023/posts/default/6843825235634093128'/><link rel='alternate' type='text/html' href='http://guish-movil.blogspot.com/2008/03/acceso-archivos-y-threads.html' title='Acceso a archivos y threads'/><author><name>Guish</name><uri>http://www.blogger.com/profile/05180896173942041876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2550663013446902023.post-7748144749854607973</id><published>2008-03-11T08:57:00.000-07:00</published><updated>2008-05-06T20:29:45.079-07:00</updated><title type='text'>Uso de la clase java.util.Stack en flujo de aplicaciones J2ME</title><content type='html'>Una pila (stack en inglés) es una estructura de datos de tipo LIFO (del inglés Last In First Out, último en entrar, primero en salir) que permite almacenar y recuperar datos. Se aplica en multitud de ocasiones en informática debido a su simplicidad y ordenación implícita en la propia estructura.&lt;br /&gt;&lt;br /&gt;Para el manejo de los datos se cuenta con dos operaciones básicas: apilar (push), que coloca un objeto en la pila, y su operación inversa, retirar (o desapilar, pop), que retira el último elemento apilado. Ver &lt;a href="http://es.wikipedia.org/wiki/Pila_%28estructura_de_datos%29"&gt;Pila (estructura de datos) en Wikipedia&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Java provee una implementación de esta estructura de datos en la clase java.util.Stack que cuenta con los métodos empty, peek, pop, push y search.&lt;br /&gt;&lt;br /&gt;Push: agrega un elemento a la pila.&lt;br /&gt;Pop: recupera el último elemento y lo elimina.&lt;br /&gt;Peek: recupera el último elemento sin eliminarlo de la pila.&lt;br /&gt;&lt;br /&gt;Un ejemplo de utilización de esta clase puede ser para almacenar el flujo de una aplicación J2ME como se ve en este ejemplo adaptado del código de &lt;a href="http://cash2me.sourceforge.net/"&gt;Cash2ME:&lt;/a&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package net.sf.cash2me;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;import java.util.Stack;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;import javax.microedition.lcdui.Displayable;&lt;br /&gt;import javax.microedition.midlet.MIDlet;&lt;br /&gt;import javax.microedition.midlet.MIDletStateChangeException;&lt;br /&gt;&lt;br /&gt;public class Cash2ME extends MIDlet {&lt;br /&gt;&lt;br /&gt;private Displayable currentScreen; &lt;span style="color: rgb(0, 153, 0);"&gt;// La pantalla actual&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;    private Stack screenStack;&lt;/span&gt;       &lt;span style="color: rgb(0, 153, 0);"&gt;// contiene todas las pantallas previas&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt; /**&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;  * Recibe un objeto Displayable y lo configura como Current de Display, es decir&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;  * lo muestra en la pantalla.&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;  * @param screen El objeto Displayable a mostrar.&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;  */&lt;/span&gt;&lt;br /&gt;private void setCurrent(Displayable screen) {&lt;br /&gt;   if (currentScreen == null || screen != currentScreen) {&lt;br /&gt;       if (screenStack == null)&lt;br /&gt;           screenStack = new Stack();&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;            screenStack.push(currentScreen);&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0);"&gt;//almacena la pantalla actual en la pila.&lt;/span&gt;&lt;br /&gt;       currentScreen = screen;   &lt;br /&gt;   }&lt;br /&gt;   Display.getDisplay(this).setCurrent(currentScreen);&lt;span style="color: rgb(0, 153, 0);"&gt; //muestra la pantalla recibida&lt;/span&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt; /**&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;  * Muestra la pantalla anterior.&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;  */&lt;/span&gt;&lt;br /&gt;public void showPrevious() {&lt;br /&gt;   if (screenStack != null) {&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;        /*Controla si hay más de una pantalla en la pila*/&lt;/span&gt;&lt;br /&gt;       Displayable screen = screenStack.size() &gt; 1&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;            /*Si hay más de una pantalla en la pila recupera la última y la elimina de la pila.*/&lt;/span&gt;&lt;br /&gt;           ? &lt;span style="font-weight: bold;"&gt;(Displayable)screenStack.pop()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;            /* Si queda solo una, utiliza el método peek para recuperar la última pantalla&lt;br /&gt;           sin borrarla de la pila.*/  &lt;/span&gt;&lt;br /&gt;           : &lt;span style="font-weight: bold;"&gt;(Displayable)screenStack.peek()&lt;/span&gt;;&lt;br /&gt;       if (screen != null)&lt;br /&gt;           Display.getDisplay(this).setCurrent(currentScreen = screen);&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;En este ejemplo en lugar de recurrir directamente al método Display.setCurrent se recurre a estos métodos para llevar un "historial" de las pantallas recorridas. De esta forma cada vez que a lo largo de la aplicación se muestra una pantalla nueva, primero se guarda la pantalla actual en la pila y luego se muestra la nueva.&lt;br /&gt;&lt;br /&gt;Cuando la aplicación necesita volver a la pantalla anterior, recupera la última pantalla, que estará arriba de la pila, la muestra y la elimina, usando el método pop.&lt;br /&gt;&lt;br /&gt;Si se llega al final de la pila, quedando una sola pantalla en la pila, se utiliza el método peek para recuperar dicha pantalla sin eliminarla.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Más Información&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;Otro ejemplo de pilas en java: &lt;a href="http://www.javacoffeebreak.com/faq/faq0037.html"&gt;How do I use stacks in Java?&lt;/a&gt;&lt;br /&gt;Referencia de la clase Stack: &lt;a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/Stack.html"&gt;Class Stack&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2550663013446902023-7748144749854607973?l=guish-movil.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://guish-movil.blogspot.com/feeds/7748144749854607973/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2550663013446902023&amp;postID=7748144749854607973' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2550663013446902023/posts/default/7748144749854607973'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2550663013446902023/posts/default/7748144749854607973'/><link rel='alternate' type='text/html' href='http://guish-movil.blogspot.com/2008/03/uso-de-la-clase-javautilstack.html' title='Uso de la clase java.util.Stack en flujo de aplicaciones J2ME'/><author><name>Guish</name><uri>http://www.blogger.com/profile/05180896173942041876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2550663013446902023.post-3029991973379074862</id><published>2008-03-08T16:48:00.000-08:00</published><updated>2008-03-10T17:12:14.512-07:00</updated><title type='text'>Tutoriales y Links utiles para comenzar con J2ME</title><content type='html'>Tutoriales en java.net&lt;br /&gt;&lt;a href="http://today.java.net/pub/a/today/2005/02/09/j2me1.html"&gt;J2ME Tutorial, Part 1: Creating MIDlets&lt;/a&gt;&lt;br /&gt;&lt;a href="http://today.java.net/pub/a/today/2005/05/03/midletUI.html"&gt;J2ME Tutorial, Part 2: User Interfaces with MIDP 2.0&lt;/a&gt;&lt;br /&gt;&lt;a href="http://today.java.net/pub/a/today/2005/07/07/j2me3.html"&gt;J2ME Tutorial, Part 3: Exploring the Game API of MIDP 2.0&lt;/a&gt;&lt;br /&gt;&lt;a href="http://today.java.net/pub/a/today/2005/09/27/j2me4.html"&gt;J2ME Tutorial, Part 4: Multimedia and MIDP 2.0&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://java.sun.com/javame/reference/apis/jsr118/javax/microedition/lcdui/package-summary.html"&gt;&lt;/a&gt;Tutoriales en TechRepublic&lt;br /&gt;&lt;span class="articleTipText"&gt;&lt;a href="http://builder.com.com/article.jhtml?id=u00320020524adm01.htm"&gt;Making sense of the J2ME alphabet soup&lt;/a&gt;&lt;br /&gt;&lt;a href="http://builder.com.com/article.jhtml?id=u00220020610adm01.htm"&gt;Getting wireless with J2ME MIDP development&lt;/a&gt;&lt;br /&gt;&lt;a href="http://builder.com.com/article.jhtml?id=u00220020702adm01.htm"&gt;Building and testing J2ME MIDP applications with the Wireless Toolkit&lt;/a&gt;&lt;br /&gt;&lt;a href="http://builder.com.com/article.jhtml?id=u00220500704adm01.htm"&gt;Exploring J2ME: Building an expense tracker&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;a href="http://builder.com.com/article.jhtml?id=u00220020726adm01.htm"&gt;Exploring J2ME: Building an expense detail form&lt;/a&gt;&lt;br /&gt;&lt;a href="http://builder.com.com/article.jhtml?id=u00320020820adm01.htm"&gt;Exploring J2ME: Using the Record Management System&lt;/a&gt;&lt;br /&gt;&lt;a href="http://builder.com.com/article.jhtml?id=u00220020819adm01.htm"&gt;Exploring J2ME: Sorting records&lt;/a&gt;&lt;br /&gt;&lt;a href="http://articles.techrepublic.com.com/5100-22-1049454.html?tag=rbxccnbtr1"&gt;Exploring J2ME: Being a good mobile citizen&lt;/a&gt;&lt;br /&gt;&lt;a href="http://articles.techrepublic.com.com/5100-22-1050336.html"&gt;Exploring J2ME: Communication with the GCF&lt;/a&gt;&lt;br /&gt;&lt;span&gt;&lt;span class="articleTipText"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;Databases and MIDP en Sun Developer Network&lt;br /&gt;&lt;a href="http://developers.sun.com/mobility/midp/articles/databaserms/"&gt;Part 1: Understanding the Record Management System&lt;/a&gt;&lt;br /&gt;&lt;a href="http://developers.sun.com/mobility/midp/articles/databasemap/"&gt;Part 2: Data Mapping&lt;/a&gt;&lt;br /&gt;&lt;a href="http://developers.sun.com/mobility/midp/articles/databasemapextend/"&gt;Part 3: Putting Data Mapping to Work&lt;/a&gt;&lt;br /&gt;&lt;b&gt;             &lt;a href="http://onesearch.sun.com/search/clickthru?qt=Databases+and+MIDP&amp;amp;url=http%3A%2F%2Fdevelopers.sun.com%2Fmobility%2Fmidp%2Farticles%2Fdatabasefilter%2Findex.html&amp;amp;pathInfo=%2Fsearch%2Fonesearch%2Findex.jsp&amp;amp;hitNum=2&amp;amp;col=developer-reference"&gt;                                      &lt;b class="highlight"&gt;&lt;/b&gt;&lt;/a&gt;&lt;/b&gt;&lt;a href="http://onesearch.sun.com/search/clickthru?qt=Databases+and+MIDP&amp;amp;url=http%3A%2F%2Fdevelopers.sun.com%2Fmobility%2Fmidp%2Farticles%2Fdatabasefilter%2Findex.html&amp;amp;pathInfo=%2Fsearch%2Fonesearch%2Findex.jsp&amp;amp;hitNum=2&amp;amp;col=developer-reference"&gt;Part 4: Filtering &lt;span class="highlight"&gt;and&lt;/span&gt; Traversal Strategies&lt;/a&gt;&lt;br /&gt;&lt;b&gt;             &lt;a href="http://onesearch.sun.com/search/clickthru?qt=Databases+and+MIDP&amp;amp;url=http%3A%2F%2Fdevelopers.sun.com%2Fmobility%2Fmidp%2Farticles%2Fdatabaserecordstore%2Findex.html&amp;amp;pathInfo=%2Fsearch%2Fonesearch%2Findex.jsp&amp;amp;hitNum=1&amp;amp;col=developer-reference"&gt;                                      &lt;b class="highlight"&gt;&lt;/b&gt;&lt;/a&gt;&lt;/b&gt;&lt;a href="http://onesearch.sun.com/search/clickthru?qt=Databases+and+MIDP&amp;amp;url=http%3A%2F%2Fdevelopers.sun.com%2Fmobility%2Fmidp%2Farticles%2Fdatabaserecordstore%2Findex.html&amp;amp;pathInfo=%2Fsearch%2Fonesearch%2Findex.jsp&amp;amp;hitNum=1&amp;amp;col=developer-reference"&gt;Part 5: Searching a Record Store&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Referencia&lt;br /&gt;&lt;a href="http://java.sun.com/javame/reference/apis/jsr118"&gt;Mobile Information Device Profile Reference&lt;/a&gt;&lt;br /&gt;&lt;a href="http://en.wikibooks.org/wiki/Java_Programming"&gt;Wikibooks - Java Programming&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2550663013446902023-3029991973379074862?l=guish-movil.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://guish-movil.blogspot.com/feeds/3029991973379074862/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2550663013446902023&amp;postID=3029991973379074862' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2550663013446902023/posts/default/3029991973379074862'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2550663013446902023/posts/default/3029991973379074862'/><link rel='alternate' type='text/html' href='http://guish-movil.blogspot.com/2008/03/tutoriales-y-links-utiles-para-comenzar.html' title='Tutoriales y Links utiles para comenzar con J2ME'/><author><name>Guish</name><uri>http://www.blogger.com/profile/05180896173942041876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2550663013446902023.post-1412616940328277734</id><published>2008-01-30T15:11:00.000-08:00</published><updated>2008-01-30T15:50:22.806-08:00</updated><title type='text'>Como llevar el diario en el celular</title><content type='html'>Una de las funciones más interesantes del W580i es que puede navegar cualquier página html, sin que sea necesariamente una especial para celulares.&lt;br /&gt;&lt;br /&gt;Esto lo consigue adaptando la página web al tamaño de la pantalla, reordenando el texto y cambiando el tamaño de las imágenes.&lt;br /&gt;&lt;br /&gt;El problema es que las páginas web normales tienen un "peso" mucho mayor y puede resultar en una factura de teléfono bastante pesada.&lt;br /&gt;&lt;br /&gt;Cómo navegar offline&lt;br /&gt;Para poder bajarse todo un sitio puede usarse WinHTTrack Website Copier. Luego esa carpeta copiarla al teléfono en la carpeta "Web Saved Pages".&lt;br /&gt;&lt;br /&gt;Cómo obtener una copia del sitio más facil de navegar&lt;br /&gt;Algunos sitios tienen muchos graficos y tardan mucho en cargase en el navegador. Hay varios servicios que, combinados con HTTrack, permiten llevar un copia más "liviana" de un sitio web en el celular.&lt;br /&gt;www.mowser.com&lt;br /&gt;www.skweezer.net&lt;br /&gt;www.google.com/gwt/n&lt;br /&gt;www.baresite.com&lt;br /&gt;&lt;br /&gt;Estos sitios implementan lo que se llama &lt;a href="http://wapreview.com/blog/wp-mobile.php?p=26&amp;amp;page=1"&gt;Mobile Transcoding&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2550663013446902023-1412616940328277734?l=guish-movil.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://guish-movil.blogspot.com/feeds/1412616940328277734/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2550663013446902023&amp;postID=1412616940328277734' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2550663013446902023/posts/default/1412616940328277734'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2550663013446902023/posts/default/1412616940328277734'/><link rel='alternate' type='text/html' href='http://guish-movil.blogspot.com/2008/01/como-llevar-el-diario-en-el-celular.html' title='Como llevar el diario en el celular'/><author><name>Guish</name><uri>http://www.blogger.com/profile/05180896173942041876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2550663013446902023.post-243260899059494091</id><published>2007-12-28T11:57:00.000-08:00</published><updated>2008-03-11T22:08:20.179-07:00</updated><title type='text'>Tips para el tutorial de J2ME</title><content type='html'>Siguiendo el tutorial de :&lt;br /&gt;&lt;h2 class="r"&gt;&lt;span style="font-size:100%;"&gt;&lt;a href="http://java.net/pub/a/today/2005/02/09/j2me1.html" class="l" onmousedown="return clk(this.href,'','','res','1','')"&gt;java.net: &lt;b&gt;J2ME Tutorial&lt;/b&gt;, &lt;b&gt;Part 1&lt;/b&gt;: &lt;b&gt;Creating  MIDlets&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;&lt;/h2&gt;..se me presentaron dos problemas:&lt;br /&gt;&lt;br /&gt;1. Al momento de compilar fallaba con "package javax.microedition.midlet does not exist". Lo solucioné agregando el directorio bin de la JDK a la variable de entorno PATH de XP.&lt;br /&gt;("C:\Program Files\Java\jdk1.6.0_03\bin" en mi PC)&lt;br /&gt;&lt;br /&gt;2. Al momento de correrlo en el emulador fallaba con "ALERT: java/lang/ClassFormatError: Bad version information."&lt;br /&gt;La solucion la encontré en&lt;br /&gt;&lt;a href="http://forum.java.sun.com/thread.jspa?threadID=569449&amp;amp;messageID=4126314"&gt;Sun Java Wireless Toolkit - running the first Midlet&lt;/a&gt;&lt;br /&gt;Consiste en compilar la clase con las siguientes opciones:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;C:\WTK2.5.2\article&gt;javac -target 1.4 -source 1.4 -bootclasspath ..\lib\cldcapi11.jar;..\lib\midpapi20.jar com\j2me\part1\DateTimeApp.java&lt;/span&gt;&lt;br /&gt;Y continuar el proceso.&lt;br /&gt;Como resultado el JAR podia correr en el emulador pero fallaba en el telefono, al repetir los pasos con Wireless toolkit generó un JAR que era aceptado por el telefono.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2550663013446902023-243260899059494091?l=guish-movil.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://guish-movil.blogspot.com/feeds/243260899059494091/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2550663013446902023&amp;postID=243260899059494091' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2550663013446902023/posts/default/243260899059494091'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2550663013446902023/posts/default/243260899059494091'/><link rel='alternate' type='text/html' href='http://guish-movil.blogspot.com/2007/12/tips-para-el-tutorial-de-j2me.html' title='Tips para el tutorial de J2ME'/><author><name>Guish</name><uri>http://www.blogger.com/profile/05180896173942041876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
