Puedes descargar el código fuente aquí
ScrumCards de Autentia en Android
Creo francamente que se ha producido una gran evolución en los dispositivos móviles sin precedentes.
¡Ahora ya sí se pueden usar de un modo eficiente!
Para poder ser justos en la comparación de las dos principales tecnologías: IPhone y Android quiero desarrollar
la misma aplicación o equivalente a la recién desarrollada sobre la baraja de Scrum en el IPhone:
https://adictosaltrabajo.com/tutoriales/tutoriales.php?pagina=scrumIphone.
Aunque en Autentia ya hay gente que lleva tiempo cachareando con Android, voy a probar a ver el tiempo que tardo en hacerlo
yo… bien oxidado, desde cero. Esto huele a pique…
Instalación del entorno
Nos vamos al Web de desarrollo de Android en http://developer.android.com/index.html
Nos bajamos la última versión del SDK de Android. Yo estoy en Mac.
El entorno consta de una extensión de Eclipse y un SDK. Leeros bien las instrucciones que …por mucho correr … yo tuve algún problemita.
Descargamos entonces eclipse Galileo para Mac. Me bajo la versión con soporte para Java (no J2EE que no necesitamos
para nada)
Tarda una ratito.
Arrancamos eclipse en nuestro Mac y definimos la ubicación por defecto de área de trabajo. Marcad si
queréis el check para que no os lo pregunte más,
A mi me da un pequeño error que ignoro relacionado con php. Pinchamos en Eclipse en el menú Help->Install New Software. Luego si queremos actualizar podemos usar la opción Check for Updates.
Pulsaremos Add e insertaremos la dirección del servidor de Android (ir a las instrucciones para ver el que esté en ese momento).
Nos aparecerán los elementos a instalar.
Se instalarán
Tarda una rato porque tiene que bajarse el software de internet
Ahora podemos tirar eclipse y volverlo a arrancar. Diremos que queremos crear un nuevo proyecto.
De tipo Android Project.
Pero nos dirá que no hemos establecido el SDK todavía. Esto es lo que os decía que hay que leerse
las instrucciones antes … no es problema porque lo salvamos con facilidad.
Nos vamos a ir al directorio donde hayamos descargado el SDK de Android. En mi Mac lo lógico me parece ponernos
en Developer/….En el directorio de herramientas pulsamos android.
Nos vamos a la pestaña de Settings y pinchamos Force https using http. Esto es porque no me funciona la conexión
https …
Vamos a la lengüeta de paquetes disponibles y elegimos las últimas revisiones del SDK.
Pinchamos en Instalar seleccionados… y estamos en marcha.
Como esto tarda, vamos a hacer una configuración mientras.
Establecer el path del SDK
Ahora tenemos que asegurarnos que ponemos en el path de nuestro sistema operativo la carpeta de Tools para una buena
integración con Eclipse. Debemos editar o crear el fichero .bash_profile en el Mac. Ver instrucciones de cómo se
hace en otros sistemas operativos.
Yo lo hago con el Vim exportando la variable path.
Grabamos y salimos
Ya se han descargado todos los paquetes.
Comprobamos lo que tenemos.
Crear un Emulador
Ahora desde cualquier lugar podríamos invocar al emulador … pero todavía nos falta una pequeña
configuración
No tenemos definido ningún dispositivo virtual … así que poco vamos a poder emular.
Vamos a Virtual Devices
y seleccionamos New
Le ponemos el nombre deseado, el nivel de API de las descargadas, el tamaño de la memoria y el swing tal y como
veis…
Ya tenemos un dispositivo Android por defecto
Sólo tenemos que lanzarlos. Tarda un ratillo en arrancar pero ya estamos .
Navegamos por la Web de Autentia a ver cómo queda.
En el emulador podemos hacer lo mismo que en un teléfono normal.
Os recomiendo leer las instrucciones del emulador http://developer.android.com/guide/developing/tools/emulator.html
Para rotar el emulador de Android en Mac recordad que hay que pulsar simultaneamente Fn + Ctrl + F11 (o lo que sea)…
lo mejor es consultar la documentación.
Creación de un proyecto
Bueno, vamos de nuevo a Eclipse e intentamos crear el proyecto … lástima … todavía no podemos.
Nos vamos a las preferencias de Eclipse
E indicamos la localización del SDK de Android
Nos encuentra los targets.
Y por fin empezamos.
Un proyecto Android se basa en una primera actividad que hemos llamado CartasScrum.
Una actvidad puede tener una ventana que está definida en un fichero xml.
Los ficheros xml de Andrioid son pre-compilados generándose una clase R de referencias que podemos usar en nuestros
programas.
Vemos en la primera captura que nuestra clase de actividad CartasScrum hereda de Activity y que establece como vista
R.layout.main.
Una aplicación tiene distintas actividades que para nuestra baraja podría ser:
- La pantalla de selección de carta a mostrar (botones).
- La pantalla con el detalle
La primera que se ejecutará se basará en el contenido del fichero Android.xml
Una de las cosas más importantes a tener en cuenta con las actividades es su ciclo de vida. Cuando se arrancan,
se paran, se restablecen …
Como estamos en Eclipse, vamos a redefinir los métodos básicos para ver ese ciclo de vida en nuestro lo… y
así de camino vemos cómo funciona.
Establecer trazas
Pulsando sobre la clase actividad con el botón derecho se nos muestra la opción de Source -> Override/Implement
Methods … Esto es una de las cosas que más he echado de menos en xcode a la hora de desarrollar en Iphone.
Elegimos los métodos OnPause, OnRestart … ya hay que leerse la documentación porque no es el objetivo del
tutorial.
Usaremos los métodos Log.x para trazar información
Aparece algo como esto
public class CartasScrum extends Activity { public static String MIAPP = "CartasScrum"; // constante solo para trazas /** Llamada al crearse la actividad. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.i(MIAPP,"Estamos en OnCreate"); setContentView(R.layout.main); // establecemos la vista de plantilla } @Override protected void onDestroy() { // TODO Auto-generated method stub Log.w(MIAPP,"Estamos en OnDestroy"); super.onDestroy(); } @Override protected void onPause() { // TODO Auto-generated method stub Log.w(MIAPP,"Estamos en OnPause"); super.onPause(); } @Override protected void onRestart() { // TODO Auto-generated method stub Log.w(MIAPP,"Estamos en OnRestart"); super.onRestart(); } @Override protected void onResume() { // TODO Auto-generated method stub super.onResume(); } @Override protected void onStart() { // TODO Auto-generated method stub Log.w(MIAPP,"Estamos en OnStart"); super.onStart(); } /* (non-Javadoc) * @see android.app.Activity#onStop() */ @Override protected void onStop() { // TODO Auto-generated method stub Log.w(MIAPP,"Estamos en OnStop"); super.onStop(); } }
Damos a ejecutar como aplicación Android.
Y abrimos en Eclipse la perspectiva de depuración.
Abajo a la derecha nos aparece la consola de log. Podemos poner un filtro para ver sólo los mensajes que nos interesan
Por la etiqueta que hemos puesto en el parámetro de nuestra llamada a la función Log.
Añadir elementos a nuestra primera ventana
Desde el principio vemos que todo está muy ordenadito y estructurado. Todas las cadenas están en un fichero
llamado strings.xml dentro del directorio res (muy importante). Podemos editar visualmente el contenido para cambiar la cadena
por defecto en la ventana de nuestra primera actividad.
En el directorio layout dentro de ‘res’ vemos que está main.xml. Si lo pinchamos podremos editar visualmente
nuestra ventana. Le podemos cambiar el tema por ejemplo …que es un conjunto de estíos.
Para montar nuestra botonera vamos a insertar debajo el texto por defecto y layout tabular. De él colgarán 5 filas y a
su vez los botones dentro de cada fila. Fijaos a la derecha.
Como la quinta fila sólo tiene un botón, vamos a sacarla del layout tabular (pulsando el botón Down) para
que quede como un elemento más libre. Podemos ver que cada botón tiene un identificador y texto
tipo @+id/Button01.
Si arrancamos la aplicación no aparece ningún texto porque todavía no lo hemos registrado.
Nos vamos de nuevo al editor de cadenas de caracteres y agregamos del boton1 al 13.
Y tendremos que ir uno a uno por los botones para, en su propiedad text, seleccionar el texto del botón que hemos creado.
Ya vemos el aspecto que tiene.
No vamos a complicarnos mucho con el aspecto visual aunque sí describir una pincelada de cómo se hace.
Estableciendo estilos
Podemos asociar a los botones un estilo de tal modo que cambiando externamente el estilo cambien todos los botones …
vamos… el mismo concepto que css. Creamos un fichero xml pichando el botón derecho sobre el directorio res
dentro de Eclipse. Elegimos crear un fichero xml de Android.
Decimos que es un fichero de valores y le llamamos styles.xml (por seguir un poco la convención).
Es importante el destino: res/values
Añadimos un elemento de tipo Stile, estilo.
Dentro de estilo (botonesGrandes) un item o elemento.
Y decimos que la propiedad androide:textSize es 18pt (ojo que en la captura me he confundido y pone tex…)
Ahora le asociamos el estilo al botón.
Y vemos cómo queda
Con paciencia se lo asignamos a los demás.
Creación de la segunda ventana
Ahora vamos a crear la segunda pantalla que será el soporte de la segunda actividad.
Creamos de nuevo un
fichero xml de Android
Le llamamos detallecarta.xml. Ponedlo en minúsculas porque luego es muy puntilloso para estos temas.
Elegimos que es de tipo layout.
Veis lo que os decía si lo pones con mayúsculas.
Bueno, repetimos la operación y borramos el fichero anterior para evitar líos.
Ahora vamos a irnos a por nuestras cartas de Scrum a www.autentia.com
Fijaos que he cambiado el nombre de las imágenes para que no de guerra en Android.
En Iphone trababa que se llamasen ?, 0,5, Descansamos? Aquí no cuela por lo que evitamos problemas.
Desde el escritorio (Finder en Mac) pinchamos y arrastramos todas las imágenes al directorio drawable-hdpi. Si os
fijáis, la clase R se verá modificada añadiendo nuevos identificadores de estos elementos.
La base de nuestra ventana será un ImageView y pondremos en la propiedad Background la imagen del reverso…
se hace seleccionándola visualmente como se ve en la captura.
Añadir una segunda actividad
Ahora vamos a añadir la clase de la actividad.
Desde el asistente de eclipse añadimos una clase.
La llamamos DetalleCartas y decimos que hereda de android.app.Activity
Podemos copiar y pegar el código del OnCreate de la primera actividad y decirle que la vista asociada es nuestra
DetalleCartas (usando el asistente de autocompletar a partir de la clase R)
Vamos a añadir la actividad al fichero de manifiesto. Aunque vamos a invocar una actividad directamente desde otra,
en este fichero se pueden establecer filtros de invocación automáticos (cosa que no vamos a hacer de momento).
Decimos que queremos editar el fichero con el editor de manifiesto (pinchando el botón derecho sobre AndroidManifest.xml)
Pinchamos en añadir y aplicamos un filtro para ver sólo las que empiezan por A… nuestra actividad.
Elegir la acción
Enlazando todo con código
El código es sencillísimo. Creamos un gestor de eventos inicializado con la actividad y la imagen
asociada a cada botón.
Al pulsar el botón, llamaremos a la segunda actividad y le pasaremos como parámetro la imagen con la que
tiene que pintar (dentro de un Intent). He quitado los métodos que no usamos para nada (On..)
package es.autentia.ScrumCards; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.util.*; import android.view.View; import android.widget.Button; public class CartasScrum extends Activity { public static String MIAPP = "CartasScrum"; // constante solo para trazas /** Llamada al crearse la actividad. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.i(MIAPP,"Estamos en OnCreate"); setContentView(R.layout.main); // establecemos la vista de plantilla establecerListener(R.id.Button01, R.drawable.carta_0_cc); // asociamos el gestor de eventos establecerListener(R.id.Button02, R.drawable.carta_05_cc); establecerListener(R.id.Button03, R.drawable.carta_1_cc); establecerListener(R.id.Button04, R.drawable.carta_2_cc); establecerListener(R.id.Button05, R.drawable.carta_3_cc); establecerListener(R.id.Button06, R.drawable.carta_5_cc); establecerListener(R.id.Button07, R.drawable.carta_8_cc); establecerListener(R.id.Button08, R.drawable.carta_13_cc); establecerListener(R.id.Button09, R.drawable.carta_20_cc); establecerListener(R.id.Button10, R.drawable.carta_40_cc); establecerListener(R.id.Button11, R.drawable.carta_100_cc); establecerListener(R.id.Button12, R.drawable.carta_nose_cc); establecerListener(R.id.Button13, R.drawable.carta_descansamos_cc); } void establecerListener(int ID,int IDimagen) // ponemos el gestor de eventos y le asociamos una imagen { Button botonAux = (Button) this.findViewById(ID); botonAux.setOnClickListener( new GestorClicks(IDimagen,this)); // le pasamos la imagen y la actividad } // clase auxiliar de gestión de eventos para asociar la imagen al botón class GestorClicks implements View.OnClickListener { int idImagen = R.drawable.reverso_cc; // ponemos por defecto el reverso Activity actividad = null; public static String MIAPP = "CartasScrum - GestorEventos"; // para depuración GestorClicks(int pImagenID, Activity pActividad) // constructor { idImagen = pImagenID; actividad = pActividad; } public void onClick(View v) { Log.i(MIAPP,"Boón pulsado " + v.getId()); Log.i(MIAPP,"Mostraremos la imagen " + idImagen); Intent parametros = new Intent (actividad.getApplicationContext(),DetalleCartas.class); // creamos los parametros parametros.putExtra("es.autentia.ScrumCards.IDImagen", idImagen); // pasamos un parametro extra a la actividad actividad.startActivity(parametros); // invocamos la actividad } }
Y la segunda actividad es todavía más sencilla porque simplemente cambiamos la imagen a mostrar en la vista. Al pulsar en la vista finalizamos la acción por lo que volvemos a la anterior.
package es.autentia.ScrumCards; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.util.Log; // para el log import android.view.View; import android.widget.*; // para el ImagaView import android.content.Intent; // para los parametros extra en el Intent public class DetalleCartas extends Activity { public static String MIAPP = "CartasScrum-DetalleCartas"; // para log public int idimagen = R.drawable.carta_100_cc; // si falla algo que salga siempre el 100 /** Invocado cuando se llama la primera vez. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Intent parametros = this.getIntent(); // recuperamos parametros. int IDImagen = parametros.getIntExtra("es.autentia.ScrumCards.IDImagen", idimagen); Log.i(MIAPP,"Estamos en OnCreate"); setContentView(R.layout.detallecartas); // recordar invocar antes de enlazar componentes visuales ImageView vista = (ImageView) this.findViewById(R.id.ImageView01); // enlazamos con la vista vista.setOnClickListener( new GestorClicksVentana(this)); vista.setImageResource(IDImagen); // ponemos la imagen } } //clase auxiliar de gestión de eventos para asociar la imagen al boón class GestorClicksVentana implements View.OnClickListener { Activity actividad = null; // enlace con nuesta actividad public static String MIAPP = "CartasScrum - GestorClicksVentana"; GestorClicksVentana(Activity pActividad) // asociamos en parámetro con la veriable de clase { actividad = pActividad; } public void onClick(View v) { // manipulamos en evento // TODO Auto-generated method stub Log.i(MIAPP,"Botón pulsado " + v.getId()); actividad.finish(); // cerramos la actividad } }
Sencillo ¿verdad? todo es fácil cuando ya lo has conseguido 😉
Algunas conclusiones sobre el desarrollo Iphone/Android
Bueno, otro reto que no he tardado más en resolver que unas cuantas horas… La verdad es que me anima bastante a
afrontar cualquier reto en este tipo de desarrollos.
Como resumen diría:
Ventajas del desarrollo con IPhone
- Es un único dispositivo por lo que no hay que «hacerlo todo tan parametrizable
ni flexible». - Un buen aspecto visual es más fácil de obtener.
- En emulador y entorno xcode es más rápido en cargar y en conmutar vistas (desarrollo/depuración).
- Documentación muy buena.
- En entorno más integrado y sencillo de montar.
Inconvenientes del desarrollo con IPhone
- Sólo se puede desarrollar en Mac.
- Hay que aprender un nuevo lenguaje: Objetive-C
- Tienes que preocuparte de la gestión de memoria.
- Xcode no está tan evolucionado con asistentes
como Eclipse: Auto-completar (xcode tiene pero me gusta menos), asistentes para construcción de clases,
redefición de métodos, etc. - No poder instalar tus propios programas en tu dispositivo sin pagar.
Ventajas del desarrollo con Android
- Se programa en Java en cualquier entorno (aunque esto sólo lo es para el que ya conoce
Java ya que para el que conoce Cocoa trabajar con Iphone sea trivial). - Te olvidas de la gestión básica de memoria
(aunque es como todo.. las buenas prácticas hay que usarlas igual). - Hay una gran cantidad de empresas
aproyándolo por lo que el potencial de talento y velocidad es impresionante.
Inconvenientes del desarrollo con Android.
- Emulador lento al cargar aunque engancha al vuelo (no hay que cargarlo constantemente).
- Entorno gráfico poco elaborado para mi gusto.
Bueno, ya sabéis que si queréis desarrollos o formación sobre todas estas cosas y la integración
con entornos transaccionales podéis encontrarnos en www.autentia.com.