Archive for the ‘Android’ Category
Notificaciones ‘push’ en dispositivos móviles
¿Qué es una notificación push?
Es un mensaje que una aplicación servidora envía a una aplicación cliente indicándole que tiene algún tipo de información nueva disponible. Lo que distingue a las notificaciones push es que el servidor inicia la comunicación, no espera a que el cliente pregunte si hay algo nuevo. La ventaja es la inmediatez: la información llega al cliente (y por tanto al usuario) en cuanto está disponible en el servidor.
El ejemplo más clásico de este tipo de notificaciones es el correo electrónico. Un usuario tiene una aplicación de correo electrónico ejecutándose en su dispositivo. Alguien le envía un correo, que queda almacenado en el servidor. A partir de ahí pueden ocurrir dos cosas:
- El cliente de correo electrónico está configurado para consultar al servidor, con una frecuencia predeterminada, si hay nuevos correos. Si la frecuencia es de una vez cada 5 minutos el usuario puede tardar ese tiempo en enterarse de que ha recibido un correo nuevo.
- El cliente (y el servidor) soportan notificaciones push. En este caso el servidor envía un mensaje al cliente para avisarle de que ha llegado un nuevo correo, y el cliente a su vez se lo notifica de alguna forma al usuario para que lo lea si le interesa.
En el caso de las aplicaciones de mensajería instantánea la necesidad de la inmediatez es aún más manifiesta: para que la conversación sea fluida necesitamos que los mensajes nos lleguen en cuanto son enviados, e incluso queremos saber cuándo nuestro interlocutor está escribiendo algo.
¿Cómo se implementa una notificación push?
La manera habitual de implementar una notificación push es establecer una conexión TCP de larga duración. El cliente abre una conexión TCP con el servidor y la deja abierta. Sobre esta conexión TCP el servidor enviará las notificaciones al cliente, usando algún protocolo de aplicación. IMAP y XMPP son ejemplos de protocolos estándar usados para correo y mensajería respectivamente, aunque existen múltiples protocolos propietarios.
Notificaciones push en BlackBerry
El éxito de las BlackBerry se debe en parte a su sistema de push email. Cuando leer el correo desde el móvil era una experiencia dolorosa en otros sistemas, las BlackBerry ya conseguían que sus usuarios recibiesen el correo de manera instantánea. RIM subscribe un acuerdo con los operadores de telefonía, por el cual se establece una conexión permanente con unos servidores especiales operados por RIM. Estos servidores reciben el correo del usuario desde los servidores BES, y lo notifican de forma inmediata a las BlackBerry.
La tecnología de notificaciones push de RIM está disponible para terceros a través de la BlackBerry Push API.
Notificaciones push en iPhone
Apple incorporó desde el principio un sistema de notificaciones push para el correo electrónico de Yahoo. La aparición de MobileMe añadió notificaciones push tanto para el correo como para el calendario y los contactos.
Cuando Apple diseñó la SDK del iPhone tomó la decisión de no permitir a los desarrolladores crear aplicaciones que se ejecutasen en segundo plano. Como consecuencia, las aplicaciones desarrolladas por terceros sólo se ejecutan mientras están en primer plano, deteniéndose cuando el usuario quiere realizar otra actividad.
La nueva versión de la SDK incorpora el Apple Push Notification service, un servicio que envía notificaciones a las aplicaciones del iPhone aunque estas no se estén ejecutando. Para ello la notificación pasa primero por los servidores de Apple, con los que el móvil mantiene siempre una conexión abierta. La notificación se envía al móvil y se muestra al usuario como un mensaje de texto o como una ventana de notificación, que servirán además para lanzar la aplicación y procesar la notificación recibida.
Notificaciones push en Android
Android proporciona notificaciones push para el correo electrónico, calendario y contactos, tanto en el HTC Dream como en el HTC Magic. Como en los casos anteriores, el sistema establece un canal siempre abierto con los los servidores del proveedor (en este caso Google).
Aunque los desarrolladores de Android tienen la opción de programar aplicaciones que se ejecuten en segundo plano el sistema se reserva el derecho de detener cualquier aplicación cuando así lo decida, en función de los recursos disponibles en la máquina. Así que podemos desarrollar un cliente que mantenga conexiones TCP de larga duración con el servidor ejecutándose en bakcground, pero no podemos garantizar que la aplicación se esté ejecutando para mantener esta conexión abierta. Claro que este problema se presenta aunque queramos traernos la información usando pull, es decir, consultando al servidor de periódicamente.
En las versiones beta de la SDK se incluía un servicio llamada XMPPService o GTalkService, que permitía a los desarrolladores enviar notificaciones utilizando la infraestructura de Google Talk. Este servicio fue retirado de la versión final de la SDK por problemas de seguridad, como se explica aquí: Some information on APIs removed in the Android 0.9 SDK beta. No sería extraño que Google incluyese una versión mejorada en alguna de las próximas versiones de Android.
Impresiones sobre el HTC Magic
Ha pasado un mes y medio desde que tengo el HTC Magic. Me pasé de Orange a Vodafone por este móvil, un mes antes de que Orange anunciaran en exclusiva el HTC Hero. En fin…
Como Internet está lleno de análisis del Magic me limito a soltar algunas impresiones personales. No he tenido ocasión de usar de forma continuada otros móviles de gama similar, así que no voy a hacer comparaciones.
- La pantalla es mejor de lo que esperaba. Brillante y nítida. Hubiese sido aún mejor con 3,5 pulgadas. Para evitar llevar la funda puesta le compré un protector de pantalla.
- La interfaz de usuario resulta cómoda y agradable. Fácil de configurar. Echo en falta un sistema rápido para desinstalar aplicaciones.
- No hay multitouch. Podría ser útil para ampliar imágenes o páginas web.
- El sistema es razonablemente estable, pero de vez en cuando se ralentiza sin motivo aparente. No demasiado a menudo ni durante mucho tiempo, pero resulta molesto. Probablemente se deba a alguna de las aplicaciones instaladas. Aún no se me ha quedado colgado.
- El Market contiene una buena cantidad de aplicaciones, tanto de pago como gratuitas. La interfaz es simple pero un poco limitada. Me gustaría que hubiese un sistema para actualizar varias aplicaciones de golpe.
- El GPS es muy rápido. El magnetómetro es interesante. El acelerómetro es un pelín lento, o al menos es lenta la transición entre las dos orientaciones posibles de la interfaz.
- Por algún motivo no se puede tener el home en formato landscape.
- La cámara no tiene flash. Y además es muy mala.
- El trackball funciona bien, pero nunca lo uso.
- La batería no va sobrada, pero no tengo problemas para que me dure todo el día.
- La calidad del sonido en las llamadas en buena. Tener toda la información de los contactos centralizada (y sincronizada con los contactos de GMail) resulta muy cómodo.
- El WiFi va bastante bien. El bluetooth no lo he probado.
- Me he aficionado a Twitter. Aún no me he decidido entre Twidroid y TwitterRide.
T-Mobile G1: dudas
- ¿Cómo funcionará el Android Marketplace? ¿Aplicará Google restricciones sobre el tipo de aplicaciones que se pueden publicar? Parece que en la presentación insinuaron que existirá algún tipo de proceso de validación.
- El G1 sólo funcionará con SIMs de T-Mobile. Además, se impide el uso de aplicaciones de voz sobre IP en las conexiones a través de la red de T-Mobile, limitando su uso a conexiones WiFi. ¿Veremos algún dispositivo libre? ¿A qué precio?
- ¿Cómo es de estable el sistema? La versión 1.0 de la SDK acaba de salir, así que habrá que esperar unas semanas antes de comprobar si es mínimamente usable. ¿Cuánto dura la batería?
- ¿Era necesario que fuese tan feo?
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: }
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 invocaonStop()al desaparecer yonRestart()inmediatamente antes de reaparecer.onFreeze()yonPause()son llamadas secuencialmente cuando otra actividad va a pasar en encargarse de la interacción con el usuario. TrasonPause()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 eventoonResume().
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í.



