Revista Informática

Estructura de un proyecto en Android Studio

Publicado el 15 agosto 2014 por Jamesrevelo @herprogramacion
Como habíamos visto en el artículo introductorio a la programación en Android, el proyecto de una aplicación está contenido en una jerarquía donde se ubican todos los archivos de código fuente Java, los recursos, las configuraciones y los archivos de construcción de Gradle.
El articulo de hoy tiene como fin comprender la estructura de archivos de un proyecto en Android Studio. Esto nos permitirá investigar a  fondo la lógica de construcción  de una aplicación. También estudiaremos como está estructurado el archivo Android Manifiest, que contiene la carpeta “res”, veremos la utilidad de los archivos layout.xml, los archivos R.java. Y finalmente daremos un vistazo al código fuente.
Android Studio, Estructura de un proyecto

¿Por donde iniciamos?

Para comenzar la explicación, ejecuta Android Studio y selecciona el proyecto “Test” que creamos anteriormente. Ahora ubícate en el panel llamado “Project”, el cual representa la estructura de tu proyecto. Como notas, están las carpetas .idea, app, buildgradle y otros archivos de configuración.
Panel Project en Android Studio
La carpeta app es la que contiene todo lo relacionado con tu proyecto, es la carpeta que nos interesa por el momento y donde incluiremos los archivos necesarios para que nuestra aplicación sea empaquetada. Si despliegas su contenido veras tres carpetas: build, libs y src. Por ahora ignoraremos los demás archivos.
Android Studio, carpeta app
Normalmente la mayor parte del tiempo y fuerzas las usaremos en la carpeta src(Source). Dentro de ella se ubica la carpeta main, la cual contiene todos los archivos fuente Java para nuestra aplicación. La carpeta res(Resources) que contiene los recursos del proyecto(iconos, sonido, diseños, etc) y el archivo AndroidManifiest.xml.
Android Studio, carpeta src

¿Qué es el ANDROID MANIFIEST?

Es un archivo XML que contiene nodos descriptivos sobre las características de una aplicación Android. Características como los building blocks existentes, la versión de SDK usada, los permisos necesarios para ejecutar algunos servicios y muchas más. En pocas palabras el Android Manifiest es un panorama de toda nuestra aplicación.
Si abres el archivo en el editor verás un código similar a este:
<?xmlversion="1.0"encoding="utf-8"?><manifestxmlns:android="http://schemas.android.com/apk/res/android"
  package="com.herprogramacion.test">
  <application
  android:allowBackup="true"
  android:icon="@drawable/ic_launcher"
  android:label="@string/app_name"
  android:theme="@style/AppTheme">
  <activity
  android:name=".MyActivity"
  android:label="@string/app_name">
  <intent-filter>
  <action android:name="android.intent.action.MAIN"/>
  <category android:name="android.intent.category.LAUNCHER"/>
  </intent-filter>
  </activity>
  </application>
</manifest>
Todas las aplicaciones deben contener este archivo por convención. El nombre debe permanecer intacto, ya que se usa como referencia para el parsing de nuestra aplicación. El nodo raíz de este documento se representa con la etiqueta <manifiest> y por obligación debe contener un hijo de tipo <application>.
En el código anterior podemos observar que manifiest posee dos atributos, xmlsn:android y package. El primero no debemos cambiarlo nunca, ya que es la dirección donde se encuentran todas las descripciones a implementar en una aplicación Android.
El atributo package indica el nombre del paquete Java que soporta a nuestra aplicación. El nombre del paquete debe ser único y un diferenciador a largo plazo.
La etiqueta <application> representa como estará construida nuestra aplicación. Dentro de ella definiremos nodos referentes a las actividades que contiene, las librerías incluidas, los Intents, Providers, y demas componentes.
Algunos atributos de la etiqueta <application> son:
  • allowBackup: Este atributo puede tomar los valores de true o false. Indica si la aplicación será persistente al cerrar nuestro AVD.
  • icon: Indica donde está ubicado el icono que se usará en la aplicación. Debemos indicar la ruta y el nombre del archivo que representa el icono. En este caso apuntamos a las carpetas drawable donde se encuentra ic_launcher.png. Icono por defecto que nos proporciona Android Studio.
  • label: Es el nombre de la aplicación que verá el usuario en su teléfono. Normalmente apunta a la cadena "app_name" que se encuentra en el recurso strings.xml(Mas adelante lo veremos).
  • theme: Este atributo apunta al archivo de recursos styles.xml, donde se define la personalización del estilo visual de nuestra aplicación.

Dentro de <application> encontraremos expresada la actividad principal que definimos al crear el proyecto Test. Usaremos <activity> para representar un nodo tipo actividad.
<activity> tiene dos atributos: name, el cual se refiere a la clase Java que hace referencia a esta actividad (Comienza con un punto “.”). Y el atributo label que hace referencia al texto que se mostrará en la cabecera de la actividad. En este caso es el mismo string "app_name".
Por el momento estudiaremos hasta este punto. En próximos artículos veremos el proposito de los nodos <intent-filter>, <action> y <category>.

¿Que utilidad tiene el archivo strings.xml?

Dentro de la carpeta "res" encontraremos todos aquellos recursos tercerizados para nuestra aplicación. Esta práctica de excluir los atributos de la aplicación a través de archivos externos, permite reducir la complejidad de diseño en las interfaces.
Uno de los recursos mas relevantes es el archivo strings.xml, que se encuentra dentro de la subcarpeta values. Este fichero almacena todas las cadenas que se muestran en los widgets(controles, formas, botones, vistas, etc) de nuestras actividades. Por ejemplo, si tuvieses un botón cuyo titulo es "Presiona aquí", es recomendable incluir dicha cadena en tu archivo strings.xml.
Android Studio, values
Para declarar nuestro recurso de strings usaremos el nodo raíz <resources>. Para declarar las cadenas usaremos la etiqueta <string> y estableceremos el atributo name como identificador. Dentro de esta etiqueta pondremos el texto que se visualizará en el componente de interfaz. Esta declaración es similar al uso de la etiqueta <h1>Texto</h1> en HTML.
Si abres el archivo, verás que se encuentran tres nodos del tipo <string> : "app_name", "action_settings" y "hello_world".
<?xmlversion="1.0"encoding="utf-8"?>
<resources>
  <string name="app_name">Test</string>
  <string name="hello_world">Hello world!/string>
  <string name="action_settings">Settings</string>
</resources>
app_name contiene el nombre de la aplicación. En este caso es "Test", action_settings se refiere al titulo del menú acciones y hello_world es el string para nuestro mensaje en pantalla la actividad.
El archivo strings.xml es muy útil para los desarrolladores. Una de sus grandes utilidades es facilitar el uso de múltiples idiomas en tu aplicación. Esto se debe a que puedes externalizar las cadenas del código java y seleccionar la versión del arhivo strings.xml con el  lenguaje necesitado.
Personalmente te recomiendo que uses este archivo siempre, incluye todo tu texto y no dejes nada por fuera, tu aplicación te lo agradecerá en el futuro.

¿Que hay dentro de la carpeta layout?

En la carpeta layout encontrarás los archivos de diseño de todas tus actividades. En mi caso existe el archivo activiy_my.xml. Este archivo representa el diseño de la interfaz de mi actividad principal. En el se establecerán todos los widgets que vaya a agregar a la actividad.
Android Studio, layout
Construir la interfaz a través de nodos XML es mucho mas sencillo que la creación a través de código Java. Adicionalmente Android Studio nos ha dotado de un panel de diseño estilo Drag and Drop, lo cual es una bendición para los desarrolladores, ya que facilita demasiado la creación de una interfaz de usuario.
Este archivo de diseño comienza con un nodo raíz llamado <RelativeLayout>. Un Layout es el contenedor principal que define el orden y secuencia en que se organizarán los widgets en nuestra actividad. Existen varios tipos de Layouts, como por ejemplo el LinearLayout, GridLayout, FrameLayout, etc.
Android Studio crea por defecto un RelativeLayout porque permite crear un grupo de componentes con ubicaciones relativas. Quiere decir que se ubicaran por referencias y no por valores absolutos. Esto permite ajustar nuestras aplicaciones a cualquier tipo de pantalla para dispositivos móviles.
Si abres el archivo de diseño de tu actividad verás algo como esto:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:paddingLeft="@dimen/activity_horizontal_margin"
  android:paddingRight="@dimen/activity_horizontal_margin"
  android:paddingTop="@dimen/activity_vertical_margin"
  android:paddingBottom="@dimen/activity_vertical_margin"
  tools:context=".MyActivity">
  <TextView
  android:text="@string/hello_world"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"/>
</RelativeLayout>
Veamos la utilidad de los atributos para <RelativeLayout>:
  • layout_width: Es el ancho que tendrá el layout dentro de la actividad. Aunque se puede especificar con unidades personalizadas, es recomendable usar match_parent para ajustarlo al ancho del dispositivo.
  • layout_height: Representa la dimensión vertical del layout. Usa match_parent para ajustarla al dispositivo.
  • paddingLeft, paddingRight: Es el espacio lateral existente entre el contorno del Layout y los widgets. Su valor apunta al archivo de recursos dimens.xml ubicado en la carpeta "values". Este archivo contiene nodos de tipo <dimen> con valores density-indepent pixels (dp). Para estos paddings se usa el nodo "activity-horizontal-margin", cuyo valor estándar son 16dp.
  • paddingTop, paddingBottom: Es el espacio vertical existente entre el cortorno del Layout y los widgets. Su valor es igual a el nodo "activity-vertical-margin" de dimens.xml.
  • context: Define el nombre del archivo Java que contiene la actividad donde el Layout será acogido.

Con este diseñador solo ubicamos los componentes donde nos plazca y automáticamente son generados como nodos en nuestro archivo.
Los lectores que han creado páginas web a través de frameworks como DreamWeaver podrán entender rápidamente el concepto, debido a que diseñar la interfaz de una aplicación Android es muy similar a crear aplicaciones HTML.

¿Como hacemos con los recursos gráficos?

Si has sido atento también podemos encontrar el icono de la aplicación en una serie de carpetas que comienzan por el adjetivo drawable. Estas carpetas se relacionan directamente con el tipo de densidad de pantalla donde se ejecutará nuestra aplicación.
Android Studio, drawables
La mayoría de dispositivos móviles actuales tienen uno de estos 4 tipos de densidades:
  • Mediun Dots per Inch(mdpi): Este tipo de pantallas tienen una densidad de 160 puntos por pulgada.
  • High Dots per Inch(hdpi): En esta clasificación encontraremos teléfonos cuya resolución es de 240 puntos por pulgada.
  • Extra high dots per inch(xhdpi): Resoluciones mayores a  340 puntos por pulgada
  • Extra Extra high dots per inch(xxhdpi): Rangos de resoluciones mayores a 480 puntos por pulgada.

Miremos una pequeña imagen ilustrativa:
Densidades de pantalla en teléfonos móviles
La imagen muestra algunos ejemplos de dispositivos móviles cuya densidad se encuentra dentro de los rangos establecidos. Al final podemos ver una categoría extra llamada xxxhdpi. Esta denominación describe a la densidad de televisores de ultima generación que ejecutan Android.
Sería excelente que definieras todos tus recursos gráficos en los distintos tipos de densidades. Esta diversidad permitirá mayor compatibilidad con distintos dispositivos móviles.

¿Que es eso del archivo R.java ?

El archivo R.java es una archivo que se autogenera dento de la carpeta build, para linkear todos los recursos que tenemos en nuestro proyecto al código Java.
Android Studio, R.java
Si abres el archivo podremos ver un código similar a este:
/*AUTO-GENERATED FILE. DO NOT MODIFY. *
* This class was automatically generated bythe
* aapt tool from the resource data itfound. It
* should not be modified by hand. */

package comherprogramaciontest;
public final class R {
  public static final class attr {
  }
  public static final class dimen {
  public static final int activity_horizontal_margin=0x7f040000;
  publicstaticfinalint activity_vertical_margin=0x7f040001;
  }
  public static final class drawable {
  publicstaticfinalint ic_launcher=0x7f020000;
  }
  public static final class id {
  public static final int action_settings=0x7f080000;
  }
  public static final class layout {
  publicstaticfinalint activity_my=0x7f030000;
  }
  public static final class menu {
  publicstaticfinalint my=0x7f070000;
  }
  public static final class string {
  public static final int action_settings=0x7f050000;
  public static final int app_name=0x7f050001;
  public static final int hello_world=0x7f050002;
  }
  public static final class style {
  /** Customize your theme here.

  */
  public static final int AppTheme=0x7f060000;
  }
}
Como ves, la clase R contiene clases anidadas que representan todos los recursos de nuestro proyecto. Cada atributo tiene un dirección de memoria asociada referenciada a un recurso en especifico. Por ejemplo, la clase string posee el atributo hello_world, el cual representa nuestro TextView en la actividad principal. Este recurso esta ubicado en la posición 0x7f050002.
No modifiques el archivo R.java, el se actualiza automáticamente al añadir un nuevo elemento al proyecto.

¿Y el codigo Java?

Justamente era lo que iba a decir. Finalmente llegamos a la carpeta "java". Aquí se alojarán todos los archivos relacionados con nuestras actividades y otros archivos fuente auxiliares.
Android Studio, java
Al abrir nuestro archivo MyActivity.java veremos toda la lógica necesaria para que la actividad interactúe de manera correcta con el usuario.
package comherprogramaciontest;
import androidappActivity;
import androidosBundle;
import androidviewMenu;
import androidviewMenuItem;
public class MyActivity extends Activity {
  @Override
  protected void onCreate(Bundle savedInstanceState){
  superonCreate(savedInstanceState);
  setContentView(Rlayoutactivity_my);
  }
  @Override
  public boolean onCreateOptionsMenu(Menu menu){
  // Inflate the menu;this adds items to the actionbar if it is present.
  getMenuInflater().inflate(Rmenumy, menu);
  return true;
  }
  @Override
  public boolean onOptionsItemSelected(MenuItem item){
  // Handle action bar item clicks here. The actionbar will
  // automatically handle clicks on the Home/Upbutton, so long
  // as you specify a parent activity inAndroidManifest.xml.
  int id = itemgetItemId();
  if(id == Ridaction_settings){
  return true;
  }
  return superonOptionsItemSelected(item);
  }
}
Para toda actividad creada debemos extender una subclase de la superclase Activity. Mas adelante veremos que una actividad tiene un ciclo de vida y lo único que esta bajo nuestro control es la manipulación de cada estado.
Si ya notaste, las actividades no tiene un punto de entrada main(). Esto se debe a que las aplicaciones Android parten de múltiples puntos de ejecución. Pero esa característica será objeto de estudio del próximo articulo.James Revelo Urrea - Desarrollador independiente

Volver a la Portada de Logo Paperblog