jueves, 29 de diciembre de 2011

Resources

Haciendo una gran separación de lo que nos podemos encontrar en un proyecto de Android, podemos decir que tenemos dos cosas; el código JAVA y los recursos.

El código JAVA todos (o casi todos) sabemos lo que es y lo que hace...pero y los recursos?. Pues los recursos no son más que ficheros en XML (la gran mayoría) y algún que otro binario (para imágenes, audio, etc). Estos ficheros serán los encargados de contener la información para pintar nuestra interfaz, cargar una lista desplegable con valores predeterminados, mostrar cadenas de texto, etc.

En Android, todo tiene su sitio y como tal, debemos establecer cada recurso en su lugar correspondiente (podemos inventarnos los nombres de los directorios, pero si lo hicieramos, no estaríamos siguiendo las Best-Practices de Android y sería un verdadero caos a la hora de trabajar en equipo). La gran mayoría de los recursos están contenidos en el directorio RES de nuestra aplicación, a excepción de los RAW que se alojan en un directorio aparte con ese mismo nombre. Para acceder a dichos recursos tenemos la famosa clase R, la cual indexa y da acceso a todos los recursos definidos. Vamos a ver qué subdirectorios y ficheros podemos tener y qué podemos almacenar en cada uno de ellos:
  • VALUES
    • strings.xml: almacena texto estático definido en formato XML como pares de clave-valor.
    • <?xml version="1.0" encoding="utf-8"?>
      <Resources>
       <!-- Pre-defined Strings -->
          <string name="hello">Hello World!</string>
          <string name="app_name">Resources</string>
          <!-- Own Strings -->
          <string name="txtAceptar">Aceptar</string>
      </Resources>
      El atributo "name" identifica cada entrada y será el nombre por el que nos referiremos a ella cada vez que queramos hacer uso de su valor.  
      Accediendo a su valor
      -XML: por ejemplo para establecer el texto de un control en la definición de un layout con el formato "@string/[Name]":
      <TextView 
       android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:text="@string/txtAceptar"/>
      
      -JAVA: usamos el método getString([String-Name]) 
      String str = this.getString(R.string.txtAceptar);
       
      • arrays.xml: como su propio nombre indica, almacena arrays definidos en formato XML.
      • <?xml version="1.0" encoding="utf-8"?>
         <resources>
             <array name="miarray">
                 <item>Item1</item>
                 <item>Item2</item>
             </array>
         </resources>
        El atributo "item" identifica cada entrada.  
        Accediendo a su valor
        -XML: por ejemplo para establecer el contenido de una lista desplegable (Spinner) a traves de la propiedad "entries" con el formato "@array/[Name]":
        <Spinner
             android:layout_width="fill_parent"
             android:layout_height="wrap_content"
             android:entries="@array/miarray"/>
        
        -JAVA: para acceder a la matriz, necesitamos un "ContextWrapper" (getResources), otorgándonos acceso a todos los recursos.
        //Arrays de cadena
        String[] str_arr = this.getResources().getStringArray(R.array.miarray);
        //Arrays de enteros
        int[] int_arr = this.getResources().getIntArray(R.array.my_int_array);

      • colors.xml: almacenaremos los distintos colores que vayamos a usar en la aplicación. Se define en formato XML.
      • <?xml version="1.0" encoding="utf-8"?>
         <resources>
             <!-- definición hexadecimal como HTML: -->
             <color name="error">#FF0000</color>
             <!-- definición hexadecimal (#AARRGGBB) definiendo el canal alfa -->
             <color name="fondo">#F0053781</color>
         </resources>
        El atributo "name" identifica cada entrada y será el nombre por el que nos referiremos a ella cada vez que queramos hacer uso de su valor.  
        Accediendo a su valor
        -XML: por ejemplo para establecer el color de fondo y del texto de un control en la definición de un layout con el formato "@color/[Name]":
        <TextView 
             android:layout_width="fill_parent"
             android:layout_height="wrap_content"
             android:text="@string/hello"
             android:background="@color/fondo"
             android:textColor="@color/error"/>
        
        -JAVA: a traves del ContextWrapper.
        TextView tex = (TextView) this.findViewById(R.id.text);
        tex.setTextColor( this.getResources().getColor(R.color.error) );

        • dimens.xml: almacena dimensiones predefinidas en formato XML. Las unidades pueden ser in, mm y pt (pulgadas, milímetros y puntos respectivamente basados en la pantalla) y dp y sp (píxeles independientes del dispositivo y de la escala) que permiten un trabajo más facil con la variada gama de tamaños de los diversos dispositivos.
        • <?xml version="1.0" encoding="utf-8"?>
           <resources>
               <dimen name="dimension_milimetros">12mm</dimen>
               <dimen name="dimension_pulgadas">12in</dimen>
           </resources>
          El atributo "name" identifica cada entrada y será el nombre por el que nos referiremos a ella cada vez que queramos hacer uso de su valor.  
          Accediendo a su valor
          -XML: por ejemplo para establecer el tamaño de un control en la definición de un layout con el formato "@dimen/[Name]":
          <TextView 
               android:layout_width="@dimen/dimension_milimetros"
               android:layout_height="@dimen/dimension_pulgadas"
           />
          
          -JAVA: a traves del ContextWrapper.
          float dim = this.getResources().getDimension(R.dimen.dimension_pulgadas);
             
          • styles.xml: almacena estilos y temas en formato XML. Debido a la extensión de los mismos, los estilos y temas los trataremos en un post a parte.

        • DRAWABLE: aquí se almacenaran los iconos e imagenes de nuestra aplicación. Dependiendo de la resolución de la pantalla de nuestro terminal, podemos diferenciar tres subcarpetas:
          • drawable-hdpi: alta definición, formato WVGA(480 X 800 DPI).
          • drawable-mdpi: media definición, formato HVGA(320 X 480 DPI).
          • drawable-ldpi: baja definición, formato QVGA(240 X 320 DPI).
          Accediendo a su valor
          -XML: sólo hay que especificar el nombre de la imagen con el formato "@drawable/[NombreArchivo]":
          <ImageView
               android:layout_width="fill_parent"
               android:layout_height="wrap_content"
               android:src="@drawable/imagen_policia"
            />
          
          -JAVA: a traves del ContextWrapper con el formato "R.drawable/[Name]".
          ImageView view = (ImageView) this.findViewById(R.id.drawme);
          view.setImageResource(R.drawable.imagen_policia);

        • RAW: como comentamos antes, este directorio se aloja fuera del RES. Aquí se almacenaran archivos binarios de nuestra aplicación tales como videos, audios, páginas html, etc.
          Accediendo a su valor
          -JAVA: a traves del ContextWrapper con el formato "R.raw/[Name]".
          //Abrimos el fichero y vemos si tenemos algo
          InputStream ins = getResources().openRawResource(R.raw.config_db);
          int size = ins.available();
          //Leemos el contenido a un array de bytes.
          byte[] buffer = new byte[size];
          ins.read(buffer);
          ins.close();
          //Guardamos la copia del fichero
          FileOutputStream fos = new FileOutputStream("copia_config_db.db");
          fos.write(buffer);
          fos.close();
          

        • LAYOUT: son archivos XML generadores de las pantallas de nuestra aplicación. Esto ya ha quedado explicado en anteriores post.

        • MENU: aquí se almacenarán archivos XML para formar los menús de nuestra aplicación. Debido a la extensión de los mismos, estos menús los trataremos en un post a parte.

        • XML: en esta carpeta almacenaremos en formato XML los ficheros de configuración de nuestra aplicación. Debido a que son ficheros generados por nosotros, pueden tener la apariencia y estructura que nosotros queramos.
        • <?xml version="1.0" encoding="UTF-8"?>
           <root>
               <item>
                   <titulo>Google</title>
                   <descripcion>Buscador web.</abstract>
                   <link standalone="true">http://www.google.es</link>
               </item>
           </root>
          
          Para analizar el XML, usamos la clase "XmlResourceParser" que la veremos en otro post.

        Una muestra de nuestro proyecto con los recursos la tenemos a continuación en la siguiente captura:















        Maikel.

        martes, 27 de diciembre de 2011

        Layouts

        Los layouts son contenedores donde podremos almacenar nuestros controles. Entre las propiedades más utiles de este control podemos encontrar:
        • android:layout_width: indica la anchura del contenedor. Como constantes para esta propiedad tenemos:
          • fill_parent: la anchura del contenedor la establece el layout donde se encuentra contenido (si sólo tenemos un layout, la dimensión del control ocupará toda la pantalla a lo ancho).
          • match_parent: igual al anterior, el tamaño a lo ancho lo especifica el contenedor padre.
          • wrap_content: el ancho del contenedor será el mismo que tenga el control o controles que albergue.
          • variable: este no es una constante (como su nombre indica), sino que nosotros mismos le indicamos qué tamaño queremos para el contenedor (indicándolo mediante px, dp, etc.).
        • android:layout_height: igual que la anterior pero para la altura.
        • android:orientation: depende del tipo de layout, especificaremos orientación Horizontal o Vertical para posicionar los controles.
        • android:id: identificador para referirnos al layout. A través de este ID, accederemos a todas sus propiedades desde JAVA.
        • android:background: color de fondo del layout. El color se especifica en formato RGB hexadecimal con la opción de poder añadir un canal más para el Alpha. A grandes rasgos, este canal Alpha nos indica el nivel de transparencia que tendrá nuestro color. Los formatos para esta propiedad son:
          • #RGB
          • #ARGB
          • #RRGGBB
          • #AARRGGBB

        Los tipos de Layout disponibles son:
        • LinearLayout: cuando creamos una actividad nueva, por defecto trae este tipo de layout. Este contenedor nos agrupa los controles uno detrás de otro alineados a la izquierda. Dependiendo lo que le especifiquemos en su propiedad "orientation", nos agregará los controles de forma horizontal o vertical. En el siguiente código vemos un LinearLayout padre donde especificamos que el ancho sea el de la pantalla, su altura sea de 200dp, la orientación de los controles verticales y su color de fondo azul con el canal alfa transparente. Contiene otro LinearLayout donde especificamos que la anchura sea la que tenga el contenedor padre, la altura se adapte al control que contenga, la orientación de los controles verticales y el color de fondo rojo con una transparencia del 50%. Debido al canal alfa, el color es una mezcla entre el rojo especificado en este layout y del azul del padre, dando un tono morado.
        <?xml version="1.0" encoding="utf-8"?>
        <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="200dp"
            android:orientation="vertical" 
            android:background="#ff0000ff"
            android:id="@+id/lyEjemplo_layouts">
         
            <LinearLayout
                android:id="@+id/linearLayout1"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                android:background="#88ff0000">
        
                <TextView
                    android:id="@+id/textView1"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="Etiqueta 1" />
        
                <TextView
                    android:id="@+id/textView4"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="Etiqueta 2" />
        
            </LinearLayout>
         </LinearLayout>


        •  RelativeLayout: este contenedor permite especificar la posicion de cada elemento de forma relativa a su elemento padre, a otro elemento incluido en el mismo layout o incuso a otro layout. En el ejemplo, vemos como el control EditText01 se alinea a la derecha del control TextView01 y el control EditText02 se posiciona debajo y a la derecha del control EditText01.
        <RelativeLayout
                android:id="@+id/relativeLayout1"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" >
        
                <TextView
                    android:id="@+id/TextView01"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="Nombre:"
                    android:width="100px" />
        
                <EditText
                    android:id="@+id/EditText01"
                    android:layout_width="220px"
                    android:layout_height="wrap_content"
                    android:layout_below="@+id/RelativeLayout01"
                    android:layout_toRightOf="@+id/TextView01" />
        
                <EditText
                    android:id="@+id/EditText02"
                    android:layout_width="220px"
                    android:layout_height="wrap_content"
                    android:layout_alignRight="@+id/EditText01"
                    android:layout_below="@+id/EditText01" />
            </RelativeLayout>

        •  AbsoluteLayout: cada elemento que contenga este contenedor, deberá especificar las coordenadas X e Y en sus propiedades para situar al control dentro de su layout. Este método está obsoleto y se desaconseja su uso.
        • FrameLayout: indicado para contener un único elemento, ya que posiciona los controles a partir de su esquina superior izquierda uno encima del otro.
        <FrameLayout
                android:id="@+id/frameLayout1"
                android:layout_width="wrap_content"
                android:layout_height="match_parent" >
        
                <Button
                    android:id="@+id/button1"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="Button" />
        
                <TextView
                    android:id="@+id/textView1"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="Large Text"
                    android:textAppearance="?android:attr/textAppearanceLarge" />
            </FrameLayout>
        


        • TableLayout: contenedor basado en tabla. Se pueden añadir filas (TableRow) pero no columnas, es decir, las columnas las forman los controles que vamos añadiendo a las filas (un control, una columna). El tamaño de la columna suele corresponder al tamaño que tenga el control insertado, aunque hay propiedades del TableLayout que nos ayudan a manejar estos parámetros:
          • android:shrinkColumns: indica que columnas pueden contraerse cuando no hay sítio suficiente para mostrar todas las columnas en pantalla y se nos ocultan por la derecha.
          • android:stretchColumns: indica que columnas pueden expandirse si hay sitio suficiente a la derecha del control.
          • android:collapseColumns: indica que columnas queremos ocultar.
          • android:layout_span: análogo al atributo Colspan de HTML. Indica cuantas celdas contiguas ocupará la celda a la que se le aplique.
         Estas propiedades aceptan una lista de índices indicando las columnas afectadas, aunque también podemos hacer referencia a todas las columnas pasándole un asterisco (*).

        <TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:id="@+id/tableLayout1"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:collapseColumns="1"
            android:shrinkColumns="0"
            android:stretchColumns="0" >
        
            <TableRow
                android:id="@+id/tableRow1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" >
        
                <Button
                    android:id="@+id/button1"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="Button" />
        
                <Button
                    android:id="@+id/button2"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="Button" />
        
                <Button
                    android:id="@+id/button3"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="Button" />
            </TableRow>
        
            <TableRow
                android:id="@+id/tableRow2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" >
        
                <CheckBox
                    android:id="@+id/checkBox1"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:keepScreenOn="false"
                    android:text="CheckBox" />
            </TableRow>
        
            <TableRow
                android:id="@+id/tableRow3"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" >
        
                <Spinner
                    android:id="@+id/spinner1"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_span="2" />
            </TableRow>
        
        </TableLayout>
        



        Maikel.

        jueves, 22 de diciembre de 2011

        Primera aplicación sencilla

        Vamos a mostrar los pasos para crear una primera aplicación sencilla donde introduzcamos un nombre en una caja de texto y mediante un botón nos aparezca otra pantalla con el nombre introducido.

        Lo primero es crear un proyecto nuevo en eclipse, para ello pulsamos Ctrl+N o pinchamos en File --> New --> Other, apareciendo el asistente de creación de proyectos. Seleccionamos Android Project y nos aparecerá otra ventana donde pondremos el nombre de la aplicación y el target que queramos.









        A la hora de seleccionar el Target, vemos que para una misma plataforma podemos elegir el Target de Android o de Google APIs. ¿Cual es la diferencia? Pues si pensamos usar en nuestro proyecto Google Maps u otra librería específica de Google, deberíamos elegir el Target Google APIs. Si no vamos a usar nada de esto, seleccionaremos el Target de Android, que sólo incluye librerías del core de Android.







        En la última pantalla de configuración, nos pide que le introduzcamos el nombre del paquete y el nombre de la actividad inicial. En Java es muy comun poner el nombre del dominio en el nombre del paquete pero al reves, así que vamos a ello.









        Con esto, ya tendremos creado nuestro proyecto listo para codificar.








        Lo primero a realizar es remodelar la actividad principal de nuestra aplicación, ya que por defecto, Eclipse te monta un ejemplo "Hola Mundo" que a nosotros no nos hace falta. Hay que añadir una caja de texto y un botón y debemos hacerlo en el fichero main.xml. Si echamos un vistazo a este fichero, vemos que podemos editarlo en modo diseño o modo texto (yo lo haré por código). Dentro del Layout es donde debemos colocar nuestros controles, ya que un Layaout es un contenedor de controles (ya hablaremos de estos contenedores).
        El código debe quedar así:

        <?xml version="1.0" encoding="utf-8"?>
        <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:orientation="vertical" >
        
            <EditText 
               android:id="@+id/txtNombre"
               android:layout_width="fill_parent"
               android:layout_height="wrap_content"
                />
            
            <Button android:id="@+id/btnAceptar"
                android:text="@string/textoBoton"
                android:layout_width="wrap_content"
               android:layout_height="wrap_content"
                />
        
        </LinearLayout>
        

        Vamos por partes:

        • La propiedad ID: con la sintaxis @+id, estamos indicando que cuando compile, nos genere en la clase R.java una nueva constante referente al control que podremos usar más adelante en nuestro código.

        • La propiedad Text: con la sintaxis @string, estamos indicando que la cadena de texto la coja del fichero de constantes string.xml. También podemos poner el texto directamente mediante un string.

          Una vez conseguido esto, vamos a crear la pantalla que recojerá la cadena de texto y la mostrará por pantalla. Para ello, pulsamos Ctrl+N y nos aparece el asistente para crear nuevo elemento. Dentro de la carpeta Android, seleccionamos el componente Layout, ya que nosotros queremos crear una pantalla nueva.









          Luego de damos un nombre a nuestra nueva pantalla, seleccionamos que elemento root queremos implementar (seleccionamos LinearLayout para que nos cree el contenedor) y le damos a finalizar.












          En nuestra nueva pantalla sólo vamos a crear una etiqueta que muestre lo introducido en la caja de texto anterior. Debe quedarnos algo así:

          <?xml version="1.0" encoding="utf-8"?>
          <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:orientation="vertical" >
          
              <TextView 
                  android:id="@+id/lblMensaje"
                  android:layout_width="fill_parent"
                  android:layout_height="wrap_content"
                  />
          
          </LinearLayout>


            Con esto ya tenemos nuestras dos interfaces gráficas o Layouts. Ahora toca codificar lo que queremos que haga la aplicación cuando introduzcamos una palabra en la caja de texto y pulsemos el botón. Por tanto, nuestra clase ActividadInicial debe contener las siguientes líneas:

            • Declaramos las dos variables que harán referencia a nuestros controles.
            • private EditText txtCadena;
               private Button btnAceptar;
              

            • Referenciamos las variables a los controles.
            • txtCadena = (EditText) findViewById(R.id.txtNombre);
                btnAceptar = (Button) findViewById(R.id.btnAceptar);
              

            • Creamos el evento OnClick del botón.
            • btnAceptar.setOnClickListener(new OnClickListener() {
                 public void onClick(View v) {
                  pasarStringactividadFinal();
                 }
                });
              

            • Creamos la función llamada desde el evento que contiene la lógica para llamar a la siguiente actividad.
            protected void pasarStringactividadFinal() {
              // establecemos un texto por defecto si no tiene nada
              if (txtCadena.getText().length() == 0) {
               txtCadena.setText(R.string.txtDefecto);}
              // Creamos el Intent que llamará de una actividad a otra.
              // Como parámetros, para este constructor, necesitamos pasarle
              // el contexto actual y la clase de destino
              Intent intent = new Intent(this, ActividadFinal.class);
              // Creamos un objeto Bundle que es parecido a un Hash-Table o
              // tabla de clave-valor y le insertamos el valor a pasar
            //mediante la propiedad putString(clave,valor)
              Bundle ht = new Bundle();
              ht.putString("Parametro", txtCadena.getText().toString());
              // Añadimos la información al Intent mediante la propiedad
            //putExtras(bundle)
              intent.putExtras(ht);
              // Llamamos a la nueva actividad pasándole el intent
              startActivity(intent);
             }
            }
            

            La clase ActividadFinal debe contener la siguiente información:

            • Heredar de la clase Actividad y crear el evento onCreate enlazando mediante el
              ContentView el layout correspondiente (en este caso muestratextbox.xml).
            • public class ActividadFinal extends Activity {
               /** Called when the activity is first created. */
               @Override
               public void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.muestratextbox);
              
               }
              }
              
              

            • Mostramos por pantalla la cadena pasada
            • //Referenciamos el control para establecerle el texto
                TextView lblContenedor = (TextView)findViewById(R.id.lblMensaje);
                //Instanciamos un objeto Bundle para extraer los valores 
                //pasados desde la pantalla anterior
                Bundle ht = getIntent().getExtras();
                //Extraemos el valor de la clave correspondiente mediante la 
                //propiedad getString() y la enlazamos a la etiqueta para mostrarla por pantalla
                lblContenedor.setText("El texto introducido es " + ht.getString("Parametro")); 
               
              Por último, solo nos queda añadir en el fichero AndroidManifest.xml la nueva actividad creada.
              <activity android:name=".ActividadFinal"></activity>

            Entrada dedicada a Carmen Delgado, a ver si se pone pronto a programar ;-)

            Maikel.

            viernes, 16 de diciembre de 2011

            ¿Qué es eso de AC2DM?

            Las siglas de Android Cloud To Device Messaging (mensajería de la nube al dispositivo) hacen referencia al sistema por el cual Google conecta con las aplicaciones instaladas en el teléfono y le comunica que tiene datos para consumir. 

            Cuando tenemos una aplicación la cual debe actualizarse periodicamente, esta debe conectarse cada intervalo de tiempo al servidor de donde obtenga la información, preguntar si tiene alguna novedad y, si la tiene, descargarla (esto se conoce como Polling). ¿Qué pasa si no hay nada que descargar? Pues que estamos consumiendo batería y datos.

            A partir de la versión 2.2 de Android, Google ha introducido un nuevo sistema de comunicación entre el servidor y los dispositivos. Este nuevo sistema se conoce como mensajes Push, donde el servidor es el que conecta con el dispositivo cuando hay datos para la aplicación y le dice que se conecte al servidor para descargarlos. Con esto, nos aseguramos que las conexiones sólo son realizadas cuando realmente son necesarias.
            Otra ventaja que nos ofrece, es que la aplicación puede no estar ejecutándose en ese momento, ya que este mensaje push lanzara un Intent que levantará la aplicación. Tampoco necesitamos crearle interfaz gráfica a la hora de recibir la información, pero si queremos podemos crearle una o implementar alguna notificación en la barra de notificaciones.

            Para poder usar este servicio, es necesario registrarse en este enlace.

            Por ahora es una pequeña pincelada de algo que tiene muy buena pinta. Intentaremos trastear un poco y colgar alguna aplicacion de ejemplo.

            Maikel

            jueves, 3 de noviembre de 2011

            Ciclo de vida de una actividad en Android

            Algo esencial a la hora de programar aplicaciones, es saber de que manera se comportará nuestra aplicación a la hora de ejecutarla. Para ello, es imprescindible saber su ciclo de vida, algo necesario para saber dónde inicializar variables, crear o destruir objetos, o simplemente qué hacer cuando la aplicación llegue a su fin.

            Las actividades son gestionadas por el sistema mediante una pila de actividades. Cuando una nueva aplicación aparece, esta se situa al principio de dicha pila pasando a ser la actividad en ejecución (la actividad anterior no volverá a primer plano hasta que esta no termine).

            Según la documentación de Android, una actividad podemos encontrarla en 4 estados, aunque bajo mi punto de vista sólo son 3, ya que el cuarto es una combinación del segundo y tercero:

            1. Activa: cuando la actividad está la primera en la pila de actividades y es la que está en primer plano en el dispositivo.
            2. En pausa: cuando la actividad pierde el foco pero es todavía visible (se le superpone otra actividad en modo pantalla parcial o modo transparente). Esta actividad continua viva, manteniendo toda la información de estado, miembros, etc permaneciendo unida al gestor de ventanas. Si el sistema necesita memoria podrá matar la actividad. 
            3. Detenida:cuando hay otra aplicación tapando por completo a la activa (por ejemplo entra una llamada), la aplicación pasa a estar detenida. Dicha aplicación mantiene la información de estado, miembros, etc pero ya no está visible para el usuario, por lo que el sistema, en caso de necesitar memoria, puede eliminarla. 
            4. Pausa / Detenida: el sistema puede eliminar de la memoria una actividad en uno de estos dos estado preguntando si queremos finalizarla nosotros mismo o eliminarla el mismo sin preguntar. Cuando la actividad vuelva a estar visible, será necesario reiniciarla y restaurarla a su estado anterior.
             En el siguiente diagrama vemos como se gestionan estos estados y como se pasa de uno a otro:


            Cuando lanzamos la aplicación, se llama al método OnCreate(), donde inicializaremos los componentes esenciales de nuestra actividad (llamaremos a setContentView() para definir el diseño de la interfaz de usuario, crearemos las vistas, enlazaremos los datos, etc)

            Inmediatamente se llama al método OnStart() justo antes de que la actividad sea visible en el terminal. A partir de aquí, puede llamarse al método OnResume() o al método OnStop(), dependiendo de la focalización o no de la actividad.

            El método OnResume() se llama justo antes de que el usuario comience a interactuar con la actividad. 

            Después de este método se ejecuta el OnPause(). Este método se llama cuando el sistema está a punto de levantar otra actividad. Este método se utiliza normalmente para guardar cambios sin salvar, detener animaciones y otras cosas que puedan consumir recursos, etc. Este método debe ejecutarse rápidamente, ya que hasta que no concluya, el sistema no podrá levantarse la nueva actividad. A partir de aquí, puede llamarse al método OnResume() si la actividad vuelve de nuevo a primer plano, o llamar al método OnStop() si se convierte en invisible para el usuario.

            El método OnStop() se ejecuta cuando la actividad ya no es visible por el usuario debido a que está siendo destruida por el sistema o porque otra actividad se ha reanudado y se ha colocado encima. A partir de aquí, solo nos quedan tres opciones: llamar al método OnRestart() si queremos que la aplicación vuelva a primer plano, que el sistema la elimine por necesidad de memoria, o ejecutar el método OnDestroy() si queremos cerrar la actividad.

            El método OnDestroy() lo podemos llamar nosotros explícitamente porque queremos destruir la actividad o puede llamarlo el sistema si necesita memoria y está destruyendo actividades para conseguirlo. A partir de aquí, la actividad estará totalmente eliminada.

            Si tenemos esto en cuenta a la hora de programar, nos ahorraremos muchos fallos a la hora de ejecutar nuestra aplicación.

            Maikel.

            Componentes de una aplicación Android

            Los componentes que usaremos en una aplicación Android son los siguientes:
            • Activity: una activity es una pantalla de nuestra aplicación. Aquí insertaremos nuestros botones, cajas de texto, etc e interactuaremos con nuestra aplicación. Estas actividades pueden estar en primer o segundo plano.
            • Content Providers: permite acceder a los datos de forma controlada entre las aplicaciones, es decir, Android nos provee un almacén donde las aplicaciones pueden leer o modificar la información de cualquier aplicación (siempre y cuando las aplicaciones tengan permiso para hacerlo) como por ejemplo los contactos del teléfono. El almacén físico de la información puede ser desde el propio teléfono (memoria interna, SDcard, SQLite) hasta sitios remotos (mediante sockets).
            • Services: análogo a un servicio de windows. No tienen interfaz gráfica y estan corriendo en segundo plano. Un ejemplo sería el servicio de recepción de correo.
            • Broadcast Receivers: este componente es parecido a los servícios. Está latente esperando alguna notificación o evento por parte del sistema o de cualquier otra aplicación para desencadenar alguna acción. Es un listener sin pertenecer a ninguna aplicación en concreto. Un ejemplo de este componente puede ser el aviso de que se ha insertado una tarjeta de memoria, que una aplicación ha terminado de descargarse, etc.
            • Intents: las comunicaciones entre componentes de una misma aplicación o entre distintas aplicaciones se realizan a través de este componente. El sistema es quien controla estas comunicaciones y es el encargado de llevarlas a cabo o no. Estos intents pueden lanzar un servicio, levantar otra actividad, etc pero siempre es el sistema quien decidirá si hacerlo o no y mediante que aplicación ejecutarlo. Por ejemplo, si nuestra aplicación debe hacer uso en algún momento de la cámara de fotos, habrá un intents que solicitará al sistema esta necesidad y él mismo decidirá o no (dependiendo si la aplicación tiene permiso) levantar la actividad de capturar foto de la cámara. Mediante este control, no tenemos que volver a definir una función para el uso de la cámara, sino que utilizaremos una ya creada optimizando el código.
            Esto es una pequeña pincelada de cada componente, cuando empecemos a programar, seguro que nos queda un poco más claro el uso de cada uno.


            Maikel.

              miércoles, 2 de noviembre de 2011

              Estructura de un proyecto Android

              Cuando creamos un nuevo proyecto para android, nos encontramos con esta estructura:



              ¿Qué contiene cada carpeta?:

              SRC: esta carpeta contiene las clases y paquetes de nuestra aplicación, en definitiva, todo el código fuente que nosotros generemos. 

              GEN: esta carpeta almacena código autogenerado al compilar el proyecto. Lo más importante de aquí es el fichero R.java, donde vamos a tener identificadores de todos los recursos que disponemos en nuestra aplicación. Mediante esta clase, podremos acceder a dichos recursos en nuestra aplicación a través de ella mediante R.”clase”.”objeto”. 

              Android x.x.x: almacena las clases del SDK de Android de la versión que hayamos indicado en el target al comenzar el proyecto.

              RES: almacena todos los recursos de la aplicación, como iconos, imágenes, vídeos, cadenas de  valores,  layouts (que son componentes gráficos definidos en XML (estos componentes también se pueden definir mediante Java)), etc. 

              Las carpetas drawable-ldpi, drawable-mdpi y drawable-hdpi almacenarán las imágenes de nuestra aplicación dependiendo si la queremos en baja, media o alta resolución (low, medium, high)
              La carpeta “layouts” contendrá tantos ficheros como pantallas tenga nuestra aplicación. Almacena, por tanto, los ficheros de definición de nuestras interfaces gráficas.
              La carpeta “values” almacenará recursos de textos, estilos, etc.
              La carpeta RES al compilarse, genera un archivo R.java en la carpeta “GEN” con todo el contenido de dicha carpeta.

              AndroidManifest.xml: es un fichero XML esencial en un proyecto Android, ya que contiene información necesaria del proyecto, como el nombre del paquete JAVA de la aplicación, los componentes (actividades, servicios, broadcast receivers y content providers), permisos, API de Android, etc.

              ASSETS: contiene otros ficheros de configuración pero que no generarán código en el fichero R.

              BIN: contiene una carpeta COM, que almacena el compilado de Java con los .class.

              El fichero DEX es otra compilación realizada por Android a partir de la carpeta COM para que la Dalvik (la máquina virtual de Android) pueda ejecutarlo
              El APK es un paquete de todo lo que contiene el BIN. Este fichero es el que necesitamos para instalar la aplicación en el teléfono.

              Se puede profundizar mucho más en cada fichero, como se utiliza, etc, pero creo que a partir de aquí, podemos tener una idea un poco clara de cómo se estructura nuestra aplicación. A partir de aquí, solo queda empezar a programar.

              Maikel.