La columna 80

El blog técnico-personal de Ángel J. Vico… en español

Estructura de un proyecto Android

Posted by Ángel J. Vico en 13 de abril de 2011

En el último post creamos nuestro primer proyecto Android, pero lo hicimos utilizando un asistente que hizo todo el trabajo sucio por nosotros, creando unas cuantas carpetas y archivos en nuestro espacio de trabajo con contenido listo para compilar, tal y como se puede observar en la siguiente captura:
Estructura de un proyecto Android

Antes de entrar en detalles de codificación de aplicaciones Android, quizás sea recomendable examinar esa estructura para poder entender mejor cómo se organiza un proyecto y dónde tendremos que agregar cada cosa cuando creemos los nuestros.

Buscando el código fuente

El código fuente de la aplicación se sitúa en dos carpetas: src y gen. En la carpeta src situaremos nuestras clases, las que codifiquemos nosotros (o copiemos de algún sitio, que de todo hay). Por otro lado, en la carpeta gen se situarán las clases que se generen automáticamente, normalmente como resultado de procesar otros archivos del proyecto.

Ambas carpetas contienen archivos escritos en Java con extensión .java, y ambas se organizan por paquetes. Cada clase Java, incluidas las creadas por nosotros, pertenece a un paquete. Además, un paquete puede contener a su vez otros paquetes. Eso crea una estructura en forma de árbol que se traduce en carpetas dentro de carpetas en el disco duro.

Cuando creamos la aplicación tuvimos que especificar el nombre del paquete en el que se incluirían de forma predeterminada nuestras clases (apartado Package name en las propiedades del proyecto). Utilizamos un nombre para el paquete con tres partes separadas por puntos (en concreto pruebas.columna80.holamundo). Al generar el proyecto, el asistente habrá creado una carpeta para cada una de las partes del nombre del paquete, cada una dentro de la anterior, situando el archivo Principal.java en la más interna de ellas.

Si tenemos muchas clases en el proyecto y queremos organizarlas, podemos crear nuevos paquetes. Éstos tendrán que ser descendientes del paquete inicial (pruebas.columna80.holamundo en esta aplicación) o de otro de los paquetes que ya hayamos creado. Para que un paquete sea descendiente de otro tiene que llevar el nombre del padre como prefijo. Por ejemplo, un descendiente del paquete inicial podría ser pruebas.columna80.holamundo.actividades.

A la hora de visualizar los paquetes en la vista Package Explorer tenemos dos opciones: verlos de forma jerárquica o de forma plana. Para cambiar de un modo a otro hay que pulsar el botón del triángulo blanco (a la derecha de la botonera de la vista Package Explorer) para desplegar un menú en el que seleccionaremos Package Presentation para mostrar las dos opciones: Flat (vista plana) y Hierarchical (vista jerárquica). La vista predeterminada es la jerárquica, donde cada paquete que contiene algún archivo se muestra como una rama que tiene como nombre la última parte del nombre del paquete y que se sitúa bajo la rama que representa al resto del nombre del paquete. Por otro lado, en la vista plana todos los paquetes aparecen con su nombre completo y al mismo nivel (como hijos de la carpeta src o gen). Como una imagen vale más que mil palabras, las siguientes capturas muestran ambas vistas, la jerárquica a la izquierda y la plana a la derecha:

Paquetes en vista jerárquicaPaquetes en vista plana

En nuestro proyecto (el de la captura que encabeza el artículo) tenemos un archivo de código en cada una de las carpetas. En la carpeta src tenemos Principal.java. El nombre del archivo se corresponde, como suele ser habitual en Java, con el de la clase que se implementa en dicho archivo (aunque no es obligatorio, lo normal es implementar cada clase Java en un archivo de código fuente diferente). El nombre de esta clase lo definimos nosotros al crear el proyecto, introduciéndolo en el cuadro de texto Create Activity (en la sección Properties del asistente).

Si abrimos el fichero (haciendo doble click sobre él con el botón izquierdo del ratón) podemos ver que, efectivamente, contiene una clase de nombre Principal que hereda de la clase Activity. Esta clase define la actividad principal de la aplicación y permite implementar su comportamiento. El asistente nos ha creado el código mínimo necesario para poder mostrar el saludo, que es lo único que hace nuestra aplicación. Puedes obtener más información sobre las actividades en este post.

De forma análoga, si desplegamos la carpeta gen y el paquete que contiene veremos un único archivo de código fuente con el nombre R.java. Este archivo lo genera automáticamente el compilador y contiene identificadores para los recursos incluidos en el proyecto. Al estar declarados en Java, esos identificadores se pueden utilizar en el resto del programa para hacer referencia a los recursos que identifican. Sobre los recursos hablaré en el siguiente apartado y sobre la forma de usarlos en el programa en otro post.

Podemos abrir el archivo R.java para ver lo que contiene, teniendo siempre cuidado de no modificarlo. Vemos que los identificadores de recursos se definen como constantes enteras a las que se les asignan números en hexadecimal, todos diferentes. Los identificadores se agrupan en clases, cada una de ella representando a un tipo de recurso distinto. Esas clases, a su vez, se declaran dentro de una clase global de nombre R. El asistente nos creó cuatro recursos: el icono predeterminado para la aplicación, el diseño (layout) predeterminado para la actividad principal de la aplicación y dos cadenas de texto, una para el nombre de la aplicación y otra para el mensaje (el saludo) que se muestra en la actividad. En el siguiente apartado veremos dónde están los recursos que se corresponden con esos identificadores.
Contenido de R.java

Un detalle que aún no he comentado sobre la vista Package Explorer es que los archivos .java no son las hojas del árbol que se muestra, sino que se pueden desplegar también para mostrar elementos internos. Dichos elementos se muestran también de forma jerárquica según las relaciones que tienen en el propio código fuente. Así, podemos ver la jerarquía de clases y los atributos o métodos que contienen representados como hijos de las clases en el árbol. Haciendo doble click con el botón izquierdo del ratón sobre cualquiera de esos elementos veremos su definición en la ventana de edición, lo que puede resultar bastante útil para localizarlos cuando los archivos empiezan a crecer.
Archivos Java desplegados

Los recursos

Se consideran recursos todos aquellos elementos que utiliza la aplicación que no forman parte del código fuente. Normalmente se tratan como recursos las imágenes, los archivos de audio, animaciones, vídeos, etc. Android permite definir fuera del código también otros elementos como cadenas de texto, menús o incluso los diseños de las actividades. Es lo que se denomina externalización de recursos, y es algo bastante útil porque permite modificarlos de forma mucho más sencilla que si estuvieran codificados en archivos Java y porque permite tener variantes para un mismo recurso, de forma que se pueda usar uno u otro según las características del dispositivo donde se ejecute la aplicación. Esta última característica es la más importante de todas, dado que permite que los textos de la aplicación se muestren en el idioma que tiene configurado el usuario o que la disposición de los elementos visuales se adapte al tamaño de la pantalla.

Los recursos se localizan todos dentro de la carpeta res del proyecto. Se distribuyen en carpetas, cada una de las cuales representa un tipo de recursos. Los nombres de estas carpetas están prefijados, aunque no es necesario incluirlas todas. En los siguientes apartados describiré los diferentes recursos que se pueden tener y cómo debe llamarse la carpeta que los contenga.

Otro detalle importante de los recursos es que no sólo se pueden utilizar en el código fuente de la aplicación, también se pueden utilizar en otros recursos. Por ejemplo, un diseño puede incluir cadenas, dimensiones o colores que también estén definidos como recursos. Podemos ver un ejemplo de esto en el archivo res/layout/main.xml de nuestro proyecto. En ese archivo, que contiene el diseño de la actividad principal de la aplicación, se hace referencia a la cadena hello que se define en el archivo res/values/strings.xml y que contiene el saludo que muestra la aplicación.

Veamos ahora qué tipo de recursos podemos tener en nuestra aplicación:

Recursos simples

Se sitúan dentro de la carpeta values, y pueden ser de diversos tipos. Todos se definen en archivos XML. Dentro de la carpeta values puede haber varios archivos XML cuyo nombre es irrelevante. Cada uno de estos archivos puede contener definiciones de recursos de diversos tipos mezcladas. Sin embargo, se recomienda agrupar todos los recursos del mismo tipo en un mismo archivo, no mezclarlos, y darle al archivo un nombre representativo: strings.xml, colors.xml, etc.

El plugin ADT proporciona un editor de texto para editar directamente el XML o un editor simple de recursos que permite crear algunos de los tipos utilizando cuadros de diálogo:
Editor de recursos
Dentro de la carpeta values podemos incluir varios tipos de recursos:

  • Cadenas de texto: pueden ser cadenas independientes o arrays de cadenas
  • Colores: se definen en hexadecimal y comenzando siempre por una almohadilla (#). Deben incluir, como mínimo, tres valores, que se corresponden con la cantidad de rojo, verde y azul que componen el color deseado (formato RGB). Además, pueden llevar también información sobre el nivel de transparencia del color (lo que se denomina canal alfa). Si se omite, el color es completamente opaco.
  • Dimensiones: normalmente se utilizan como atributos de otros recursos y permiten dar uniformidad a los distintos elementos que se muestran en pantalla, a la vez que posibilitan el cambiar su tamaño en función del tipo de pantalla que tenga el dispositivo que ejecuta la aplicación. Se definen con un número seguido (sin espacios) por una cadena que representa la dimensión.
  • Estilos: permiten definir un conjunto de propiedades visuales que se pueden aplicar, todas juntas, a vistas o incluso actividades (aplicados como temas).
  • Booleanos: sólo pueden tener los valores true o false. Se suelen usar para hacer que la aplicación actúe de una forma u otra en función de las características del dispositivo donde se ejecuta.
  • Identificadores: podemos crear identificadores únicos para la aplicación. Son similares a los que se generan automáticamente para cada recurso, pero sin la necesidad de tenerlos ligados a ninguno de ellos (aunque podemos hacerlo). La aplicación podría necesitar este tipo de identificadores en algunas situaciones. Por ejemplo, para usarlos como códigos de error o para identificar cuadros de diálogo.
  • Enteros: son valores numéricos que se utilizan de forma similar a como se usan los booleanos. Aunque, a diferencia de estos últimos, aquí podemos definir arrays de enteros.
  • Arrays genéricos con tipo: se pueden crear arrays de recursos, bien sea de recursos ya definidos (identificados por su nombre) como de recursos genéricos (sin nombre asociado).

Recursos gráficos

La mayoría de los recursos gráficos se localizan bajo la carpeta drawable y pueden ser de numerosos tipos. Sin embargo, la mayor parte de las veces usaremos sólo unos pocos:

  • Mapas de bits: imágenes sencillas en formato PNG, JPG o GIF (aunque el más recomendable es el PNG). Los archivos se copian directamente a la carpeta drawable y se identifican en la aplicación por su nombre (el del archivo).
  • Imágenes redimensionables (nine-pacth): imágenes compuestas por nueve imágenes más pequeñas que permiten escalar el objeto rectangular representado a cualquier tamaño. Las imágenes se corresponden con las 4 esquinas del objeto (no cambian de tamaño), los cuatro laterales (se estiran en la dirección correspondiente) y el centro (se redimensiona al tamaño adecuado). Se utilizan para proporcionar gráficos para controles como botones, que se pueden adaptar a diferentes tamaños. Son archivos con extensión .9.png que se sitúan directamente en el directorio drawables.
  • Animaciones: las hay de dos tipos:

    • Animaciones imagen a imagen (Frame Animations): se definen en archivos XML, en la carpeta drawable. Cada elemento de la animación es otro recurso gráfico de la carpeta drawable junto con el tiempo que tiene que visualizarse.
    • Animaciones basadas en transformaciones (Tween Animations): se definen también en archivos XML, pero en la carpeta anim. Contienen una serie de transformaciones y efectos, como desvanecimientos, rotaciones, escalados o desplazamientos, que se aplican en el orden y con las características definidas a la imagen que queramos.

Diseños

Los diseños definen la forma de disponer los elementos visuales en la pantalla. Se aplican a las actividades (el equivalente a las ventanas en un sistema operativo de PC) y contienen vistas (el equivalente a los controles) y la forma de distribuirlas.

Se definen en archivos XML dentro de la carpeta layout e incluyen todas las vistas y grupos de vistas (contenedores de otras vistas) que se quieren mostrar en pantalla, personalizadas por medio de los diferentes atributos que poseen. Lo habitual es utilizar el resto de recursos para personalizar estas vistas: cadenas de texto, colores, dimensiones e incluso elementos gráficos.

Es el principal recurso de las interfaces de usuario y conviene, por tanto, verlo con bastante más detalle del que me puedo permitir en este post (bastante largo ya de por sí), por lo que le dedicaré uno o más posts dentro de poco.

Menús

En la carpeta menu se definen todos los diferentes tipos de menús que puede tener una aplicación: menú de opciones (el que se muestra cuando se pulsa el botón MENÚ), menú contextual (el que se muestra cuando se deja pulsado un elemento gráfico en la pantalla) y submenú (el que se muestra cuando se escoge en un menú una opción que contiene un menú anidado).

Se definen en archivos XML y cada menú puede contener elementos simples, grupos de elementos y submenús.

Resto de recursos

Por completitud, voy a enumerar en esta sección el resto de recursos que se pueden tener en el proyecto, aunque se utilicen con algo menos de frecuencia:

  • Lista de colores para estados: es un recurso que se define en XML en la carpeta color y que se utiliza como si fuera un color normal (de los que se definen en la carpeta values). La diferencia radica en que no define un único color, sino varios: uno por cada estado que pueda tener el elemento al que se le aplique. De esta forma, el color se cambiará automáticamente cada vez que cambie el estado del objeto. Por ejemplo, un botón puede tener diferente color cuando está pulsado y cuando no lo está.
  • Archivos XML: aunque la mayoría de recursos se definen en archivos XML, cada uno en la carpeta que le corresponde, también es posible que necesitemos disponer de archivos XML específicos para utilizarlos en la aplicación directamente. Esos archivos se sitúan en la carpeta xml. Un ejemplo de esto es el archivo XML que se utiliza para definir la pantalla de preferencias de la aplicación.
  • Otros archivos de recursos: archivos que se utilizarán directamente en la aplicación. Se colocan en la carpeta raw.

Otras carpetas interesantes

Hay más carpetas en el proyecto, aunque algunas no las crea directamente el asistente:

  • Carpeta libs: aquí se sitúan las bibliotecas privadas que utiliza el proyecto. Las bibliotecas son conjuntos de archivos java compilados y empaquetados en un archivo JAR. Sirven para reutilizar conjuntos de clases en otros proyectos, sin tener que copiar los archivos java individuales y sin tener que proporcionar el código fuente.
  • Carpeta assets: aquí se pueden colocar también archivos que se utilizarán directamente en la aplicación (igual que los que se incluyen en la carpeta res/raw). La diferencia es que a los que se incluyen en la aplicación como recursos se accede por medio del identificador que se les asigna al compilar, mientras que a los de la carpeta assets se accede de forma similar a como se accede a archivos externos, pudiendo incluso navegar por los directorios que creemos.
  • Carpeta jni: además de programar para la máquina virtual Dalvik, las herramientas de desarrollo permiten crear componentes nativos, que se compilan directamente para la arquitectura hardware del dispositivo en que se ejecutarán y que pueden formar parte de aplicaciones convencionales. Los archivos fuente de esos componentes se colocan en la carpeta jni y se compilan con las herramientas específicas que incluye el Native Development Kit (NDK).
  • Carpeta Android versión: en nuestro proyecto de ejemplo, Android 1.5. Esta carpeta contendrá la biblioteca de clases correspondiente a la versión de Android para que le estamos creando la aplicación, en formato JAR (la que escogimos en la sección Build Target de las propiedades del proyecto).
  • Carpeta bin: esta carpeta, que se crea al compilar por primera vez, contendrá los archivos resultantes de la compilación: el paquete de la aplicación (archivo .apk), las clases compiladas a bytecode Java (archivos .class), los recursos compilados, etc.

El manifiesto

Además de carpetas, también se incluyen en el proyecto algunos archivos genéricos que, sin ser parte del código fuente o recursos, determinan la forma en que se generará la aplicación al compilar. De todos ellos, el archivo AndroidManifest.xml es el más importante de todos.

Este archivo, el manifiesto de la aplicación, contiene la información que el sistema operativo necesita conocer antes de poder ejecutar la aplicación. Aunque nos referiremos a este archivo en muchas ocasiones en futuros posts, valga por el momento la siguiente lista como resumen de su contenido:

  • Identificación de la aplicación: nombre del paquete, número de versión, etc. También si permitimos que la aplicación se pueda mover a la tarjeta SD.
  • Atributos de la aplicación: el nombre que se le mostrará al usuario, icono y logotipo, una descripción de su funcionalidad e incluso permisos globales.
  • Permisos: los que requiere la aplicación para funcionar. Son los que se le muestran al usuario antes de instalarla.
  • Componentes hardware: los que la aplicación utiliza o puede utilizar. Se puede indicar si son indispensables o no y sirven para que la aplicación sólo aparezca en el Android Market de equipos compatibles.
  • Pantallas: las que son compatibles con la aplicación. También se utiliza para filtrar aplicaciones en el Android Market.
  • Versiones de Android: la mínima que la aplicación requiere para ejecutarse y aquella para la que se ha creado (que no tienen por qué coincidir). Principal elemento de filtrado en el Android Market.
  • Actividades: datos de todas las actividades que incluye la aplicación, como nombre, icono, permisos de ejecución, etc.
  • Otros componentes de la aplicación: datos de servicios, proveedores y receptores de contenidos, etc.

Las siguientes capturas muestran el manifiesto de nuestra primera aplicación, tanto el editor específico que proporciona el plugin ADT como el propio XML:

Manifiesto - Datos generalesManifiesto - Atributos de la aplicaciónManifiesto - XML

El resto de archivos

Aunque el manifiesto es el más importante de todos, hay más archivos genéricos en un proyecto Android:

  • default.properties: fichero generado que contiene las propiedades del proyecto, las que se definen en Eclipse en Project | Properties | Android.
  • build.properties: contiene la información necesaria para firmar automáticamente la aplicación (necesario para poder publicarla en el Android Market). Con Eclipse no se utiliza porque dispone de un asistente específico para ello.
  • build.xml: contiene la información necesaria para compilar el proyecto desde línea de comandos. No se utiliza en Eclipse.

Recuerda que en esta página dispones de enlaces a todos los artículos sobre Android que he publicado en La columna 80.

6 comentarios to “Estructura de un proyecto Android”

  1. […] recomiendo este excelente post que abarca una explicación muy detallada acerca de cada uno de los directorios y componentes de un […]

  2. Jaime said

    excelente post, Gracias

  3. Leslie said

    Me dejó claro lo que andaba buscando

  4. Angela said

    excelente post

  5. Edgar Bernal said

    Excelente tutorial. Tienes un error de tipeo (Package en vez de Pocket)

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s