jueves, 5 de junio de 2014

Plugin device-orientation (brújula)

El nombre lo dice casi todo. Este plugin Phonegap/Cordova sirve para saber hacia dónde apunta el dispositivo, accediendo a la brújula. La brújula del dispositivo obtiene la dirección a la que apunta el mismo, normalmente, desde la parte superior, y está expresada en grados, desde 0 a 359'99 donde el 0 es el norte.

Plataformas soportadas

Este plugin está soportado por todos los sistemas más usados, por lo que implementarlo nos garantiza prácticamente 0 problemas de compatibilidad. Aquí el listado de los mismos:

  • Amazon Fire OS
  • Android
  • BlackBerry 10
  • Firefox OS
  • iOS
  • Tizen
  • Windows Phone 7 y 8
  • Windows 8

Instalación

Basta con escribir en consola, dentro de la carpeta del proyecto lo siguiente:
cordova plugin add org.apache.cordova.device-orientation

Y ya podremos hacer uso de los métodos de la API device-orientation.

Métodos

Son los siguientes, y podemos observar bastantes similitudes en su comportamiento respecto a los métodos de otras API como la del acelerómetro o la geolocalización.

  • navigator.compass.getCurrentHeading(onSuccess, onError);
  • navigator.compass.watchHeading(onSuccess, onError, [compassOptions]);
  • navigator.compass.clearWatch(watchID);
La explicación del funcionamiento de estos métodos es similar a la de los métodos análogos de otros plugins ya explicados, con la diferencia de que a las funciones callback onSuccess y onError se les envían otros objetos como parámetros. El objeto enviado a la función onSuccess es el llamado CompassHeading. Y a la función onError se le pasa el objeto CompassError. Por ejemplo, en el caso del acelerómetro, recordemos que a la función onSuccess(o como quisiéramos llamarla) se le pasaba el objeto Acceleration. Por lo demás, el funcionamiento es muy parecido. Con getCurrentHeading obtenemos la dirección a la que apunta el dispositivo en un momento determinado, con watchHeading realizamos un muestreo que referenciamos en una variable(en explicaciones anteriores la habíamos llamado watchID), y clearWatch sirve para detener ese muestreo.
También disponemos de un objeto de opciones, que podemos pasar de forma optativa, y contendrá la configuración con la que realizaremos el muestreo. Los valores que puede contener el objeto compassOptions son frequency y filter. Frequency determina el valor en milisegundos en el que haremos el muestreo de datos. Si además incluimos la opción filter, frequency es ignorado. Filter indica el valor mínimo en grados requerido para realizar una nueva llamada a la función onSuccess. No recomiendo incluir filter, porque no está soportado por muchos de los principales sistemas(Android, Windows Phone 7 y 8, entre otros).

Objetos

Como hemos mencionado antes, el objeto CompassHeading es pasado como parámetro a la función onSuccess cuando se obtienen datos de forma satisfactoria. Podemos acceder a sus siguientes propiedades:

  • magneticHeading: Valor numérico expresado en grados, que varía entre 0 y 359'99 y que indica hacia adónde apunta el dispositivo en el momento que se obtiene.
  • trueHeading: Igual que magneticHeading, pero relativo al polo Norte geográfico. Un valor negativo indica que no se puede determinar este valor.
  • headingAccuracy: Desviación en grados que puede haber entre los datos obtenidos y la dirección real a la que apunta el dispositivo.
  • timestamp: Tiempo en milisegundos en el que se tomó la muestra de datos.
No recomiento usar trueHeading y headindAccuracy por problemas documentados de compatibilidades.

El otro objeto del que podemos hacer uso es CompassError, que se pasa como parámetro a la función callback onError cuando llamamos a getCurrentHeading o watchHeading. Tiene la propiedad code, que puede valer, según el error:
  • CompassError.COMPASS_INTERNAL_ERR
  • CompassError.COMPASS_NOT_SUPPORTED
La explicación es bastante sencilla, o bien ha habido error al tomar los datos, o el dispositivo no dispone de brújula.


Ejemplo práctico

Vamos a implementar una brújula visual. ¿Cómo lo haremos? Mostraremos por pantalla una imagen cuya parte superior girará tantos grados como nos indique la propiedad magneticHeading del objeto CompassHeading, gracias a javascript y CSS. Una vez sabemos qué queremos y cómo implementarlo con las herramientas de las que disponemos, vamos a ello.

Partiremos del esqueleto que ya teníamos listo.
Por supuesto, podemos editar algunas opciones en el config.xml:

La imagen la guardaremos en www/img, yo he usado la siguiente imagen tomada de openclipart.org:
http://openclipart.org/image/300px/svg_to_png/188726/Compass_Rose_Arvin61r58.png




Una vez incluída en la carpeta de imágenes del proyecto, completamos el body del index.html tal que así:
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <meta name="format-detection" content="telephone=no" />
        <!-- WARNING: for iOS 7, remove the width=device-width and height=device-height attributes. See https://issues.apache.org/jira/browse/CB-4323 -->
        <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height, target-densitydpi=device-dpi" />
        <link rel="stylesheet" type="text/css" href="css/bootstrap.min.css">
        <link rel="stylesheet" type="text/css" href="css/index.css" />
        <title>Proyecto Phonegap</title>
    </head>
    <body>
        <div class="container">
            <h1 class="text-center">Brújula Phonegap</h1>
            <div class="row well text-center">
                <img img="brujula" src="img/brujula.png" alt="">
            </div>
        </div>
        
        <script type="text/javascript" charset="utf-8" src="cordova.js"></script>
        <script type="text/javascript" src="./js/jquery-1.11.0.min.js"></script>
        <script type="text/javascript" src="./js/bootstrap.min.js"></script>
        <script type="text/javascript" src="./js/fastclick.js"></script>
        <script type="text/javascript" src="./js/index.js"></script>
        <script type="text/javascript">
            window.addEventListener('load', function() {
                new FastClick(document.body);
            }, false);
            app.initialize();
        </script>
    </body>
</html>

Como vemos, sólo hemos añadido la etiqueta img cuya fuente es la imagen elegida, y mediante javascript le aplicaremos CSS con el giro que determine la brújula del dispositivo. Así queda el index.js:

var app = {
    // Application Constructor
    initialize: function() {
        this.bindEvents();
    },
    // Bind Event Listeners
    //
    // Bind any events that are required on startup. Common events are:
    // 'load', 'deviceready', 'offline', and 'online'.
    bindEvents: function() {
        document.addEventListener('deviceready', this.onDeviceReady, false);
    },
    // deviceready Event Handler
    //
    // The scope of 'this' is the event. In order to call the 'receivedEvent'
    // function, we must explicity call 'app.receivedEvent(...);'
    onDeviceReady: function() {
        app.receivedEvent('deviceready');
    },
    // Update DOM on a Received Event
    receivedEvent: function(id) {
        //tomaremos el muestreo de datos cada segundo (1000 ms)
        watchID = navigator.compass.watchHeading(onSuccess, onError, {frequency: 1000});

        //función onSuccess que aplica CSS a la imagen de la brújula del html
        function onSuccess(heading){
            //guardo los datos obtenidos del objeto CompassHeading
            var orientacion = 360-heading.magneticHeading;
            //aplico con jquery una rotación que depende de la variable orientacion
            $("#brujula").css('-webkit-transform','rotate(' + orientacion + 'deg)');
        }
        //funcion onError que tiene el objeto CompassError pasado como parámetro
        function onError(compassError) {
            //me limito a informar del error
            alert('Error: ' + compassError.code);
        }
    }
};


Como en ejemplos anteriores, usamos cosas propias de Phonegap una vez que se ha capturado el evento deviceready. En este caso, como ya hemos explicado, la magia está en rotar la imagen de la brújula con la línea $("#brujula").css('-webkit-transform','rotate(' + orientacion + 'deg)');
El muestreo se actualiza cada 1000 milisegundos, como bien expresa la opción frequency, pero se puede cambiar al gusto.

Antes de compilar, importante, instalar el plugin en nuestro proyecto, que luego vienen los llantos.

Y finalmente compilamos en local o en la nube y testeamos el funcionamiento del programa. Yo he optado por compilar en local con la orden phonegap build android, y copiar el fichero HelloWorld-debug-unaligned.apk de la carpeta platforms/android/ant-build en el teléfono directamente.

Imagen de la aplicación en ejecución:

lunes, 2 de junio de 2014

Phonegap vs programación nativa, y breve reflexión

Programar haciendo uso de Phonegap tiene sus ventajas, pero también tiene sus desventajas, y según el caso, podría llegar a ser más conveniente realizar aplicaciones nativas para cada sistema.
En este artículo vamos a analizar los pros y contras que pueden ayudarnos a decantarnos por el uso de Phonegap o no.

Ventajas de Phonegap respecto a programación nativa para cada sistema:
  • Un código, varios ejecutables. La ventaja evidente de Phonegap es el ahorro de tiempo y esfuerzo ya que con un mismo código podemos obtener los  ejecutables para distintas plataformas. Además, supone un importante ahorro de dinero si estamos en un entorno empresarial.
  • Utilización de lenguajes de desarrollo web. Para obtener los ejecutables de nuestras aplicaciones, desarrollamos con javascript, html, y css. Si tenemos conocimiento de estas herramientas, prácticamente ya tenemos una base válida para empezar a programar en Phonegap. Quizá debamos añadir también un conocimiento muy básico de xml por aquello del fichero de configuración config.xml.
  • Aprovechamiento de frameworks, preprocesadores, etc muy potentes disponibles en desarrollo web. Como prácticamente estamos haciendo desarrollo web con algunos matices, podemos usar herramientas de ayuda como son preprocesadores css(Sass, Less, Stylus...), preprocesadores html(haml, jade, emmet...), preprocesadores javascript(coffeescript) o frameworks de desarrollo javascript(Angularjs, Emberjs, jquery...). Esto hace la programación web más amena y cómoda.
  • El aprendizaje de html, css y javascript que adquirimos al aprender a programar para Phonegap, en caso de no tenerlo, no sólo es bueno para escribir aplicaciones móviles, sino para desarrollo web en general. El saber tecnologías nuevas siempre es bueno pero en el caso de estas tres, hoy en día, es más importante aún.
  • Con Phonegap Build, tu código a la nube. Mediante utilidades como Adobe Phonegap Build podemos evitar tener kits de desarrollo(SDK) en nuestros ordenadores para compilar, y además tendremos más ordenadas las aplicaciones desarrolladas. En caso de trabajo en equipo, esta ventaja gana peso.
  • Desde la versión 3.0 de Phonegap, el rendimiento de las aplicaciones se ha optimizado. No van a igualar a las nativas, cierto, pero con las últimas actualizaciones, cada vez la diferencia de rendimiento entre las aplicaciones nativas y las realizadas con Phonegap/Cordova es menor. Sobre todo si las ejecutamos en terminales modernos.

También analizaremos los contras que existen, no todo iban a ser alegrías:

  • El que mucho abarca, poco aprieta(compatibilidades). PhoneGap nos hace de puente entre nuestro código web y el código nativo del dispositivo, por lo que nos da la habilidad de usar parte de su hardware. Pero no todas las funcionalidades del dispositivo están disponibles, dependiendo del sistema móvil en el que nos encontremos. Es importante conocer bien las compatibilidades de cada plugin y evento Phonegap antes de "implementarlas a lo loco", para no llevarnos sorpresas.
  • La depuración es mucho más tediosa que si programamos en nativo, y en parte gran culpa de esto lo tiene javascript.
  • Una aplicación nativa siempre será más rápida que una desarrollada con Phonegap/Cordova. La explicación a esto, es que Phonegap usa un webview en una app nativa, que levanta un "servidor local", y así permite que corra nuestra aplicación móvil.

Conclusión

Como en casi todo, la elección óptima siempre vendrá tras un estudio previo al desarrollo, teniendo en cuenta los requisitos y el comportamiento esperado de las aplicaciones.
Si lo que queremos desarrollar es una aplicación simple cuyos requerimientos tienden a ser muy bajos, y que no requiere usar características del sistema operativo de la plataforma(o un uso básico de las mismas), y que adicionalmente deseamos que funcione en diferentes tipos de dispositivos móviles, PhoneGap es una muy buena elección.
Por contra, si estamos hablando de aplicaciones que soportan funciones importantes de un sistema específico, y de alta complejidad, se debe considerar seriamente su implementación en plataforma nativa.

domingo, 1 de junio de 2014

Adobe Phonegap vs Apache Cordova

Pregunta importante, ¿Con qué framework desarrollo?

Como ya vimos en la introducción, Phonegap y Cordova son muy similares. De hecho, por ejemplo, la mayoría de órdenes de línea de comandos de ambos son iguales, pero unas empiezan por phonegap y otras por cordova. Lo que ocurre realmente es que el comando phonegap encapsula al comando cordova, añadiendo, en algunos casos, algún extra, pero en la mayoría de los mismos, estamos ante el mismo código fuente.

Hay que tener en cuenta que Cordova y Phonegap llevan apenas dos años existiendo por separado (este artículo se escribe en Junio 2014), por lo que es algo normal.
Entonces, si son tan parecidos, dará igual usar Cordova que Phonegap, ¿no? Todo depende.
Depende principalmente del uso que vayamos a hacer de los factores que diferencian a ambos frameworks. Este factor diferenciador es claramente Phonegap Build.
Si nuestra meta es aprender a usar alguno de estos frameworks, haciendo uso de un SDK, por ejemplo el de Android, y realizar alguna aplicación de prueba, no importa mucho si usamos Cordova o Phonegap. Con ambos vamos a compilar de forma local y a hacer pruebas sin notar diferencias entre un framework u otro más allá de que los comandos comienzan con palabras diferentes.
Si pretendemos desarrollar aplicaciones y compilarlas en varias plataformas, hacer uso de Phonegap Build puede ahorrarnos más de un dolor de cabeza. La ventaja principal es que no tenemos que disponer de ningún SDK para compilar en local nuestras aplicaciones. Nos ahorramos además, el no poder compilar para iOS desde un ordenador que no sea MAC(en local). Si estamos en MAC no tendríamos ese problema, de hecho, el SDK de Windows Phone está disponible para MacOS. Nuestro código fuente se envía a Phonegap Build, es compilado en la nube, y se nos da la opción de descargar los ejecutables para las distintas plataformas, todo muy simple. La desventaja de esto, es que el testeo de posibles errores es más lento, ya que la compilación e instalación de las aplicaciones pasa por más fases que si desde el SDK, en local, lanzamos un emulador para probarlas.

En mi opinión, la situación ideal es disponer en local de un SDK y testear la aplicación en un único sistema móvil(por ejemplo Android, como hemos hecho). Una vez que comprobemos que nuestra aplicación funciona correctamente, haciendo uso de Phonegap Build, obtenemos los ejecutables de nuestra aplicación en distintas plataformas. Esta situación ideal depende de los elementos que nos proporcionan Phonegap/Cordova, o mejor dicho, del conocimiento que tengamos de los mismos. Recordemos que algunos plugins, y ciertos eventos, no son compatibles con todas las plataformas móviles.
Esta situación es extensible al trabajo en equipos, en empresas por ejemplo. Dado que Phonegap Build nos permite pasarle el código de las aplicaciones por medio de GitHub, si usan Git como control de versiones todos los miembros de un equipo de desarrollo, el desarrollo en equipo es más ágil.
Por ejemplo, cada miembro testea los códigos de su rama(en otras palabras, la parte de la aplicación que le toca implementar) en local, hace los "merge" necesarios cuando crea oportuno a la rama master del proyecto, y cuando está lista una versión definitiva, teniendo ya creada una app en Phonegap Build enlazada al código GitHub del proyecto, basta con actualizar los ejecutables de cada sistema, y el sistema en la nube hace el trabajo por nosotros.