- Okay, Houston, we've had a problem here.
- This is Houston. Say again, please!
- Uh, Houston, we've had a problem.
CAPCOM Apollo XIII, Jack Swigert - Jack R. Lousma - James A. Lovell.
Aprovechando que Rafa Aguilar (aka @rais38) ha publicado en Objective-C.es un par de entradas sobre las notificaciones Push en iOS he decidido aparcar un par de cosillas que me tenían bastante atareado y continuar con el análisis de Helios.io que había prometido.
Yo no me voy a detener a explicar en que consisten las notificaciones Push y que tipos podemos encontrar en iOS ya que Rafa lo ha explicado estupendamente si no que voy a contar como se desarrollaría el ejemplo de la segunda entrada con Ruby en lugar de con PHP. Para ello, usaré Houston, una gema desarrollada por @mattt. La versión actual de Helios (que tiene unas pocas horas) ya incluye Houston de serie así que Helios y Orbiter nos proporcionan un backend completo para el envío de notificaciones Push.
Os dejo los enlaces a los artículos de Rafa por si los queréis consultar antes de empezar:
Envío de notificaciones en iOS (Parte 1)
Envío de notificaciones en iOS (Parte 2)
Helios y Orbiter. Preparando el CAPCOM.
Si habéis seguido las indicaciones del artículo de Objective-C.es, tendréis una aplicación instalada en vuestro dispositivo que vuelca al log de Xcode el token que le devuelven los servidores de Apple para las notificaciones Push. Helios y Orbiter nos proporcionan un sistema para almacenar esos tokens en un servidor, esto nos será útil cuando queramos enviar notificaciones desde nuestro servidor a los dispositivos que tengamos vinculados a nuestra aplicación. No será necesario pasar siempre el token al servicio si no que podría bastar con usar el alias.
Para ello, nos descargamos Orbiter de GitHub y lo incorporamos a nuestro proyecto o bien usamos CocoaPods, lo que hagamos habitualmente y modificamos el siguiente método del AppDelegate:
El servidor que voy a utilizar para almacenar los tokens y enviar las notificaciones es el mismo de la entrada anterior sobre almacenamiento de datos y sincronización. Si recordáis, una de las cosas que hicimos fue poner seguridad por lo que necesitamos pasarle un usuario y una contraseña. Orbiter usa NSURLCredential para estos fines.
Si hemos hecho todo correctamente, al arrancar la aplicación en el dispositivo obtendremos el siguiente resultado:
Y en el panel de administración de Helios veremos lo siguiente:
Ahora tenemos que preparar nuestro servidor para que realice el envío de notificaciones Push. Como ya hemos comentado al principio, esta funcionalidad no la traía Helios en su primera versión y nos obligaba a nosotros a incluir y configurar esta gema. Hace pocas horas han actualizado el repositorio de Helios incluyendo la funcionalidad de envío de mensajes mediante Houston. Como el merge en GitHub es tan reciente, la gema que hay en RubyGems.org todavía no está actualizada así que para poder usarla en nuestro proyecto Rails he tenido que indicar en el gemfile que tome el fuente de GitHub. Al hacerlo de esta forma, las dependencias no son visibles por el Bundler por lo que, para evitar errores, he indicado también que necesitamos la gema Houston.
Ahora tendremos que guardar el certificado para realizar APS en alguna carpeta de nuestro proyecto y decirle a Helios donde está. Los pasos que hay que seguir para trabajar con los certificados están en el post de Rafa, lo único que haremos diferente es el paso de exportación del certificado, al que le daremos un nombre más comodo para nuestra configuración:
El fichero .pem resultante lo dejaremos en la carpeta config de nuestro proyecto (junto al xcdatamodel) y modificaremos la configuración de Helios en nuestro application.rb de la siguiente manera:
Para comprobar que todo está bien configurado, ejecutamos la siguiente instrucción desde el terminal (recordad que nuestro servidor tiene configurado usuario y contraseña):
Listo, parece que ya tenemos comunicación con Houston... o por lo menos recibimos sus mensajes. ;-)
Houston incluye una utilidad de terminal a la que le pasamos un token, la ubicación del certificado y el mensaje que queremos enviar. Esto no verifica que hayamos configurado correctamente ningún servidor, solo que el certificado y el token sean correctos:
Siguientes pasos
Nuevamente vuelvo a tener sentimientos encontrados. Aunque esta vez he terminado más satisfecho de forma general con los resultados obtenidos de Helios, Orbiter y Houston todavía queda mucho por hacer para tener algo que se parezca mínimamente a lo que nos ofrecen Parse o Urban Airship
Hemos almacenado los tokens en nuestro servidor y hemos sido capaces de enviar notificaciones a nuestro dispositivo desde el terminal. Podríamos realizar el envío de mensajes desde la propia aplicación con un método semejante a este:
Pero en realidad este mensaje no se lo estaríamos enviando al Apolo XIII solamente si no a toda la misión Apolo. Si nos atrevemos a mirar el código fuente de Helios, el fichero push-notification.rb es bastante clarificador: no solo admite el parámetro payload, también admite otro parámetro llamado tokens que es de tipo array. Es decir, si le pasamos un array de tokens el mensaje solo llegará a los dispositivos determinados por esos tokens.
Pero los tokens están almacenados en el servidor, hacemos el registro con Orbiter cada vez que un dispositivo en el que instalamos la aplicación acepta que le enviemos notificaciones Push. ¿Tenemos que descargarnos el listado completo de tokens al dispositivo y filtrar por los alias? Parece que no.
Si nos fijamos en el mismo fuente de antes, donde se define el método get devices, vemos que hay algunos parámetros que se le pueden pasar a dicho método: pages, per_page, limit, offset y q... los cuatro primeros son, obviamente, para controlar la paginación de los resultados y el quinto parece ser el indicado para hacer una query a la tabla Device pero, ¿qué es tsquery? Pues según la documentación de PostgreSQL es la forma de hacer búsqueda completa de texto dentro de una determinada entidad.
En realidad tsquery devolverá todas las registros en los que aparezca el lexema que estamos buscando, esto es, si queremos buscar el token del Apolo XIII haríamos una llamada como la siguiente:
Pero si, por ejemplo, quisiéramos buscar el token del Apolo XI:
Recuperariamos los tokens de los Apolos XI, XII, XIII y XIV. Es más, como la búsqueda se hace en todos los campos de la entidad Device, pudiera ser que recuperáramos algún otro registro más. Por ejemplo, si en vez de misiones espaciales utilizáramos como alias los nombres de las lunas de Jupiter. Al buscar el token de Europe, la consulta nos devolvería el token del alias Europe y el de todos los registros de dispositivos con timezone europeo.
Para este caso particular, y viendo el funcionamiento de los servicios de Parse y Urban Airship, sería conveniente ampliar las funcionalidades de push-notification.rb para incluir los alias como parámetro y buscar sus tokens. Además sería conveniente hacer el envío de notificaciones en batch para los casos en los que hubiera muchos tokens. Sería recomendable que las notificaciones se almacenaran en base de datos y que el envío se hiciera en background... vamos, que esto es un no parar. :-)
Aun con todo el trabajo que queda por hacer, hemos podido ver lo sencillo que es montar un sistema de notificaciones para nuestras aplicaciones iOS. Si solo lo queremos para enviar, de vez en cuando, un mensajero para que nos compren alguna aplicación, con esto tenemos más que suficiente.