Antes de proceder con este artículo, le recomiendo que lea mi artículo anterior “Desarrollando Apps para iOS y Android con FlashDevelop” que le será de utilidad si quiere iniciar a desarrollar aplicaciones para dispositivos móviles con FlashDevelop.

Sobre este artículo

Mi objetivo es ayudarles a crear su primera aplicación AIR Android/iOS completamente funcional gracias a un par de herramientas que he desarrollado y que considero que pueden ser de utilidad para muchos por su sencillez.

Herramientas

  • En esta ocasión usaremos el ya hablado en el artículo anterior FlashDevelop con Flex y AIR.
  • ArbolNegro: Usaremos mi proyecto OpenSource que he movido recientemente a Github; es una serie de paquetes de clases que he desarrollado desde hace varios años, que eliminan ciertas tareas repetitivas al momento de crear programas y aplicaciones con actionscript, como lo son cargar un XML (complicado para principiantes en as3), un tipo muy singular de LiquidLayout, carga de clases externas almacenadas en otros swfs entre otras, que si se presenta la oportunidad las demostraré, pero no es el punto principal de este artículo.
  • BlueMarble: Blue Marble inició como un apéndice de Arbol Negro, pero sus funciones cambiaron drásticamente durante el desarrollo y actualmente lo he separado como proyecto de Arbol Negro y funciona como un Framework, pero sigue siendo dependiente de él. La función principal de Blue Marble es crear un GUI sin preocuparse por ello, semejante a Flex en el hecho de que juntas unos cuantos componentes y ya tienes tu aplicación, pero con las diferencias que es mucho más liviano (mi principal queja de Flex es su peso), está completamente basado en código, no en un markup tipo HTML como Flex, por lo que posiblemente sea todo muy abstracto para quien solo haya hecho de este tipo de aplicaciones, pero lo hice de esta forma para evitar que en el desarrollo se mezcle el código con el markup, una mala práctica (o no dependiendo del desarrollador) a raíz de arreglar cosas de última hora. Será Blue Marble de lo que hablaré principalmente.





Inicializando



Descargamos ArbolNegro y BlueMarble y lo ponemos en nuestro directorio de elección; por costumbre tengo separadas todas las class del proyecto en sí, pero también es recomendable tener la copia con el proyecto por los posibles cambios a futuro de los paquetes que incluyamos. Procedemos a abrir FlashDevelop, y creamos un nuevo proyecto “AIR Mobile AS3 APP”; una vez cargado procedemos a agregar las referencias a nuestras class de ArbolNegro y BlueMarble y cualquiera que usted ya tenga con anterioridad. Para ello nos dirigimos al menú, Tools > Global ClassPaths (Ctrl – F9) Global Classpaths window   Seleccionan as3 en el combobox, presionan Add Classpath y van al directorio donde se encuentra ArbolNegro y BlueMarble; si están por separado hay que agregar ambos directorios. Ambos paquetes empiezan con la carpeta “net/”, la carpeta que debe ser incluida debe ser la que contenga a esa misma carpeta net/ para poder hacer la llamada a las classes desde la raíz, por ejemplo import net.absulit.bluemarble.controls.Button. Una vez agregadas las classes podemos proceder a crear lo básico de la aplicación.

Creando la aplicación

Antes de iniciar, hay unas cuantas cosas que quiero que tengan presentes, una de ellas es que el Framework funciona en su estado actual; puede que se encuentren un bug, pero hasta el momento no me ha impedido publicar 2 aplicaciones en Play Store; otra es que estoy consciente que se puede mejorar, hay  un par de cosas que quiero cambiar y se las mencionaré en el camino; en el momento que las desarrollé me pareció el enfoque más sencillo, y me gusta no complicarme,y por el momento se van a quedar así hasta que planifique una re estructuración; pero nada de lo anterior les va a evitar desarrollar un app super facil y rápido. Profundizando un poco más sobre BlueMarble y su estructura, este tiene una interfaz mínima, transparencias y lineas monocromáticas; también su estructura funcional se basa en tomar ideas de proyectos ya existentes, como lo es Flex y su concepto de ventanas que me parece muy atinado, al igual que su navegación; y por otro lado el concepto de States de Flixl (que también usa Starling) en el que un “mundo” es una class aparte, y para entrar en ese nuevo mundo, llamamos a la Class de forma dinámica sin almacenar todo en memoria. Así cada ventana de BlueMarble es un “Mundo Nuevo” donde programamos aparte del resto del sistema y con una comunicación sencilla entre ventanas enviando un objeto de parámetro que veremos más adelante. Para empezar ya a codear, nos vamos a la carpeta /src y abrimos el archivo Main.as que es la raíz de nuestro programa; aquí vamos a establecer las variables de BlueMarble y las llamadas de clases, pero antes, vamos a comentar una línea que luego nos puede ser algo incómoda al momento de hacer debug, y es en el método deactivate(), que es un listener que se dispara al ponerse Idle el aparato, pero también al darle click fuera de la ventana de AIR, por lo que se nos puede cerrar sin querer al estar revisando el output de FlashDevelop:

private function deactivate(e:Event):void { // auto-close //NativeApplication.nativeApplication.exit(); }

Sugiero cambiar esta linea de código de point a gesture, ya que si en algún momento queremos proceder a usarlos es muy probable que se nos olvide y caigamos en frustración porque los eventos no se dispararán; no es obligado y tampoco afecta el uso de BlueMarble (hasta donde mis pruebas actuales indican), pero es una recomendación. // touch or gesture? Multitouch.inputMode = MultitouchInputMode.GESTURE; Procedemos a continuación a crear una variable para nuestro administrador de ventanas llamando a la class WindowManager de Blue Marble

WindowManager

private var _windowManager:WindowManager;

al digitar los dos puntos (“:”) se llamará automáticamente al generador de código automático y nos incluirá WindowManager en cuanto presionemos enter al aparecer un pop up; en caso que no se importe solo por presionar mal alguna tecla, procedemos a colocar el cursor sobre el nombre de la class e inmediatamente presionamos Ctl-Shift-1; esta secuencia importará WindowManager automáticamente y con cualquier otra class en nuestro código; una entre varias ventajas que tiene FlashDevelop con respecto al manejo de código actionscript que está ausente en otros lenguajes que dan soporte de colores como PHP, Javascript; aunque PHP tiene autocompletar para classes nativas, pero no así importadas por nosotros; esto obviamente por que su enfoque principal es HaXe/as3. WindowManager es la class que administrará nuestras ventanas y la navegación entre ellas, cargándolas y descargándolas de memoria, conforme las llamamos; es una class gráfica dependiente de la variable Stage, por lo que recomiendo este siguiente código para asegurarse de que Stage ya se ha cargado correctamente, ya que podrían presentarse problemas si esto no se realiza, ya que la necesita para tomar medidas de pantalla y colocar los elementos antes de que se presenten en pantalla:  

// entry point

init(); if (stage != null){ addedToStage(); }else{ addEventListener(Event.ADDED_TO_STAGE, addedToStage); }


Este código se coloca en el constructor Main(); tiene una función init() para inicializar variables, esto porque el constructor en Actionscript al compilarse no se comprime, lo que aumenta el tamaño final del archivo, así que hay que mantener al mínimo el uso de variables e inicializadores en el constructor, por eso es mejor tener una referencia a una función sin comprimir, que todas las variables; luego preguntamos si el stage existe; si ya se cargó para ese momento, entonces procedemos a llamar a la función donde iniciará el programa, en caso contrario ponemos un listener y este esperará a que el contenido se cargue para iniciar. Este método también es muy útil al crear swf para web, ya que el archivo al ser descargado no estará funcional hasta que esté completo, y si stage se llama antes pues habrán problemas. En nuestra funcion addedToStage agregamos al parametro default de Event un null para poder hacer la llamada en solitario de la función en el constructor, y también para evitar ponerle el null a mano en el constructor

private function addedToStage(e:Event = null):void

También movemos las siguientes lineas de código que estaban en el constructor aquí:

stage.scaleMode = StageScaleMode.NO_SCALE; stage.align = StageAlign.TOP_LEFT; stage.addEventListener(Event.DEACTIVATE, deactivate);

  Y ahora sí dentro de esta función podemos iniciar nuestro programa después de estas últimas líneas. Window Manager en sí misma la vamos a necesitar en otras partes, así que la convertí en un Singleton; que es una class que solo puedes instanciar una vez, y solo por el método ofrecido por la clase; esto también para mantener la integridad de la aplicación y no tener más de un WindowManager corriendo; pero si podremos tener más de una referencia y usar sus propiedades como una variable global.

_windowManager = WindowManager.instance; addChild(_windowManager);

La raya baja en la propiedad (“_”) es una costumbre de desarrolladores de actionscript; tiene dos utilidades, una es hacer notoria que la variable es privada en contexto de variables locales en un método, pero es puro concepto visual, hay muchos que no les gusta y no lo usan; pero la segunda utilidad tal vez los haga cambiar de parecer, y es que el autocompletar de FlashDevelop al presionar “_” y una letra, nos mostrará únicamente esas variables o propiedades privadas, y se tiene un acceso rápido a ellas. Pueden no usarlas, pero se los recomiendo, es casi que un standard entre desarrolladores de actionscript. WindowManager es un Sprite, lo que quiere decir que se verá en pantalla; pero no será visible hasta indicarselo directamente por actionscript, y para eso está addChild, que agrega variables de tipo DisplayObject al DisplayList que es el ambiente visual, lo que vemos en pantalla. Inmediatamente después de creada, la agregamos al DisplayList, para luego proceder a agregar nuestras pantallas o ventanas; esta es una de las cosas que quisiera mejorar, ya que por costumbre a veces, hago addChild después de tener a todos los objetos visuales y variables listas, pero WindowManager necesita de acceso a stage, y solo puede tenerlo al hacerse el addChild, ya que como tuve que elegir crear el Singleton, no puedo enviar stage de parámetro; si se hace addChild de WindowManager luego de agregar las ventanas, es muy probable que todo se desordene en pantalla, le recomiendo lo intente para ver las consecuencias de ello, pero luego de agregar unas ventanas para que sea visible el daño.

Window

Una ventana es una class que hereda de Window, así de simple, esto nos permitirá enviársela a WindowManager para que la coloque en nuestra pantalla. Para crear una nueva class, damos click derecho sobre nuestra carpeta src/ y seleccionamos Add > New Class y llenamos los datos de la siguiente ventana:

New Class

Clase nueva, herencia y constructor default

A simples rasgos una class heredada de Window luce así:  

package { import net.absulit.bluemarble.controls.Window;
public class MainWindow extends Window {
public function MainWindow(width:int=400, height:int=400, data:Object=null) {
super(width, height, data);
}
}
}


Sin poner nada en esta ventana, podemos enviársela a WindowManager y tener la aplicación vacía, pero lista:  

_windowManager.push(MainWindow, "Home", [true|false], [iconpath:String]); _windowManager.sort();

  Para esto agregamos las dos lineas anteriores; el método push, inserta la referencia de la class dentro de WindowManager para futuro uso, incluso si llamamos directamente a la class luego, es necesaria para otros procesos; el segundo parámetro existe para otro componente visual: El TabBar; ese string pondrá un texto en el TabBar para ser visualizado inmediatamente y para navegación; el true o false sirve para esconder el boton del TabBar; el iconpath es un parámetro que exíste pero no está completamente funcional; provee un ícono para ser usado con o sin el texto, pero me pareció más apropiado en este primer release de BlueMarble dejar funcional al menos uno y luego retomar el desarrollo, aunque el campo está abierto desde ya. Luego llamamos a la función sort() que acomodará finalmente los elementos en pantalla y principalmente el TabBar, que tiene que hacer un conteo de las ventanas existentes y visibles; así como de las medidas de la pantalla actuales. Técnicamente con esto la aplicación está completa, pero falta incluir algo, un archivo del que el mismo ArbolNegro depende, y es flash.swc (incluido en la descarga del ejemplo). Si considera que está listo, puede probar la aplicación, presionando Ctrl-Enter y probarlo StandAlone en el computador:

Primera compilación

Me gusta cambiar las dimensiones en Run.bat y usar las dimensiones en proporción al iPhone, ya que a la vez sirve para visualizarlo en la computadora y acostumbrarnos al mínimo tamaño disponible:

set SCREEN_SIZE=320x480:320x480

Como pueden apreciar en la imagen anterior, la interfaz es mímina; TabBar con “Home” de label, y arriba, aunque vacío, está el ActionBar, que podrá contener por ahora, un botón de navegación a la izquierda, aunque usted puede darle el uso que requiera, y un botón de acción a la derecha, pensado para menús secundarios; en medio puede ir un título, que se ajustará y mostrará de acuerdo a su tamaño. Estos elementos son accesibles gracias a propiedades dentro de cada Window, aunque pienso cambiarlo a algo más sencillo y asignarlo al WindowManager en un futuro, o ambos, pero prefiero el WindowManager para un acceso más abierto que actualmente no tengo al poner el acceso dentro de Window. Veamos un ejemplo sobre como modificar estas propiedades; para esto nos vamos a nuestra recién creada ventana MainWindow.as, recordando mantener el proceso de preguntar si existe stage antes de usarlo, proseguimos con el código:  

private function init():void { _actionBar.title = "Blue Marble Demo 1"; _actionBar.navigation = new Button(); _actionBar.navigation.label = "Exit"; _actionBar.navigation.addEventListener(MouseEvent.CLICK, onClickActionBarNavigation); _actionBar.action = new Button(); _actionBar.action.label = "Test"; }

private function onClickActionBarNavigation(e:MouseEvent):void { NativeApplication.nativeApplication.exit(); }

ActionBar actualmente es una propiedad heredada de Window (pero estará en WindowManager) y de ahí podemos acceder a los botones navigation y action; crearles una nueva instancia (mi principal queja de esto es rehacerlas, cuando deberian estar constantes a mi gusto, aunque eliminarlas entre ventanas ahorra memoria, creo que es algo incomodo rehacerlas) y agregarles un listener y su método como por ejemplo el CLICK para hacer EXIT con el método nativo de AIR. Pueden probarlo y de hecho el exit funcionará. Para probarlo bien en Android y iOS pueden revisar el post anterior y comprobar que todo funcione bien.

Conclusión

Dentro de un Window, pueden meter LO QUE SEA que ustedes ya hayan hecho en actionscript con anterioridad, esa era mi meta, simplificar la forma de hacer aplicaciones y devolverle el poder al programador sin obstáculos de componentes pesados y poder hacer lo que sabemos hacer, que es crear nuestra propia interfaz dentro de la aplicación. Hay muchas cosas más por ver; hay un par de componentes que no he detallado aquí, pero que son fáciles de usar y pueden ver el código, que son Button, Text e InteractiveList, aunque el último necesita una explicación propia, pero eso será para otro artículo. Si quieren ver una aplicación completamente terminada en BlueMarble pueden ver Webcams Costa Rica la cual originalmente fue desarrollada en Flex con un peso de 6MB ahora con BlueMarble tiene un peso de 712KB También aquí adjunto el proyecto terminado en FlashDevelop para que puedan revisarlo:

Descarga BlueMarbleDemo1

Espero que esto sea de utilidad para quien aún no se haya animado a crear una aplicación y subirla al Play Store, y que empiecen a convertir esas ideas en algo real. Saludos y espero sus comentarios y dudas.