Archivos para la Categoría 'Android'

Programando en Android - NotePad (II)

La clase NotesList
La actividad principal de la aplicación NotePad es NotesList, como se puede ver en el manifest. La clase NotesList se define en el archivo NotesList.java, y es la responsable de la pantalla principal de la aplicación, mostrando una lista de las notas disponibles. Para ello hacemos que esta clase herede de ListActivity, un tipo de actividad especial diseñada para enlazarse a un cursor y mostrar los elementos del cursor en una lista.

Al iniciar la aplicación se invoca esta clase a través de su método onCreate:

   1: @Override
   2: protected void onCreate(Bundle icicle) {
   3:     super.onCreate(icicle);
   4:
   5:     setDefaultKeyMode(SHORTCUT_DEFAULT_KEYS);
   6:
   7:     Intent intent = getIntent();
   8:     if (intent.getData() == null)
   9:         intent.setData(NotePad.Notes.CONTENT_URI);
  10:
  11:     setupListStripes();
  12:
  13:     Uri uri = intent.getData();
  14:     mCursor = managedQuery(uri, PROJECTION, null, null);
  15:
  16:     ListAdapter adapter = new SimpleCursorAdapter(this,
  17:             R.layout.noteslist_item, mCursor,
  18:             new String[] {NotePad.Notes.TITLE},
  19:             new int[] {android.R.id.text1});
  20:     setListAdapter(adapter);
  21: }

En la línea 5 simplemente habilitamos los atajos de teclado. Las líneas 7-9 establecen el esquema de datos sobre el que vamos a operar, que se define en la clase NotePad. Lo veremos más adelante.

Las líneas 13 y 14 acceden a los datos. Las referencias a los orígenes de datos son objetos de tipo Uri, y en nuestro caso tienen esta forma:

   1: public static final Uri CONTENT_URI =
   2:     Uri.parse("content://com.google.provider.NotePad/notes");

El enlace entre este Uri y la base de datos se realiza en la clase NotePadProvider, que veremos en otra entrada. Basta decir por ahora que la línea 14 accede a la base de datos para abrir un cursor con las columnas especificadas por PROJECTION, que se define al comienzo de la clase NotesList:

   1: private static final String[] PROJECTION = new String[] {
   2:     NotePad.Notes._ID, NotePad.Notes.TITLE };
   3: private Cursor mCursor;

Como decíamos al principio, la actividad NotesList hereda de ListActivity, lo que le permite mostrar datos en una lista. Para ello creamos un adaptador ListAdapter, como se muestra en las líneas 16-19. La clase SimpleCursorAdaptor es un creador genérico de adaptadores, al que indicamos el layout que vamos a usar (en nuestro caso R.layout.noteslist_item), el cursor que hemos definido, los nombres de las columnas a mostrar (en este caso sólo el título), y los ids de los controles (tienen que ser del tipo TextView) que van a mostrar cada columna. ´

Finalmente el método setListAdapter asigna el ListAdapter a nuestra actividad para mostrar los datos.

Nos queda por ver el método setupListStripes:

   1: private void setupListStripes() {
   2:     Drawable[] lineBackgrounds = new Drawable[2];
   3:
   4:     lineBackgrounds[0] =
   5:         getResources().getDrawable(R.drawable.even_stripe);
   6:     lineBackgrounds[1] =
   7:         getResources().getDrawable(R.drawable.odd_stripe);
   8:
   9:     View view = getViewInflate().inflate(
  10:             android.R.layout.simple_list_item_1, null, null);
  11:     TextView v = (TextView)view.findViewById(android.R.id.text1);
  12:     v.setText("X");
  13:     v.measure(
  14:         View.MeasureSpec.makeMeasureSpec(View.MeasureSpec.EXACTLY, 100),
  15:         View.MeasureSpec.makeMeasureSpec(View.MeasureSpec.UNSPECIFIED, 0)
  16:         );
  17:     int height = v.getMeasuredHeight();
  18:     getListView().setStripes(lineBackgrounds, height);
  19: }
Este método es el encargado de dibujar líneas de colores distintos para el fondo de la ventana. Para ello definimos dos objetos Drawable, que no es más que una clase genérica para objetos dibujables, y a cada uno le asignamos un color (los colores se definen en el archivo colors.xml).
Las líneas 10 y 11 instancian una vista estándar para mostrar elementos de una lista, y la 12 obtiene el objeto TextView correspondiente al control que previamente hemos visto que mostrará la columna título de las notas.
Las líneas 12-16 hacen lo siguiente: escriben una ‘X’ en el control, luego le piden al control que decida las medidas necesarias para mostrar la información, definiendo un ancho máximo y dejando libertad al alto, para que ocupe lo que necesite. Luego obtenemos ese alto, que será el necesario para que el control muestre letras mayúsculas.
La línea 18 llama al método setStripes de la vista asociada a nuestra actividad, que se encarga de establecer un fondo con líneas alternas de los colores definidos al principio y la altura obtenida.
En la próxima entrada hablaremos del menú y de como interactuar con las notas mostradas.

Entradas anteriores:

Programando en Android - NotePad (I)
Programando en Android - Conceptos iniciales (II)
Programando en Android - Conceptos iniciales (I)
Programando en Android - Prólogo

Programando en Android - NotePad (I)

La mayoría de los mortales olvidamos cualquier conocimiento abstracto en la décima parte del tiempo que nos costó adquirir dicho conocimiento (dato completamente inventado, pero en mi caso muy próximo a la realidad). Así que lo que vamos a hacer en concretar este conocimiento, y ponernos a programar.

El programa NotePad es un ejemplo que se incluye en la documentación de Google y en la SDK. Es un programa muy simple: permite crear notas, editarlas, borrarlas y modificar el título. Vamos a ver cómo funciona.

El ejemplo NotePad. El archivo Manifest.

Comencemos por el Manifest, que es donde se definen los componentes de la aplicación. El manifest.xml es, como su extensión indica, un archivo xml, que desde hace unos años se convertido en un formato habitual para contener configuraciones. El elemento raíz se llama manifest y contiene el namespace de la aplicación. Dentro se define el elemento aplicación:

<application android:icon="@drawable/app_notes" android:label="@string/app_name">

Aquí asociamos un nombre y un icono a la aplicación. La ‘@’ nos indica una referencia a un recurso. En general tiene este formato: @[package:]type/name, donde el paquete es opcional y sólo se indica cuando no pertenece a nuestra aplicación, el tipo corresponde a uno de los definidos en la carpeta res, y el nombre indica el identificador del recurso.  En nuestro caso, el icono se encuentra bajo la carpeta drawable, y la app_name se define en el archivo strings.xml de la carpeta values.

Dentro del elemento application lo primero que aparece es un provider, que nos dará acceso a la base de datos y que veremos más adelante. Tras él podemos ver definidas tres Activities: NotesList, NoteEditor y TitleEditor. Corresponderán a cada una de las ventanas: la que muestra las notas, la que las edita y la que modifica el título. Por ejemplo, este el elemento TitleEditor:

<activity android:name="TitleEditor" android:label="@string/title_edit_title" android:theme="@android:style/Theme.Dialog">

Además de indicar el nombre de la actividad, y la etiqueta que aparecerá en la ventana asociada, también especificamos que vamos a utilizar un tema concreto para esta actividad. Los temas nos permiten cambiar el look&feel de las aplicaciones con temas predefinidos o creados por nosotros. En este caso podemos ver como el recurso correspondiente al tema se referencia a través del paquete android, ya que está definido en el sistema, no en nuestra aplicación.

Dentro de cada activity hay definidos intent-filters, que permiten concretar el ámbito en el que se van a ejecutar, como ya vimos anteriormente. Por ejemplo, en NotesList encontramos:

<intent-filter>
<action android:name=”android.intent.action.MAIN” />
<category android:name=”android.intent.category.LAUNCHER” />
</intent-filter>
;

que indica que esta es la actividad principal de la aplicación, y que aparecerá en el menú de aplicaciones del sistema. El filtro

<intent-filter>
<action android:name=”android.intent.action.VIEW” />
<action android:name=”android.intent.action.EDIT” />
<action android:name=”android.intent.action.PICK” />
<category android:name=”android.intent.category.DEFAULT” />
<data android:mimeType=”vnd.android.cursor.dir/vnd.google.note” />
</intent-filter>

nos indica que la actividad está disponible para ver, editar o seleccionar elementos del tipo vnd.android.cursor.dir/vnd.google.note, que es el tipo que definiremos más adelante para las notas. Finalmente, el filtro

<intent-filter>
<action android:name=”android.intent.action.GET_CONTENT” />
<category android:name=”android.intent.category.DEFAULT” />
<data android:mimeType=”vnd.android.cursor.item/vnd.google.note” />
</intent-filter>

permite al usuario seleccionar el tipo de dato vnd.android.cursor.dir/vnd.google.note. A diferencia de la acción android.intent.action.PICK, donde se selecciona un elemento de un conjunto de datos, aquí se selecciona un tipo de dato para que el usuario haga algo con él.

Todo esto se verá más claro al examinar el código de las actividades.

Entradas anteriores:
Programando en Android - Conceptos iniciales (II)
Programando en Android - Conceptos iniciales (I)
Programando en Android - Prólogo

Programando en Android - Conceptos iniciales (I)

El primer paso para relacionar conceptos es conocer los conceptos. Y en Android existen una serie de conceptos que suponen la piedra y el mortero de cualquier aplicación.

El archivo AndroidManifest.xml

Este archivo está presente en todas las aplicaciones Android. Su contenido especifica los componentes de la aplicación, así como la configuración global de la misma. Su descripción se muestra en esta página de la documentación.

En una aplicación habitual, dentro de este archivo habrá un elemento <application>, dentro del cuál habrá uno o varios elementos <activity>. Cada uno de estos elementos supone una interacción con el usuario (generalmente una ventana), y se corresponde con una clase que hereda de la clase Activity.

La clase Activity

Según la documentación de Google, una Activity es una cosa única con un objetivo determinado que el usuario puede hacer. Esta es una definición abstracta. Podemos concretar más la definición diciendo que una Activity (es decir, una clase de nuestra aplicación que hereda de la clase Activity) se presenta al usuario como una ventana. Esta clase crea una ventana que muestra una interfaz de usuario, la cual está definida a su vez en una instancia de otra clase, la clase View.

Cuando se ejecuta una aplicación Android lo primero que se muestra al usuario es la ventana definida por la actividad que esté marcada en el AndroidManifest.xml como principal. Las actividades se gestionan como una pila, así que desde una actividad se puede llamar a otra, y cuando esta finaliza se retorna a la actividad inicial.

Una actividad puede estar ejecutándose, en pausa o detenida. Simplificando, está en ejecución cuando es visible e interacciona con el usuario, está en pausa cuando es visible pero otra ventana, transparente o que no ocupe toda la pantalla, tiene el foco, y está detenida cuando no es visible. En todos estos casos la clase mantiene su información.

En la documentación encontramos un gráfico que ilustra el ciclo de vida de una actividad:

Aunque no es necesario entender de momento todos los detalles de este gráfico, en él se ven los estados por los que puede pasar una actividad (los óvalos coloreados) y los eventos que se disparan en dichos estados (los rectángulos grises):

  • Cuando se crea una actividad, se invoca el evento onCreate(). Este evento sólo se invoca la primera vez que se llama a una actividad, o bien cuando se llama después de que el sistema haya tenido que eliminarla por falta de recursos (más sobre esto en próximos artículos).
  • onStart() es el evento invocado cuando cada vez que la actividad se muestra al usuario. Es decir, la primera vez que se muestra, y las veces que en las que vuelve a aparecer tras haber estado oculta. En este último caso, se invoca onStop() al desaparecer y onRestart() inmediatamente antes de reaparecer.
  • onFreeze() y onPause() son llamadas secuencialmente cuando otra actividad va a pasar en encargarse de la interacción con el usuario. Tras onPause() la actividad permanece en un estado de espera en el que puede ocurrir que la aplicación sea destruida, por lo que estos eventos se usan para consolidar la información que no queremos que se pierda. Si la actividad no se destruye volverá al primer plano con el evento onResume().

La idea importante con la que quedarse es que una actividad que esté pausada o detenida (tras onPause() u onStop()) puede ser destruida por el sistema si previo aviso, por lo que deberemos encargarnos de guardar antes la información necesaria (durante onFreeze() y onPause()). Los detalles lo veremos en una próxima entrada.

Programando en Android - Prólogo

Una pequeña paradoja que se produce a la hora de aprender cualquier habilidad técnica, como un lenguaje de programación, es que para los más novatos en la materia la dificultad está no tanto en encontrar documentación completa, correcta o incluso bien redactada, sino en encontrar material lo suficientemente básico como para no perderse desde el inicio en los pequeños detalles que no se explican por parecer obvios.

Empezar a programar, o hacerlo en un sistema desconocido, supone siempre una curva de aprendizaje inicialmente muy empinada, durante la cual la tarea más importante es lo que se suele denominar “asimilar conceptos”: aprender las nociones básicas y entender cómo estas se relacionan entre sí. Aprender algo es sobre todo ver cómo un concepto nuevo se relaciona con otros conceptos ya conocidos, y establecer estas relaciones es la parte más elusiva del proceso.

A cualquier programador con un poco de experiencia le resulta difícil ver (o recordar) qué red de conceptos básicos tuvo que tejer en sus inicios para aprender los fundamentos de un lenguaje o entorno, y por ese motivo en ocasiones los programadores veteranos encuentran difícil instruir a los más inexpertos.

Dejar constancia de los problemas encontrados, las dudas resueltas y los errores cometidos en el proceso de aprendizaje resulta útil no sólo para consolidar lo aprendido sino también para mostrar a otros el trayecto recorrido, de forma que puedan evitar caminos sin salida o vueltas innecesarias. Aprender de los errores propios es útil, pero aprender de los ajenos es menos doloroso.

Sirva todo esto de justificación para una serie de artículos en los que, con la torpeza propia del novato, iré contando el proceso de desarrollo del plugin de Ipoki para Android, cuya primera y básica versión ya está casi acabada.

Primeros pasos programando con Android

Programar con Android está resultando una tarea agradable. Un sistema nuevo, diseñado desde cero, debe dar solución a los problemas que, por motivos históricos, están presentes en otros sistemas más veteranos. En algunos aspectos Android apunta en la buena dirección, como en el diseño de la interfaz de usuario, que está resuelto con elegancia. En otros, como el rendimiento o la fragmentación de dispositivos, habrá que esperar a que el sistema exista en algún lugar más que el emulador. También hay defectos, pero el sistema todavía está en beta, sufriendo modificaciones, así que de momento seremos condescendientes.

Lo cierto es que al principio la introducción de nuevos términos resulta un poco confusa, sobre todo después de la familiaridad que produce un lenguaje y un entorno de programación conocidos. Conceptos como Activity o Intent pueden ser un poco elusivos al principio. Uno de los problemas es que, pese a la abundante documentación, no hay suficientes ejemplos que den una visión global de cómo funcionan los mecanismos internos de una aplicación, al menos para los que tenemos dificultades con los conceptos abstractos y necesitamos ver las cosas en código. Pero una vez visto algo de código (como el que se puede encontrar en anddev.org) las cosas comienzan a encajar y aparece ante nosotros un framework francamente interesante.

Todavía falta algo de tiempo para ver los primeras sistemas reales en el mercado, pero mientras tanto veremos en próximas entradas cómo resultan los primeros pasos desarrollando para el emulador. Si comercialmente Android resulta un éxito, será tiempo bien invertido. Si no, al menos resultará divertido. Más que con otros sistemas, por lo menos.

Algunas consideraciones sobre Android

Hablaba en mi anterior entrada (La difícil posición de Symbian) de lo abierto de la plataforma de Google. Adjudicaba ese adjetivo tanto por la libertad que da el sistema a los desarrolladores como por la promesa de liberar el sistema con licencia Open Source. Sin embargo, en los seis meses transcurridos desde la presentación de Android sólo se ha liberado el código fuente del kernel (Android Linux Kernel Tree), lo que ha llevado a mucha gente a preguntarse en los grupos de Google sobre el por qué de tanto retraso.

A través de un artículo de CNET (Google’s Android work far from finished) llego a un hilo de discusión de uno de estos grupos ( Android source isn’t available ?????????) donde un desarrollador de Android da algunas explicaciones. Confirma que casi todo el código fuente de la plataforma será liberado: el propio de Google con licencia Apache 2.0, el resto con la licencia original (GPL, LGP, BSD…). Esto incluya la mayor parte de las aplicaciones del móvil (aunque no GMail, por ejemplo). Las partes del sistema que se mantendrán cerradas serán algunas relacionadas con los drivers de dispositivo, a causa de problemas con la propiedad intelectual. Eso sí, no da fechas, pero deja caer que será después de que aparezcan los primeros dispositivos físicos.

Como se menciona en el artículo de CNET, Google se enfrenta a un doble desafío. Por una parte lanzar una plataforma lo suficientemente abierta como para que todo el mundo pueda hacer lo que considere útil, interesante o lucrativo (y la licencia Apache está para permitir a terceros comercializar software derivado de Android). Por otra, evitar la fragmentación que tan difícil hace las cosas a otras plataformas móviles. La clave estará en la Open Handheld Alliance, compuesta por Google y sus socios, que deberá velar porque la evolución de la plataforma sea a la vez rápida y estable.

Nueva versión de la SDK de Android

Ya está disponible la nueva versión de la SDK de Android. Entre los cambios destacados, una nueva clase para traducir direcciones a coordenadas y viceversa, y un nuevo paquete para la animación de los fondos de las aplicaciones. Además de mejoras diversas y arreglo de bugs.

La descarga está disponible aquí, una lista con los cambios aquí, y las instrucciones para la actualización aquí.

Vía: Android Developers Blog

Ampliado el plazo de presentación de aplicaciones para el Android Developer Challenge

Eso anuncia hoy el Android Developers Blog. ¿Los motivos? La gran cantidad de información que han obtenido de los usuarios, gracias a la cual habrá una nueva versión de la SDK en unas semanas.

Es decir, que Google ha logrado uno de los objetivos de este concurso: obtener una comunidad de betatesters significativa para un software que todavía no tiene hardware sobre el que ejecutarse. La nueva SDK arreglará algunos de los múltiples fallos que se han detectado desde que se liberó la primera versión, y todavía podrá recibir mejoras antes de que sus librerías sean definitivamente incorporadas a los primeros modelos de teléfono.

La estrategia opuesta a la de Apple, cuya SDK debería publicarse este Febrero. Veremos como es de estable.

Abierto el plazo de envío de aplicaciones para el Android Developer Challenge

Desde el día dos de Enero se pueden enviar aplicaciones para intentar hacerse con el parte del botín de 10 millones de dólares que Google ofrece en su Android Developer Challenge, concurso en el que se premiará a las aplicaciones más útiles e innovadoras desarrolladas para la plataforma Android.

El plazo de envío se mantendrá abierto hasta el 3 de marzo, y los ganadores se repartirán premios que van de los 25.000 a los 275.000 dólares.

Más información: Android Developers Blog

Android en un Motorola Q

Entradas siguientes »