lunes, 23 de julio de 2012

Google pierde terreno en el campo de los mapas. ¿Estas preparado para el cambio?

Desde hace algún tiempo hemos asistido con pasividad al comienzo de una guerra en el mundo de los mapas. Hasta ahora, Google había sido el permanente ganador de estas silenciosas batallas; pero las cosas han comenzado a cambiar.

Para mí como consumidor, todo comenzó en el 2009 con el Nokia 5230 y su excelente servicio gratuito de mapas para móviles Ovi Maps; pero como desarrollador, no fue hasta el 2011 que comencé a sentir la necesidad de encontrar el alguna alternativa a las APIs de Google Maps.

Pantalla capturada del Servicio de actualización de mapas de TomTom
Servicio de actualización de mapas
de TomTom (clic para ampliar)
Hasta el 2009 había un ganador bastante claro en el mundo de la cartografía móvil con su popular aplicación en los GPS para coches: el TomTom, una combinación de GPS empotrado en un dispositivo de uso único con un software de navegación asistida por ordenador que no era (ni es) un producto tan barato como quisiéramos. Aún hoy, además de pagar por el dispositivo, debe pagarse una suscripción anual por la actualización de los mapas que, por ejemplo, los de España y Portugal rondan los 55 €.

Sin embargo, en el 2009 Nokia lanzó su teléfono 5230 con un servicio gratuito de cartografía y navegación incluidos, por el precio de un teléfono móvil de gama media-baja y actualizaciones gratuitas independientemente de la cantidad de ciudades o países que descargaras al móvil. De modo que, rápidamente el 5230 pasó a venderse casi más como GPS para coches que como un móvil y ahí comenzó la batalla en el mundo móvil. Tres años más tarde, aún ningún competidor (dígase iOS, BlackBerry o Android) tiene la opción de descargar gratuitamente los mapas al móvil y usarlos offline, sin necesitar una conexión de datos a Internet para su uso. (Lamentablemente esta ventaja no ha sido suficiente para mantener a Nokia a flote; pero ese es otro tema.)

Por su parte, casi desde el comienzo, Google Maps dominó los servicios de mapas en la Web, innovando, adicionando funcionalidades y haciéndole la vida fácil a los desarrolladores de aplicaciones Web que queríamos incluir información cartográfica en nuestros sitios. Sus competidores (entre otros Yahoo Maps y Virtual Earth, actualmente Bing Maps) también hicieron su parte y publicaron APIs para desarrolladores tan fáciles de usar como las de Google; pero éste les llevaba ventaja y después de aprender una tecnología, cambiar a otra da cierta pereza -salvo que haya una muy buena justificación-, así que la mayoría no vimos la necesidad de pensar en el cambio..., hasta el 2011.

En el 2011 Google hizo unos cambios en su política de uso de las APIs de mapas que restringió significativamente el volumen del uso gratuito de sus mapas. Para la mayoría de los sitios Web con poco tráfico, el cambio no les afectó; pero los grandes consumidores de los servicios de Google (tanto en la Web como en los móviles) sí vieron un cambio muy importante y decidieron actuar. El caso más famoso y sonado fue el de Apple que, en junio del 2012, hizo saber que dejarían de usar los servicios de Google para pasarse a un servicio de cartografía propio. No obstante, ya otros grandes habían hecho su elección, como Facebook, que varios meses antes se decantaba por los mapas de Microsoft para sus aplicaciones cartográficas; y otros, como Flicker, se han sumado recientemente al "movimiento alternativo" escogiendo a Nokia como su proveedor para la geolocalización de sus fotos, además de su ya existente vínculo con OpenStreetMaps, proveedor éste que, dicho sea de paso, promete tanto que Microsoft lo ha incorporado como una capa más en su servicio de mapas Web y Apple ya lo estaba usando en algunos de sus productos, antes de decidirse a abandonar del todo el uso de Google Maps.


Imagen con mapas de Microsoft, Nokia, OpenStreenMaps y Google
Microsoft Bing Maps, Nokia Maps, OpenStreenMaps y Google Maps (clic para ampliar)

Al ver esta avalancha, Google reestructuró otra vez su política de precios, haciendo un recorte significativo; pero el mal ya estaba hecho: su señorío absoluto en los mapas Webs ha comenzado a declinar y ahora los desarrolladores tenemos que lidiar con las APIs de, por lo menos, 4 proveedores diferentes: Google, Microsoft, Nokia y OpenStreetMaps.  

¿Como cubrir este abanico de proveedores? ¿Deberíamos decantarnos por un solo proveedor y asumir los riesgos de cambios futuros en su política de uso?

Probablemente, no haya una solución universal y absoluta; pero por suerte existe una solución aproximada: OpenLayers. Esta biblioteca se está postulando como la opción número uno para desarrollar una aplicación de mapas en la Web con la posibilidad de utilizar todos estos proveedores de cartografía, sin necesidad de conocer las particularidades de la implementación de cada uno.

Entonces, ya va siendo hora de que venzamos la inercia, asumamos estos cambios en la cartografía Web y nos pongamos manos a la obra. Mi recomendación: usar OpenLayers en el próximo proyecto, aunque sea combinado con Google Maps y así ir introduciendo las nuevas tendencias, sin abandonar del todo lo que conocemos y nos es familiar.

martes, 17 de julio de 2012

Aplicación en modo kiosko para Android: lo que no se puede hacer

Generalmente solemos hablar de lo que se puede hacer y cómo se hace; pero para evitar quebraderos de cabeza a veces es bueno saber qué es lo que no se puede hacer y así no perdemos el tiempo intentándolo. Debido a que ya he pasado por eso (intentar infructuosamente hacer ciertas cosas con Android) pongo aquí algunas cosas que he verificado que no es posible hacer o que no son recomendables hacer.

Nota: Antes de comenzar debo aclarar que lo que aquí se comenta está relacionado con el desarrollo de aplicaciones usando la SDK de Android que serán ejecutadas en un dispositivo con su ROM original, sin rootear. Ninguna conclusión de las siguientes deberá aplicarse al desarrollo con otras plataformas como la NDK, Mono Droid o cualquier otro medio utilizado para desarrollar aplicaciones para Android, ni para el caso de la ejecución de aplicaciones en un entorno con privilengios de súper usuario.

Las cosas que intenté hacer y ahora describo, estaban relacionadas con el desarrollo de una aplicación en modo kiosko (ver post anterior Aplicación en modo kiosko para Android). Una aplicación en modo kiosko, por definición, debería limitar toda la interacción del usuario con el dispositivo a los elementos que se quieran y definan en la aplicación. En nuestro caso, se suponía que todos los botones del hardware estarían bloqueados, incluso el botón para bloquear o apagar el móvil. Sin embargo, aquí nos encontramos con la primera limitación en Android: 

No es posible inhabilitar o desactivar el comportamiento del botón de encendido del móvil. 

Si bien es cierto que podemos interceptar algunos eventos relacionados con dicho botón, no hay nada que hacer al respecto salvo procesamientos al margen del proceso iniciado (apagado de la pantalla, reinicio o apagado del terminal). De modo que si queremos que una aplicación en modo kiosko en Android no sea interrumpida por la pulsación del botón de encendido, tendremos que inhabilitar físicamente dicho botón, lo cual es "poco" factible en la mayoría de los casos.


No obstante, supongamos que logramos inhabilitar el botón de encendido, digamos, porque empotramos un teléfono o un tablet con Android en una carcasa que limita su utilización a la interfaz táctil. Nos encontramos entonces con la necesidad de poder reiniciar o apagar el dispositivo, ya sea mediante algún elemento en la interfaz o de manera remota, reaccionando a un SMS, un código recibido por NFC, un patrón leído a través de la cámara o la estrategia que mejor nos convenga. 


Para reiniciar y apagar el dipositivo disponemos de los métodos reboot() y goToSleep(). Sin embargo, a pesar de que parece que podemos reiniciar y apagar el dispositivo con dichos métodos, la ejecución de los mismos requiere del permiso android.permission.DEVICE_POWER que, aunque no lo dice en la documentación de la SDK, está restringido a las aplicaciones que se ejecutan con permisos del sistema y, por tanto, nuestra aplicación no podrá apagar ni reiniciar el dispositivo ejecutándose como una aplicación corriente. De modo que:

No es posible reiniciar o apagar el móvil, por programación.

Finalmente, el último problema está relacionado con la intercepción de llamadas entrantes. En nuestra aplicación, deberíamos interceptar las llamadas entrantes y colgarlas para no interrumpir el funcionamiento de la aplicación. Sin embargo, aunque hay varias aplicaciones que logran hacer esto, lo hacen accediendo a una API no oficial que, desde la versión 2.3 de Android a quedado limitada a las aplicaciones que se ejecutan con permisos del sistema. De modo que, si nuestra aplicación se ejecutará en Android 2.2 o una versión anterior, podríamos usar la estrategia que se ilustra claramente este post: Blocking Incoming call - Android. Sin embargo, deberá tenerse en cuenta que ese código no funcionará en versiones de Android posteriores a la 2.2 pues desde la 2.3 el permiso necesario para manipular una llamada (android.permission.MODIFY_PHONE_STATE) se ha limitado a las aplicaciones del sistema. En Stakoverflow este tema se ha tratado extensamente (como en este hilo) y queda claro que no es posible hacerlo, y aunque hay quien propone diferentes estrategias para paliar el problema, ninguna es la solución definitiva a éste problema que pueda aplicarse a cualquier versión del sistema y en cualquier terminal. De modo que:

No es posible colgar una llamada entrante, por programación, en Android 2.3 o superior.

Hasta aquí las limitaciones con las que me he topado en el desarrollo de aplicaciones para Android. Seguramente haya muchas más, pero de momento, estas están verificadas como problemas, hasta el momento, irresolubles. A lo mejor alguien encuentra una solución universal y la comparte; pero por ahora:

  • No es posible inhabilitar o desactivar el comportamiento del botón de encendido del móvil.
  • No es posible reiniciar o apagar el móvil, por programación.
  • No es posible colgar una llamada entrante, por programación, en Android 2.3 o superior.