Búsqueda personalizada

Blog personal para aprender a programar en Android desde cero.

Mostrando entradas con la etiqueta Android Fundamentals. Mostrar todas las entradas
Mostrando entradas con la etiqueta Android Fundamentals. Mostrar todas las entradas

jueves, 11 de marzo de 2010

Application Fundamentals I


Como dije hace unos días, voy intentar resumir el articulo Application Fundamentals de Android Labs. Lo haré en dos partes.

Supongo que a estas alturas ya sabéis que el lenguaje de programación utilizado es Java. Así que para los que estamos familiarizados con este lenguaje, en principio no tendremos grandes problemas para empezar a programar en Android. Para los que no, quizás es recomendable empezar con algún tutorial de Java.

El código java compilado y los recursos utilizados en nuestra aplicación se empaquetan en un fichero de extensión APK (Android Package).
Este fichero APK lo podemos considerar como una aplicación, ya que por cada aplicación tenemos un fichero APK. Para instalarnos una aplicación debemos obtener su fichero APK, ya sea a través del Android Market o de algún otro medio.(Sí, es posible y legal)
Aunque el lenguaje de programación sea Java, las aplicaciones Android no trabajan de la misma manera. Gracias a la DalvikVM una aplicación tiene estas características:
  • Cada aplicación corre en un único proceso Linux.
  • Cada proceso corre en una VM.
  • Cada proceso es asignado a un único User ID.
Nota: este es el comportamiento normal, pero es posible que dos aplicaciones compartan el mismo UserID para ver los ficheros entre ellas. Y también correr en el mismo proceso compartiendo la misma VM.

Application Components
  • Activities: una Activity es una IU que realiza una actividad o acción. Una aplicación puede tener una simple Activity o varias. Por ejemplo, podemos tener una Activity que liste mensajes, otra que nos permita escribirlos, etc.. Todas estas acciones son clases que heredan de la clase Activity.
  • Services: es una acción sin IU pero que corre en modo background durante un tiempo indefinido. Por ejemplo, en una aplicación para escuchar música, probablemente tendremos una IU para escoger la(s) canción(es) que queremos escuchar, esto sería una Activity. En cambio, lo que es la reproducción de música en sí será un servicio, ya que si hacemos ostras cosas, como navegar, consultar el correo, etcétera, queremos seguir escuchando la música. Todas las clases que implementan servicios heredan de Service.
  • Broadcast Receivers: es un componente que aparentemente no hace nada, pero que recibe y reacciona a algunos eventos. Por ejemplo, cuando la batería esta baja, cambiamos de zona horaria, recibimos un mensaje (como en la imagen), etc.. Los broadcast receivers no tienen IU, pero suelen lanzar una Activity o un notificación a través del NotificationManager .Cada clase hereda de BrodcastReceiver

  • Content Provieders: los Content Providers hacen posible que cierta información de nuestra aplicación, sea accesible desde otras aplicaciones. Los datos podemos almacenarlos en sistema de ficheros con SQLite u otros medios. Nuestras clases Content Providers heredan de ContentProvider, y tendremos un conjunto de métodos con los que conseguir los datos que nos interesen. Un ContentProvider se activa cuando lo reclama un ContentResolver.
Intents
Los componentes ActivityBrodcastReceiver y Service se activan a través de unos mensajes asíncronos llamados Intents. Nuestros Intents heredan de la clase Intent y contienen el mensaje. A cada tipo componente se le llama de una manera distinta, pasándole la URI (entre otros parámetros):
Manifest
Para que Android pueda iniciar un componente de una aplicación debemos definirlo en un archivo xml. Este archivo se llama AndroidManifest.xml, y estará incluido en el paquete APK junto con los demás recursos.
Además de declarar los componentes, en este fichero también tenemos que incluir las bibliotecas que necesita la aplicación, y también determinar los permisos que el usuario deberá otorgar a la aplicación para su correcto funcionamiento.
Un ejemplo:


                  <?xml version="1.0" encoding="utf-8"?>
                      <manifest . . . >
                          <application . . . >
                               <activity android:name="com.example.project.FreneticActivity"
                                             android:icon="@drawable/small_pic.png"
                                             android:label="@string/freneticLabel" 
                                            . . .  >
                               </activity>
                                . . .
                          </application>
                    </manifest>

En el atributo de name de la <activity> tenemos la subclase de Activity que implimenta la funcionalidad. El icon (icono) y la label (etiqueta) apuntan a los ficheros del directorio de recursos /res/drawable que contiene un icono y una etiqueta.
Los demás componentes (<service><receiver><provider>) se declaran de una forma similar. Los componentes que no se declaran en el AndroidManifest.xml nunca se podrán ejecutar porque no son visibles para la aplicación. Sin embargo, los <broadcastReceiver> pueden ser declarados tanto en el AndroidManifest como en hardcode. Para ello deberán registrarse con la llamada Context.registerReceiver().
Esta mini-introducción del AndroidManifest.xml se puede completar con The AndroidManifest.xml File.

Intent Filters
Un objecto Intent puede llamar explícitamente a un componente. Gracias al AndroidManifest.xml, Android lo puede encontrará y lo activará. Pero si la llamada no es explícita, Android debe localizar el componente que mejor corresponda a la llamada. Android consigue hacer esto gracias a los IntentFilters. Un IntentFilter le indica a Android cual es el mejor handler para ese tipo de componente. Cosa que también declararemos en el AndroidManifest.xml. Completando el ejemplo anterior:



                <?xml version="1.0" encoding="utf-8"?>
                       <manifest . . . >
                           <application . . . >
                                <activity android:name="com.example.project.FreneticActivity"
                                              android:icon="@drawable/small_pic.png"
                                              android:label="@string/freneticLabel" 
                                        . . .  >
                                     <intent-filter . . . >
                                            <action android:name="android.intent.action.MAIN" />
                                            <category android:name="android.intent.category.LAUNCHER" />
                                     </intent-filter>
                                     <intent-filter . . . >
                                           <action android:name="com.example.project.BOUNCE" />
                                           <data android:mimeType="image/jpeg" />
                                           <category android:name="android.intent.category.DEFAULT" />
                                     </intent-filter>
                              </activity>
                                  . . .
                           </application>
                       </manifest>

El primer <intent-filter> del ejemplo (la combinación de "android.intent.action.MAIN" y "android.intent.category.LAUNCHER") es muy común, ya que indica que esta Activity es el punto de entrada de la aplicación y que se mostrará en el menú de aplicaciones que puede ejecutar el usuario.
En el segundo <intent-filter> se declara una Activity que podrá manejar datos de tipo image/jpg. "android.intent.category.DEFAULT" es la category que pondremos cuando nuestra Activity no sea ninguna otra específica.
Un componente puede tener cualquier número de IntentFilter. Si no tienen ninguno puede ser activado solamente cuando se llame explícitamente desde el código.

Para completar esta info Intents and Intent Filters.



domingo, 28 de febrero de 2010

Hello World / Hello Android

Una vez tenemos el entorno preparado vamos hacer nuestro primer proyecto. Siguiendo como guía Android Labs, nos recomiendan hacer el típico HelloWorld.
Los pasos que nos indican son los siguientes:
  1. Crear el AVD, que ya hicimos en el último paso del post anterior.
  2. Crear el projecto en Eclipse.
  3. Construir la Interfaz de Usuario dentro de la clase.
  4. Ejecutar la aplicación.
Esta manera de crear la interfaz de usuario dentro del código se llama programática. Puede ser útil para interfaces sencillas, y también se puede utilizar para crear algún elemento de manera dinámica. Pero esta forma es difícil de mantener, y por ello Android ofrece la posibilidad de crear las IU a partir de layouts en ficheros XML. Por ejemplo:



<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:text="@string/hello"/>

¿Dónde ubicamos estos ficheros XML? Primero vamos a ver la estructura de directorio:


  • src/: código de nuestras clases
  • gen/: código generado
  •  assets/: desconozco!
  • res/drawable/: imágenes
  • res/layout/: layouts para nuestra IU
  • res/value/: textos 

Para más detalles, recomiendo mirar Application Fundamentals. En los próximos post intentaré explicar de manera sencilla el contenido de esta página.

Ya hemos acabado con nuestro HelloWorld!! Si ejecutamos veremos que los resultados son iguales, tanto creando la IU programáticamente como con layouts.

Problemas
La guía de Android Labs es bastante sencilla de seguir, pero durante la realización me encontré con un problema. Después de estar jugando con los ficheros, me daba el siguiente error:
main.out.xml already defined
Después de googlear un rato no supe cuál era el motivo, pero lo solucioné eliminando el archivo main.out.xml a mano.