lunes, 21 de mayo de 2012

Sincronizando Android con la Nube

Viendo la presentación Developing Android REST client applications se habla dos errores muy grandes que todo principiante comete al implementar servicios web con Android:
  • ejecutar el servicio web en el hilo principal
  • alojar los recursos obtenidos en la memoria en lugar de en almacenamiento permanente
La parte negativa del primer punto es que las transferencias de datos pueden llevar bastante tiempo derivando en una UI lenta y en ocasiones que esta deje de responder. Por otro lado el no persistir los datos se pude pensar que hará nuestra aplicación mas rápida. Pero ¿que pasa si el S.O. decide expulsar de memoria a nuestra aplicación para darle lugar a otra? Que tendremos que volver a pedir los datos al servidor conllevando mas gasto de CPU por lo tanto de batería y el esperar tiempo necesario para volver a transferir el recurso.

En la charla se proponen tres patrones de diseño diferentes:
  • Service
  • Content Provider
  • Content Provider y SyncAdapter
Cada uno de las diseños se pueden ver las transparencias de la charla.

En este caso veamos como se implementa el ultimo de ellos. En los dos primeros patrones tenemos que encargarnos manualmente del estado de los recursos y de las transacciones, pero en el ultimo caso todo esto se hace automáticamente a través de SyncAdapter. SyncAdapter sera el encargado de gestionar el estado de los recursos y actualizarlos cuando sea conveniente, este es el patrón usado por Gmal, Facebook, LastFM, por citar algunos.

Imagen tomada de las transparencias de la presentación.
Como vemos la estructura se divide en cinco partes. La capa mas alta se encarga de mostrar los datos al usuario. La actividad es una actividad común y corriente, que interactúa con el usuario guardando pidiéndole o mostrando los datos que nos interesen. El CursorAdaptar es quien refresca los datos que están en el ContentProvider con la interfaz, mostrando siempre los datos mas recientes. Los datos son almacenados en un ContentProvider, si no quieren usar un content provider para guardar los datos deberán engañar al sistema, creando uno que no haga nada, en StackOverflow se explica mas o menos como hacerlo.

ContentProvider
Como crear un ContentProvider ya se explico en un post anterior así que como es de suponer no se volverá a explicar. Es más, dicho post fue pensado para usarlo como base para este.

Account Authenticator
Para poder sincronizar nuestra aplicación con un servidor primero debemos agregar una cuenta al sistema.  Para ello que mejor que echarle un vistazo a los ejemplos de Google, en concreto a este. El ejemplo también se puede encontrar dentro del SDK que tenemos instalado, pero no es exactamente igual a la versión online, traten de usar la versión online que es la mas actual.

Dentro del paquete authenticator se implementa la gestión de cuentas haciendo uso de tres clases:
  • Authenticator: implementa la gestión de la cuenta.
  • AuthenticationService: define un servicio que instancia a Authenticator para realizar las tareas en el background.
  • AuthenticatorActivity: la actividad mostrada para pedir las claves al usuario.
Para tener todo la gestión de cuentas haremos uso del viejo y querido copy & paste, en un mundo ideal funcionaria sin ninguna modificación pero es demasiado bueno para ser verdad asi que hay que hacer algunas modificaciones. En el ejemplo usa otra dos clases, Constants y NetworkUtilities. Si quieren también las pueden copiar, sino:
  • definir las dos constantes definidas en Constants en la clase Authenticator
  • reemplazar Networkutilities por la clase donde este implementado el acceso al servidor, el método authenticate es el que nos interesa, ya que es con el que se validan las credenciales del usuario.
Si usaron AuthenticatorActivity en lugar de una actividad propia, hay que copiar el fichero xml/authenticator.xml, el contenido de values/strings.xml, y añadir al Manifest la definición del servicio y de la actividad.
La variable android:name indica la ruta de la clase AuthenticatorService.


Con eso si instalamos nuestra aplicación al ir a Settings > Accounts and sync > Add account saldrá nuestro el tipo de cuenta que acabamos de definir.

Tengan muchísimo cuidado al declarar el servicio ya que al estar trabajando con XML es muy fácil meter la pata, en mi caso cuando se creaba la cuenta se iniciaba la sesión sin problema pero mas tarde al volver a intentarlo no se iniciaba la sesión porque no estaba guardando el password de usuario. Todo eso por tener mal los ficheros XML.


SyncAdapter
Con lo anterior ya esta la gestión de la cuenta ahora viene lo que realmente nos interesa como sincronizar nuestro teléfono con un servidor. Nuevamente tendremos que crear un servicio para que se ejecute ocultamente sin molestar a nadie. Para eso se precisan dos clases SyncAdapter y SyncService.

SyncAdapter define las acciones a realizar cuando se lleva a cabo la sincronizacion, en este caso llama al metodo syncLog de la clase VideoLogger.

syncLog implementa lo que realmente se hace al sincronizar, esto puede ir dentro de syncAdapter, pero pero claridad y facilidad de mantenimiento decididí gestionarlo aparte. Como veran primero obtiene todos los objetos PendingMovie que hay almacenados y luego va iterando sobre ellos y subiendolos al servidor, en este caso en concreto el metodo upload, borrara el objeto del ContentProvider una vez recibido el ACK del servidor.


Y SyncService instancia a SyncAdapter comom un singleton y lo vincula al servicio.

Finalmente hay que crear un XML con la definición del syncadapter y definir el servicio en el Manifest.


res/xml/syncadapter.xml

Y eso es todo.

martes, 15 de mayo de 2012

Scrum II: Scrum Team

Imagen obtenida de openclipart

Luego de haber comentado un poco la teoría en la que se basa Scrum, es posible hablar de quienes son los responsables de llevarlo a cabo. La puesta en practica se lleva a cabo en equipos denominados Scrum Team, cada equipo esta formado por Product Owner, Development Team (o equipo de desarrollo) y Scrum Master. Estos equipos son completamente autónomos, multidisciplinarios y auto-organizados. Con este modelo se pretende tener flexibilidad, creatividad y productividad. Entremos un poco en los detalles de cada perfil.

Product Owner
El Product Owner es quien gestiona el valor del producto, es decir quien decide que es lo que hay que hacer, se podría comparar con la figura tradicional del Jefe de proyecto. Product Owner hay uno y solo uno, ni dos, ni tres; únicamente una persona determinada es quien puede cumplir este rol. 

Para realizar la tarea con éxito, toda la organización debe respetar las decisiones tomadas por el Product Owner. Nada de el jefe del jefe del jefe dice A o B, el que quiera cambiar algo que hable con el Product owner, tan sencillo como eso. Si lo convencen bien, sino mala suerte, si esta en ese puesto sabrá lo que esta haciendo.

Las tareas que tiene a cargo son:
  • Definir los elementos del Product Backlog
  • Ordenar el Product Backlog para lograr los objetivos establecidos
  • Asegurarse que el equipo de desarrollo cumple con su trabajo
  • Asegurarse que el Product Backlog es visible, transparente y comprensible para todos
  • Asegurarse que el Product Backlog muestra realmente el trabajo planificado
  • Asegurarse que el equipo entiende un elemento del Product Backlog al nivel necesario
Development Team
Los integrantes del equipo de desarrollo serán los que llevaran a cabo las tareas para poder implementar el incremento del producto. Para poder realizar el desarrollo completo de un incremente logicamente tendrán que ser grupos multi-disciplinarios. La organización del grupo depende de si mismos y las relaciones internas son de igual a igual, no hay diferencias de roles, todos son considerados como desarrollador. A pesar de que cada persona tenga un conjunto de habilidades especifico, la regla anterior tiene que cumplirse por lo que cada uno tiene que ser capaz de saber cuales son sus puntos fuertes y sus puntos débiles. 

El tamaño de los equipos es algo que siempre se discute en cualquier metodología, Scrum particularmente no define una cifra concreta sino que determina dos rangos, uno inferior y otro superior. No es aconsejable que el equipo tenga menos de tres personas, aunque a primera vista parezca algo bueno ya que se reduce el tiempo de comunicación aumentando un poquito la productividad, es muy probable que la productividad ganada se desperdicie cuando el equipo se encuentre con un problema que no es el mas adecuado para sus habilidades. Y en el caso contrario equipos de de más de nueve personas requiere mucha comunicación llevando a una reducción de la productividad.

Una posible combinación para un equipo podría tener los siguientes roles: ingeniero de software, arquitecto, analista, programador, tester y diseñador de UI.

Scrum Master
El Scrum Master es el director de la orquesta, tiene que ser capaz de sincronizarse a la perfeccion con el equipo tratando de eliminar todos los posibles obstaculos que aparezcan por el camino. Gran parte de su tarea es estar pendiente de que el equipo de desarrollo siga las pautas de Scrum (teoria, practicas y reglas). Otra de sus funcionalidades es de actuar como un enlace entre el equipo y el mundo exterior, decidiendo cuando el equipo puede o no interactuar con alguien del exterior.
Brinda tres tipos de servicio:

  • Servicios para el Product Owner
    • Proveer de técnicas eficaces para la gestión del Product Backlog
    • Comunicar el objetivo del Product Backlog al equipo de desarrollo
    • Enseñar a todo el equipo como diseñar elementos del Product Backlog
  • Servicios para el Equipo de desarrollo
    • Ayudar con la organización del equipo
    • Ayudar con la creación de un producto de gran valor
    • Eliminación de obstáculos
  • Servicios a la organización
    • Guiar a la organización a adoptar Scrum como metodología
    • Generar cambios que produzcan un aumento en la productividad de equipo
    • Trabajar coordinadamente con otros Scum Masters para aumenta la eficacia de Scrum en la organización.
    • Planificar la implementación de Scrum con la organización

Los servicios que brinda un Scrum Master como puede verse son muchos y muy variados, sin duda que es un perfil muy flexible. Es una pieza clave para el desarrollo de Scrum, al principio sera un guía, un instructor enseñando al equipo con mucha frecuencia, luego que el equipo adquiera experiencia tendrá que enfocarse en la motivación, para que esta no decaiga.

Para la próxima eventos y artifactos.

viernes, 4 de mayo de 2012

Android: Creación de un ContentProvider

Un ContentProvider es una interfaz que nos brinda Android para acceder a una base de datos que se encuentre en nuestro teléfono. Y hacer que las aplicaciones puedan compartir información fácilmente.

Los pasos a seguir para la implementación son los siguientes:
  1. Extender la clase ContentProvider
  2. Crear la base de datos
  3. Implementar getType
  4. Implementar onCreate
  5. Implementar los metodos CRUD
  6. Registar el ContentProvider en AndroidManifest.xml

Se va a explicar como crear un Content Provider que llevara un registro de los ficheros que abre un usuario.

Extender la clase ContentProvider
Al definir que nuestra clase extiende ContentProvider se nos crear el esqueleto básico de nuestra clase.
Que debería ser algo así:


Crear la base de datos
Ya con la estructura creada, tenemos que definir una URI para nuestra base de datos, para que el sistema pueda identificarla. En el futuro cuando llegue el momento que queramos realizar alguna consulta a la base de datos se hará a través del URI que vamos a definir. Se definen en la linea 2 y 3.

Ademas del URI, hay que definir una serie de propiedades, entre paréntesis se indica el numero de linea:
  • Tipos de URI, un ítem especifico o un conjunto de ellos (6 - 11)
  • La base de datos, nombre, versión y nombre de la tabla (14 - 20)
  • Columnas de la tabla y su respectivo indice (23 - 28)
  • Controlador de peticiones (30-36)

Ahora hay que pasar a la creación de la BD, para ello hay que implementar SQLiteOpenHelper como una clase privada. Y como pueden ver en la constante CREATE_TABLE se define la creación de la tabla con SQL usando las columnas definidas anteriormente. Mediante SQLiteOpenHelper el inicio de la base de datos se hace de manera perezosa, es decir hasta que no se necesita no se inicia. Evitando que nuestra aplicación se inicie mas lentamente, y que surjan errores relacionados con la base de datos al iniciar la aplicación.



Implementar getType

Este metodo se encarga de analizar la consulta y decidir que tipo de datos se esta consultando. Los dos tipos de datos fueron definidos en CONTENT_TYPE_LISTCONTENT_TYPE_ITEM, el tipo de datos debe empezar por vnd.android.cursor.dir/ y vnd.android.cursor.item/ para una lista y un item especifico, respectivamente.



Implementar onCreate

Como estamos usando SQLiteOpenHelper, tan solo le indicamos que queremos crear la base de datos y  este mismo ya se encarga de hacerlo cuando sea necesario.


Implementar los metodos CRUD
Al definir como realizar las consultas a la base de datos tenemos que ver si se trata de un item especifico  o de todos.

Registar el ContentProvider
Suponiendo que nuestro ContentProvider se encuentra en un paquete llamado provider, tenemos que registrarlo en el Manifest