martes, 30 de septiembre de 2014

Interfaz de usuario, conceptos básicos

La interfaz de usuario de una aplicación es la parte que el usuario puede ver y con la que puede interactuar. Android nos proporciona una serie de contenedores y controles que podremos combinar para construir nuestra interfaz de usuario. Android también cuenta con un juego de componentes comunes a toda interfaz y que podremos utilizar en nuestros diseños: mensajes emergentes, cuadros de diálogo, menús, etc.

Todos los elementos que forman la interfaz de usuario de una aplicación están formados por objetos de tipo View (vista) y ViewGroup (vista de grupo). Un objeto de tipo View es un objeto que se muestra en pantalla y con el que el usuario puede interactuar. Un objeto de tipo ViewGroup es un objeto sin representación que puede contener otros objetos de tipo View o ViewGroup y que nos servirán para organizar nuestras plantillas.

Android nos proporciona una amplia variedad de vistas: botones, campos de texto, vistas de grupo con distribución lineal o relativa, etc.

Localización

Android se utiliza en muchos países y/o regiones al rededor de todo el mundo. Para poder llegar al mayor número de usuarios posible, nuestra aplicación tendrá que ser capaz de adaptarse a múltiples idiomas, formas de escritura, formatos de fecha, datos numéricos, archivos de sonido e imágenes relacionados con los idiomas y países de origen.

Los recursos son las cadenas de texto, plantillas, sonidos, imágenes y cualquier otro tipo de dato que nuestra aplicación necesite para su funcionamiento. Una aplicación puede incluir múltiples conjuntos de recursos adaptados a configuraciones diferentes de dispositivo. Cuando el usuario ejecuta la aplicación, Android seleccionará y cargará de manera automática los recursos que mejor se adapten a la configuración actual.

domingo, 28 de septiembre de 2014

Gestionando cambios de configuración en tiempo de ejecución

La configuración de un dispositivo suele cambiar durante la ejecución de nuestra aplicación: orientación de la pantalla, disponibilidad del teclado, idioma, etc. Cuando uno de estos cambios sucede, el sistema reinicia la actividad que se está ejecutando justo en ese instante (se invocan sus métodos onDestroy y onCreate(), por ese orden). Durante este proceso, el sistema también actualiza los recursos con aquellos que mejor se adaptan a la nueva configuración.

Para gestionar de manera adecuada el reinicio de nuestra aplicación, será necesario implementar sus actividades para que éstas sean capaces de recuperar sus estados previos. Como norma general, utilizaremos el método onSaveInstanceState() para guardar los datos necesarios y utilizaremos los métodos onCreate() o onRestoreInstanceState() para recuperarlos posteriormente.

viernes, 26 de septiembre de 2014

Accediendo a los recursos

Cada recurso en nuestra aplicación, se identifica a través de un ID de recurso. Se trata de un número entero único que se encuentra definido dentro de la clase especial R. Cada vez que la aplicación es compilada, la herramienta aapt generará automáticamente la clase R con todos los IDs asociados a los archivos contenidos en la carpeta res/ de nuestro proyecto. Por cada tipo de recurso se creará una subclase de la clase R (por ejemplo, R.drawable para recursos de tipo imagen), y por cada recurso se creará una constante de tipo entero (por ejemplo, R.drawable.icon, línea 9). Esta variable será la que utilizaremos para acceder al recurso.

La clase especial R:
public final class R {
    public static final class attr {
    }
    public static final class dimen {
        public static final int activity_horizontal_margin=0x7f040000;
        public static final int activity_vertical_margin=0x7f040001;
    }
    public static final class drawable {
        public static final int icon=0x7f020000;
    }
    public static final class id {
        public static final int action_settings=0x7f080002;
        public static final int listView=0x7f080001;
        public static final int textView=0x7f080000;
    }
    public static final class layout {
        public static final int activity_my=0x7f030000;
    }
...
}

miércoles, 24 de septiembre de 2014

Servicios, conceptos básicos

Un servicio es un componente de aplicación que ejecuta de manera indefinida operaciones en segundo plano y por tanto no necesita de una interfaz de usuario. Un servicio puede ser iniciado desde otro componente y seguir ejecutándose independientemente del estado del componente que lo inició. Además, un componente podrá conectarse a un servicio e interactuar con él a través de una interfaz (IPC - Inter Process Communication, Comunicación Entre Procesos). Por ejemplo, un servicio podría encargarse de gestionar las transacciones de red, de reproducir música, de realizar operaciones de entrada y salida (E/S), o de interactuar con un proveedor de contenido; todo ello desde un segundo plano.

sábado, 20 de septiembre de 2014

Ciclo de vida de las actividades.

Cuando interactuamos con una aplicación, sus actividades cambian de estado continuamente. Por ejemplo, cuando una actividad se inicia por primera vez, ésta pasa a un primer plano para interactuar con el usuario. Durante este proceso, Android invoca una secuencia de métodos retrollamada asociados al ciclo de vida de la actividad.  Desde estos métodos, por ejemplo, podremos configurar la interfaz del usuario. Si el usuario realiza alguna acción pasando a iniciar otra actividad, o bien cambia de aplicación, será ésta última la que pase a un primer plano. La actividad inicial pasará a un segundo plano conservándose su estado.

Los métodos retrollamada relacionados con el ciclo de vida de una actividad nos serán útiles para especificar el comportamiento de ésta ante las idas y venidas del usuario. Por ejemplo, si estamos programando un reproductor para vídeo streaming, deberíamos detener la reproducción y cerrar la conexión de red cuando el usuario cambia de aplicación. Si el usuario decide volver al reproductor, volveremos a reestablecer la conexión de red y la reproducción justo donde se había quedado.

Cargadores

Los cargadores hicieron su primera aparición con la versión 3.0 de Android. El objetivo de un cargador es el de facilitar la carga y actualización de los datos usados en una actividad o fragmento. Entre sus características, podemos destacar:
  • Pueden ser usados desde las actividades y fragmentos de nuestra aplicación.
  • La carga de los datos puede realizarse de manera asíncrona.
  • Detectan cambios en la fuente de datos y entregan los nuevos resultados.
  • Si la configuración del dispositivo cambia, el cargador recuperará los datos de la última consulta sin tener que volver a repetirla, con el consiguiente ahorro de tráfico y procesamiento de datos.

miércoles, 17 de septiembre de 2014

Proveedores de contenido, conceptos básicos

Los proveedores de contenido son objetos encargados de gestionar el acceso a un conjunto de datos estructurados. Encapsulan los datos y nos proveen de mecanismos para definir su seguridad. Los proveedores de contenido definen una interfaz estándar que permite a un proceso compartir sus datos con otros procesos.

Cuando queremos acceder a los datos de un proveedor de contenido, utilizaremos el objeto ContentResolver asociado al contexto de nuestra aplicación para comunicarnos como cliente del proveedor. Es decir, utilizaremos el objeto ContentResolver para comunicarnos con un objeto ContentProvider. El objeto proveedor recibe las peticiones de datos desde uno o varios clientes, realiza las acciones solicitadas y devuelve los resultados.

Si los datos de nuestra aplicación no se van a compartir con otras aplicaciones, no tendremos que implementar nuestro propio proveedor. Sin embargo, necesitaremos desarrollar un proveedor para nuestra aplicación si queremos implementar mecanismos de búsqueda con predicción de texto. También necesitaremos de proveedores si queremos que se puedan copiar y pegar datos estructurados o archivos desde nuestra aplicación a otras aplicaciones.

Android incorpora una serie de proveedores de contenido para audio, vídeo, imágenes y contactos. Con algunas restricciones, estos proveedores serán accesibles desde cualquier aplicación.

lunes, 15 de septiembre de 2014

Depuración

Android Studio nos permitirá depurar nuestras aplicaciones sobre dispositivos virtuales o físicos. Con Android Studio podremos:
  • Seleccionar el dispositivo sobre el que queremos depurar nuestra aplicación.
  • Visualizar el registro del sistema.
  • Añadir puntos de ruptura en nuestro código.
  • Examinar variables y evaluar expresiones en tiempo de ejecución.
  • Ejecutar las herramientas para depuración desde el SDK de Android.
  • Realizar capturas de pantalla y vídeo de nuestras aplicaciones.

domingo, 14 de septiembre de 2014

Tareas y la pila de retroceso

Una aplicación suele estar formada por varias actividades. Cada actividad debe ser diseñada en torno a un tipo determinado de acción que el usuario puede realizar y que a su vez puede iniciar otras actividades. Por ejemplo, una aplicación de correo electrónico puede tener una actividad que muestre un listado con los mensajes entrantes y cuando el usuario selecciona uno, se inicia una nueva actividad para mostrar sus detalles.

Una actividad incluso puede iniciar actividades de otras aplicaciones. Por ejemplo, si queremos enviar un correo electrónico, podemos definir una intención para realizar una acción del tipo "send" y añadirle datos adicionales como la dirección del destinatario y el mensaje. Una actividad definida en alguna aplicación y que haya sido declarada para gestionar intenciones del tipo "send", será la encargada de enviar el correo (en el caso de que existan varias actividades en el sistema capaces de responder a la misma intención, el usuario podrá seleccionar qué actividad quiere usar). Una vez se ha enviado el correo, la actividad inicial se reanuda. Todo este proceso es transparente de cara al usuario que en todo momento cree estar en la misma aplicación. Para conseguir esto, Android gestiona ambas actividades dentro de la misma tarea.

viernes, 12 de septiembre de 2014

Fragmentos

Una fragmento es un objeto de tipo Fragment que aporta su propia lógica y aspecto (IU) a una actividad. Una actividad puede contener más de un fragmento y éstos podrán ser reutilizados en varias actividades. Podemos pensar en los fragmentos como en los módulos de una actividad que cuentan con su propio ciclo de vida y que pueden ser añadidos y eliminados de una actividad mientras ésta se esté ejecutando.

Un fragmento siempre estará contenido en una actividad y su ciclo de vida dependerá del ciclo de vida de ésta. Por ejemplo, cuando una actividad entra en pausa, todos sus fragmentos también entrarán en pausa, y cuando una actividad es destruida, todos sus fragmentos también serán destruidos. Sin embargo, mientras una actividad se está ejecutando (es decir, se encuentra en estado reanudada), el estado de cada fragmento funcionará de manera independiente. Además, podremos añadir, eliminar o reemplazar fragmentos a nuestro antojo a través de un mecanismo basado en transacciones. Cada transacción, antes de ser confirmada, podrá ser registrada en una pila de retroceso para fragmentos que gestiona la propia actividad y que permitirá al usuario volver a estados previos con tan solo pulsar el botón de retroceso.

Como norma general, cuando añadimos un fragmento a una actividad, lo que estamos haciendo es insertando su plantilla dentro de la plantilla de la actividad. Podemos insertar un fragmento en una actividad de dos formas: de manera estática, añadiendo un elemento <fragment> a la plantilla de la actividad, o de manera dinámica, añadiendo el fragmento desde el código a una vista contenedora (ViewGroup) previamente instanciada. Sin embargo, no todos los fragmentos cuentan con una plantilla y su objetivo principal consistirá en aportar funcionalidad adicional a una actividad.

La vista de proyecto Android

La vista de proyecto Android nos muestra una versión simplificada de la estructura de nuestro proyecto, permitiéndonos acceder de manera rápida a los archivos más importantes, incluyendo los archivos relacionados con el sistema de builds Gradle. Esta vista se destaca porque:
  • Agrupa los archivos relacionados con el sistema de builds Gradle.
  • Muestra las carpetas más importantes para cada módulo del proyecto.
  • Agrupa los archivos manifest por módulo.
  • Agrupa los archivos de recursos teniendo en cuenta el idioma, la orientación de la pantalla, tipos de pantalla, etc.

lunes, 8 de septiembre de 2014

Actividades

Una actividad es un componente de aplicación que proporciona una pantalla con la que el usuario puede interactuar con el fin de realizar alguna operación, como por ejemplo: hacer una llamada telefónica, hacer una fotografía, enviar un correo electrónico, o ver un mapa. Cada actividad está delimitada por su ventana en la que se muestra la interfaz de usuario. La ventana generalmente ocupa toda la pantalla, pero puede ser más pequeña y flotar sobre otras ventanas.

Una aplicación generalmente está formada por un conjunto de actividades relacionadas entre sí. Una, y solo una, de esas actividades la declararemos como la actividad principal de nuestra aplicación y eso hará que se inicie por defecto cuando el usuario ejecute la aplicación por primera vez.

Una actividad también puede ser iniciada a través de otra actividad con el fin de realizar diferentes acciones. Cuando iniciamos una actividad, ésta se añade a la pila de retroceso (back stack) y pasa a un primer plano, disponible para la interacción con el usuario. Cuando el usuario pulsa el botón de retroceso, la actividad actual se saca del tope de la pila y se destruye, reanudándose la actividad previa. Al sistema de funcionamiento de la pila de retroceso se le conoce por las siglas LIFO (Last In First Out - Último Entra, Primero Sale).

Los cambios de estado que sufre una actividad son comunicados por el sistema mediante la invocación de métodos retrollamada (callbacks) asociados a la propia actividad. Hay varios métodos retrollamada que una actividad puede recibir cuando ésta cambia de estado: cuando el sistema la crea, la detiene, la reanuda, o la destruye. Para cada uno de estos eventos, podremos realizar las operaciones que consideremos necesarias implementando su método correspondiente. Por ejemplo, cuando la actividad es detenida, deberíamos implementar lo necesario para liberar la memoria de objetos pesados, tales como conexiones de red o conexiones a bases de datos. Cuando la actividad se reanuda, recuperaremos los recursos necesarios y continuamos por donde lo habíamos dejado.

viernes, 5 de septiembre de 2014

Intenciones y filtros de intenciones

Una intención (Intent) es un objeto que utilizaremos para iniciar un componente desde otro componente. Aunque las intenciones facilitan la comunicación entre componentes de varias maneras, hay tres casos de uso fundamentales:

  • Para iniciar una actividad (Activity). Una actividad representa una pantalla de nuestra aplicación. Podemos iniciar una actividad pasando una intención como parámetro del método startActivity(). La intención describe qué actividad iniciar y transportará cualesquiera otros datos que fueran necesarios.

    Si además queremos recibir algún tipo de resultado desde la actividad cuando ésta finaliza, utilizaremos el método startActivityForResult(). La actividad que originó la solicitud, recibirá el resultado a través de una intención a la que podremos acceder desde su evento onActivityResult().

  • Para iniciar un servicio (Service). Un servicio es un componente que realiza operaciones en segundo plano y que no cuenta con una interfaz de usuario. Puedes iniciar un servicio para realizar una operación (descargar un archivo, por ejemplo) pasando una intención como parámetro al método startService(). La intención describe el servicio a iniciar y transportará cualesquiera otros datos que fueran necesarios.

    Si el servicio cuenta con una interfaz cliente-servidor, podrás enlazar el servicio desde un componente pasando una intención como parámetro del método bindService().

  • Para la entrega de avisos (BroadcastReceiver). Un aviso es un mensaje que cualquier aplicación podrá recibir y que se genera como consecuencia de un evento concreto. El sistema avisa de ciertos eventos tales como que el sistema está arrancando, o que se ha iniciado la carga de batería. Podremos enviar avisos a otras aplicaciones pasando una intención como parámetro de los métodos sendBroadcast(), sendOrderedBroadcast(), o sendStickyBroadCast().

martes, 2 de septiembre de 2014

El editor de plantillas

Android Studio cuenta con un editor avanzado de plantillas que nos permitirá añadir widgets fácilmente a nuestros diseños con una simple acción de pinchar y arrastrar. También contaremos con una vista previa de las modificaciones que vayamos haciendo en el código fuente (XML) de nuestras plantillas.

El editor soporta dos modos de visualización: una vista en modo texto donde podrás modificar el código XML tal cual, y una vista en modo diseño más visual.