viernes, 24 de julio de 2009

Notificando al usuario

Notificar al usuario siempre ha sido importante, no está bien que ocurran las cosas y que el usuario no se de cuenta de qué está pasando...

  • Toast Notification: es un mensaje que aparece encima de la ventana actual. Solo tapa el espacio requerido para presentar el mensaje en un area rectangular de la ventana. La Activity continua operativa y visible mientras que el mensaje aparece tapando una sola porción como ya mencionamos anteriormente. Este tipo de notificación no acepta interacción con el usuario hace un efecto de fade-in y de fade-out, vamos que aparece con suavidad y desaparece con suavidad - paleta de colores. Puede aparecer incluso cuando la aplicación no es visible ya que éste tipo de notificación puede crearse desde un Service en el background o fondo, osea, donde no lo ven tus ojos (Un Service no se dibuja en la pantalla). Este tipo de mensajes es recomendable utilizarlos con strings cortas como "Fichero guardado", o "Me estas engañando...", lo que se te ocurra pero que sea corto..ok?. Si necesitas interacción con el usuario es mejor utilizar un Status Bar Notification en su caso.
  • Status bar notification: Este tipo de notificación añade un icono a la barra de estado del sistema con un mensaje -opcional- de esos con scroll sip (ticker significa con scroll aka) y el mensaje se expande en la ventana de notificaciones "Notifications" window. Cuando el usuario expande el mensaje el Android dispara (lanza) un Intent (Una operación a realizar) que está definida por la notificación (normalmente lanza una Activity). Incluso puedes configurar la notificación para reproducir un sonido y todo si lo deseas, vibrador, flash,etc. Este tipo de notificación es ideal cuando la aplicación está trabjando en background como un Service y necesite notificar al usuario sobre un evento ocurrido. Si necesitas enviar una alerta al usuario sobre un evento que ocurre mientras el Activity sigue con el cursor (focus), se recomienda utilizar en su caso Dialog Notification en vez de éste tipo de notificación.
  • Dialog Notification: Este diálogo acepta interacción con el usuario. El Activity pierde el focus y lo gana el diálogo. Por eso es mejor utilizar éste en caso del de la barra de estado (el punto anterior) ya que si necesitas traer al frente con esta notificación le quitas el focus al Activity. Usarlo para mostrar progresos de estado o que el usuario valide alguna acción crítica entre otras situaciones.

Eventos de usuario en Android

Básicamente están los Event Listeners y los Event Handlers.

Los Event Listeners son una interfaz en la clase View que contienen metodos callback. Esos métodos son llamados por el framework de Android cuando la View con la que el listener ha sido registrada es lanzada por la interacción del usuario con la interfaz gráfica. Algunos de éstos métodos son onClick() , onFocusChange(),etc,etc.

Los Event Handlers son utilizados para crear nuestros propios eventos cuando creamos componentes personalizados desde una View.

Todo esto de los eventos ya lo revisaremos mas adelante directamente con un ejemplo.

Con estas nociones básicas mirarse la documentación de Android para Eventos.

Creando dialogos

No recordais los DialogBox famosos en Win32? pues lo mismo, Dialog.

Aqui los definen como una ventana de diálogo que aparece en frente, en este caso en frente de la Activity que tenias al frente un instante antes de presentarse la ventana de diálogo. La Activity dueña (Owner) del diálogo.


Android soporta cuatro tipos diferentes de diálogo que veremos a continuación:

  1. AlertDialog: Puede contener desde ningun boton hasta tres botones o bien una lista de elementos entre los cuales pueden incluirse checkboxes o radio buttons. Este es el tipo de ventana de diálogo recomendado a utilizar en la mayoría de las aplicaciones. AlertDialog hereda de la clase Dialog.
  2. ProgressDialog: Implementa una barra de progreso o la tipica rueda de progreso, hereda de la clase AlertDialog y por lo tanto también soporta botones.
  3. DatePickerDialog: Este diálogo permite seleccionar una fecha.
  4. TimePickerDialog: Este diálogo permite seleccionar una hora.
Un Dialog siempre se crea y se presenta como parte de una Activity. Normalmente los creamos dentro de onCreateDialog(int) que es un metodo callback de la Activity. En caso de crear el diálogo fuera de la llamada callback de la Activity, entonces podras indicar que Activity es la dueña del diálogo mediante setOwnerActivity(Activity).

Para mostrar un diálogo, llama a showDialog(int) y pasale como parámetro un entero unico que identifica el diálogo que quieres mostrar.

static final int DIALOG_GAMEOVER_ID = 1; // int único o id del diálogo.



Mas información en la documentación de Android para Diálogos

Menus en Android

Hay tres clases de Menus:

1.- Options menu: Son los que aparecen cuando pulsas la tecla MENU. Soportan un máximo de seis elementos por menu y si hace falta mostrar mas elementos se abre otro grupo de elementos expandidos de forma vertical.

2.- Context menu: Son aquellos que aparecen como una lista flotante cuando dejas una tecla pulsada durante un tiempo prolongado sobre una View.

3.- Submenu: Otra lista flotante de elementos que sirve para añadir subopciones a los options o los context menus. No se pueden crear Submenus anidados de otros submenus.

Snippet de ejemplo:

/* Creates the menu items */
/*
* --- Esto es un callback que hay que sobreescribir en la Activity ---
*/
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, MENU_NEW_GAME, 0, "New Game");
menu.add(0, MENU_QUIT, 0, "Quit");
return true;
}

/* Handles item selections */
/*
* --- Esto es otro callback que hay que sobreescribir en la Activity ---
* --- Ocurre cuando se selecciona una opcion del menu aki hacemos ---
*/

public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case MENU_NEW_GAME:
newGame();
return true;
case MENU_QUIT:
quit();
return true;
}
return false;
}

// Ambos callbacks ocurren en el Activity.


Para mas información sobre los menus la documentación de Android > menus

jueves, 23 de julio de 2009

Interfaz de usuario en un Activity con Layout

Un Layout es la arquitectura de la interfaz de usuario en una Activity. Este define la estructura del Layout y contiene todos los elementos que se muestran al usuario. Los Layouts se pueden declarar de dos maneras:

  1. Declarando los elementos de la interfaz de usuario en el XML.
  2. Instanciando los elementos del layout en tiempo de ejecución mediante código.
La ventaja de declarar los elementos de la interfaz de usuario en el XML es que separas la capa de presentación del código.

vease: http://developer.android.com/guide/topics/resources/available-resources.html#layoutresources

Cada Layout debe contener un elemento raiz(root), el cual debe ser una View o un ViewGroup. Una vez definido el elemento raiz(root), puedes añadir Layouts adicionales o widgets como elementos hijos para construir una jerarquía de Views que definen el Layout.
Por ejemplo LinearLayout contiene un TextView y un Button.

Dentro de los XML podremos visualizar como algunos elementos llevan el atributo id de la siguiente manera:

android:id="@+id/my_button"

La @ quiere decir que el parser trate el resto de la string como un ID y el signo + que es un nuevo recurso y debe ser creado y añadido a los recursos.

Ejemplo:
Definimos una View/Widget en el fichero de layout y le asignamos una ID única:

<button id="@+id/my_button" layout_width="wrap_content" layout_height="wrap_content" text="@string/my_button_text"/>


Para crear una instancia de la View y capturarla del layout hacemos esto:
Button myButton = (Button) findViewById(R.id.my_button);

Posición del layout:
getLeft(), getTop(), getRight() ,getBottom()

Tamaño, desplazamiento y margenes:
getMeasuredWidth() , getMeasuredHeight(), getWidth(), getHeight(), setPadding(int, int, int, int), getPaddingLeft(), getPaddingTop(), getPaddingRight(), getPaddingBottom()

BroadcastReceiver Class - Vista rápida

BroadcastReceiver

La clase base que recibe Intents enviados por sendBroadcast(). Puedes registrar dinámicamente una instancia de ésta clase con Context.registerReceiver() o estáticamente publicando una implementación a través del tag en el archivo de Manifiesto "AndroidManifest.xml".

Cuidado!
Si estás registrando un receiver en la implementación de Activity.onResume(), debes eliminarlo con Activity.onPause(). (No querrás recibir Intents cuando esté en pausa, esto ahorra un consumo innecesario de los recursos del sistema).

  • Normal broadcasts. Son enviados con Context.sendBroadcast y son asincronos. Todos los receivers de broadcast se ejecutan en orden indefinido, a menudo al mismo tiempo. Esto es mas eficiente, pero significa que los receivers no pueden usar las APIs result or abort usadas aqui.
  • Ordered broadcasts. Son enviados con Context.sendOrderedBroadcasts y son enviados a su destinos en ese momento. Cada receiver ejecuta en turno, esto puede propagar un resultado al siguiente receiver, o puede abortar el broadcast si no se quiere pasar a otros receivers. El orden de ejecución de los receivers puede ser controlado con el atributo android:priority en el filtro intent-filter; receivers con la misma prioridad serán ejecutados en un orden arbitrario.

Ciclo de vida de un receiver.

Un objeto BroadcastReceiver es solo válido durante la llamada a onReceive(Context, Intent). Una vez que retorna de ésta función el sistema considera que el objeto debe finalizar y no estar mas tiempo activo.

Esto significa que no puedes realizar operaciones asíncronas utilizando onReceive porque debes retornar de la función para manejar la operación asíncrona y en este punto el objeto ha sido finalizado por el sistema y deja de estár activo y el sistema se toma su libertad de matar el
proceso antes de que se pueda realizar la operación asíncrona por completo. Debes utilizar la API NotificationManager en su lugar

Información mas detallada de la clase en la documentación de Android

Service Class - Vista rápida

Service Class

Un Service es un componente de la aplicacion que se ejecuta en background o de fondo, no interactua directamente con el usuario, y se ejecuta por un periodo de tiempo indefinido. Cada clase Service debe tener una declaración en el archivo de Manifiesto "AndroidManifest.xml". Los Services pueden lanzarse con Context.startService() y Context().bindService().

Hay dos razones por las cuales un Service puede ser ejecutado por el sistema. Si alguien llama al metodo Context.startService() entonces el sistema obtendra el servicio (lo creará y llamará a su método onCreate() en caso necesario) y entonces llamará a su método onStart(Intent,int) con los argumentos pasados por el cliente. En éste punto el Service continuará ejecutándose hasta que sea llamado el método Context.stopService() o stopSelf().

Mas en la documentación de la clase...