Desarrollo de aplicaciones móviles multiplataforma con Apache Cordova utilizando AngularJS, Ionic y ngCordova
0. Índice de
contenidos.
- 1. Entorno
- 2. Introducción
- 3. Instalación y configuración del entorno de desarrollo
- 4. Creación y configuración del proyecto
- 5. Descripción de las tareas que podemos utilizar
- 6. Workflow altamente productivo
- 7. Incluimos la librería ngCordova
- 8. Caso de uso: crear una opción de menú que muestre la información del dispositivo
- 9. Conclusiones
1. Entorno
Este tutorial está escrito usando el siguiente entorno:
- Hardware: Portátil Mac Book Pro 15″ (2,3 Ghz Intel Core i7, 16 GB DDR3)
- Sistema Operativo: Mac OS X Mavericks
- NodeJS 0.10.33
- Yeoman 1.3.3
- Grunt 0.4.5
- Bower 1.3.12
- AngularJS 1.2.26
- Ionic 1.0.0-beta.13
- Cordova 4.0.1
- ngCordova 0.1.7-alpha
2. Introducción
En este tutorial vamos a intentar describir con el mayor detalle posible la configuración para el mejor entorno de desarrollo que he podido encontrar para trabajar en este tipo de aplicaciones y vamos a ponerlo a prueba con un pequeño caso de uso.
3. Instalación y configuración del entorno de desarrollo
En esta sección vamos a ver cómo instalar y configurar las herramientas necesarias para estos desarrollos en el entorno de Mac, lo bueno que tienen estas herramientas es que son multiplaforma por lo que estos pasos no difieren mucho en otras plataformas como Ubuntu.
NodeJS
A poco que hayáis metido la cabeza en el desarrollo frontend ya os habréis encontrado con esta herramienta que permite ejecutar Javascript en el servidor. Gracias a ella se han implementado multitud de herramientas como: la línea de comandos Cordova e Ionic, Yeoman, Grunt, Bower y un sin fin de aplicaciones.
Para instalarlo simplemente accedemos al web http://nodejs.org/download/ y descargar el instalable adecuado.
En el mismo proceso de instalación también se instala la herramienta NPM (Node Package Manager) que vamos a utilizar para instalar el resto de herramientas.
Git
Para el que no lo conozca es un sistema de control de versiones distribuido. Necesitamos tener un cliente de Git instalado, ya que muchas de las herramientas que vamos a instalar descargan código que necesitan desde estos repositorios.
Para instalarlo, accedemos a la web http://git-scm.com/downloads y seleccionamos el adecuado a nuestra plataforma.
Ruby
Solo es necesario en caso de que queramos utilizar SASS para trabajar con CSS. Si usaís Mac seguramente ya lo tengaís instalado pero si no es el caso, recomiendo seguir cualquiera de los métodos que se mencionan en esta URL: https://www.ruby-lang.org/en/downloads/
Ant
El viejo Ant es utilizado por algunas de las otras herramientas para poder realizar su funcionalidad. Si no lo tenéis instalado ya, simplemente descargarlo de la web.
Lo siguiente es descomprimirlo y actualizar la variable ANT_HOME y PATH.
Resto de herramientas
En este momento ya tenemos instaladas las herramientas mínimas necesarias para poder instalar el resto, que gracias a la gestión de módulos de NPM basta que instalemos una para que automáticamente se instalen el resto.
Vamos a instalar el generador de Yeoman «generator-ionic». Me gusta porque te integra perfectamente AngularJS e Ionic, y por defecto, te viene preparado para poder utilizar cualquier plugin de Cordova.
Además te ofrece la posibilidad de hacer livereload en el propio dispositivo móvil aumentando nuestra productividad al no tener que estar constantemente teniendo que volver a instalar la aplicación para ver cómo queda.
Para instalar este generador simplemente tenemos que ejecutar en un terminal:
npm install -g generator-ionic
Con la ejecución de este comando, automágicamente, npm nos ha instalado todos los módulos de los que dependen, entre los que destacan:
- Yeoman: es la herramienta que nos va a permitir crear la aplicación con un determinado esqueleto.
- Bower: es la herramienta que gestiona de manera eficaz las dependencias entre librerías Javascript de nuestro proyecto. Si queremos incluir una nueva lo haremos con el comando «bower install nombre_librería» y se encargará de almacenarla junto a las otras y añadir la referencia en el fichero index.html por nosotros.
- Grunt: es una herramienta de task runner, es decir al estilo de Ant, mediando la ejecución de comandos podemos realizar distintas tareas como: minificar el código, actualizar las líbrerías, ejecutar el proyecto en un navegador, …
- Cordova: es la plataforma de ejecución de aplicaciones híbridas que nos permite mediante un único desarrollo web poder desplegar nuestra aplicación en distintas plataformas como: android, ios, windows phone, etc…
- Ionic: tanto la librería Javascript como la herramienta por línea de comandos que entre otras cosas nos permite hacer el livereload en el dispositivo móvil. La librería nos ofrece un catálogo de directivas de AngularJS y estilos que tienen por objetivo que apariencia de la interfaz sea lo más «nativa» posible para mejorar la experiencia de usuario.
Nota: queda a responsabilidad de cada uno tener preparado el entorno para poder desarrollar en la plataforma móvil deseada. Es decir, para Android tener el Android SDK configurado e instalado, para IOS tener el XCode con todas las herramientas necesarias, etc… Además para trabajar con Android aconsejo echar un vistazo a Genymotion es mucho más rápido que el emulador convencional de Android.
4. Creación y configuración del proyecto
Con todas las herramientas instaladas y correctamente configuradas vamos a comenzar el desarrollo de nuestra aplicación web con AngularJS, Ionic y ngCordova sobre Apache Cordova.
Una vez instalado creamos la carpeta raíz del proyecto donde queramos almacenar la aplicación y dentro ejecutamos el asistente de Yeoman.
mkdir poc-autentia cd poc-autentia yo ionic
De este modo ejecutamos el asistente que nos irá haciendo una serie de preguntas:
- Would you like to use SASS with Compass (requires Ruby)? Nos pregunta si queremos gestionar las hojas de estilo con la herramienta SASS, que nos es más que un preprocesador de las hojas estilo CSS que nos permite tener un código más legible y reducido. Es necesario tener instalado Ruby y la gema Compass. Si no hemos querido instalar Ruby, decid no.
- Which Cordova plugins would you like to include? Aquí podemos seleccionar si queremos incluir ya algún plugin del dispositivo.
- Which starter template [T] or example app [A] would you like to use? Podemos seleccionar el esqueleto inicial de nuestra aplicación entre los siguientes:
- [T] Blank: si no queremos ningún esqueleto.
- [T] Tabs: nos proporciona un esqueleto con pestañas abajo.
- [T] Side Menu: nos proporciona un esqueleto con el menú corredizo. Para el ejemplo vamos a utilizar este.
- [T] Maps: nos proporciona un esqueleto con un mapa de Google.
- [T] User Intro: nos proporciona un esqueleto con una mini-aplicación de introducción a base de slides antes de mostrar la pantalla principal.
- [A] Pets: nos proporciona el esqueleto de una aplicación completa con pestañas abajo y algo más de funcionalidad.
Al finalizar Yeoman nos habrá creado la siguiente estructura de ficheros y carpetas, divididas por funcionalidad:
- Carpetas propias de Cordova:
- hooks: almacena los scripts para realizar tareas personalizadas como la carga automática de plugins.
- plugins: almacena el código fuente de los plugins que vayamos a utilizar.
- merges: almacena por plataforma los ficheros que queramos personalizar.
- platforms: almacena el código fuente de los proyectos híbridos por cada plataforma soportada.
- www: almacena el código fuente que va a ser ejecutado dentro de cada proyecto híbrido. En el caso de este generador, es aquí donde va a almacenar la salida de las tareas que ejecute.
- config.xml: es el fichero que almacena información de relevancia para poder configurar los proyectos dependiendo de la plataforma.
- Carpetas propias de la aplicación web:
- app: almacena el código fuente de nuestra aplicación. Será aquí donde editemos los ficheros y recursos necesarios para la implementación de nuestra aplicación. Mantiene una estructura por defecto que es buena práctica respetar.
- test: almacena el código de test. El proyecto ya está configurado para ejecutar los test con Karma y PhamtonJS.
- Carpetas para la gestión del proyecto:
- node_modules: contiene todos los módulos de nodejs necesarios para la ejecución de tareas del proyecto. Se regenerá a través del comando “npm install”.
- bower.json: utilizado por la herramienta bower para gestión del proyecto. Almacena información como el nombre y la versión del proyecto así como todas las dependencias de librerías de Javascript. A través del comando “bower install” incluye estas dependencias en la carpeta “app/lib” de nuestro proyecto y edita el fichero index.html para incluir las referencias de script correspondientes.
- package.json: utilizado por la herramienta npm. Especifica que módulos de node tienen que ser instalados para el correcto funcionamiento del proyecto. Estos módulos son los que se almacenan en la carpeta “node_modules”.
- Gruntfile.js: es el fichero utilizado por la herramienta Grunt para el lanzamiento de tareas del proyecto, describir que tareas podemos realizar en el proyecto como: ejecutar la aplicación en un server, minificar el código, añadir una nueva plataforma o plugin, etc…
- .gitignore: por defecto, el generador nos crea el fichero .gitignore donde se incluyen todas las carpetas y ficheros que no deben subirse al control de versiones, dado que pueden volver a ser generados de forma automática.
5. Descripción de las tareas que podemos utilizar
Estas son algunos comandos que tenemos disponibles cuando desarrollamos la aplicación web:
- grunt serve => Ejecuta la aplicación en el navegador. Con la opción –livereload habilitamos que cualquier cambio en el código de la aplicación se vea inmediatamente reflejado en el navegador, sin tener que reiniciar.
- grunt serve:compress => Lo mismo pero con los archivos fuente minificados.
- grunt jshint => comprueba si estamos cumpliendo todas las normas de estilo en nuestro código.
- grunt karma => deja corriendo el testrunner favoreciendo el desarrollo de nuestra aplicación con TDD, al tener un feedback permanente del estado de los tests.
- grunt coverage => ofrece un informe de la cobertura de nuestros test usando Istanbul.
En el momento de necesitar probar el desarrollo en el dispositivo móvil, debido a que estemos utilizando funcionalidad nativa, tenemos los siguientes comandos:
- grunt platform:add:{platform} => equivale a ejecutar el comando de Cordova “cordova platform add {platform}”. De esta forma añadimos todas las plataformas que queramos soportar. Ejemplo, “grunt platform:add:android”
- grunt plugin:add:{plugin} => equivale al comando de Cordova “cordova plugins add {plugin}”. Ejemplo, “grunt plugin:add:org.apache.cordova.device”
- grunt [emulate|run]:{target} => como el comandos de Cordova podemos decidir entre probar la aplicación en un dispositivo fijo o hacerlo en un emulador. También soporta el livereload y podemos hacer que los console.log se muestren en el terminal gracias al flag –consoleLogs. Ejemplo, “grunt run:android –livereload –consoleLogs”
- grunt build:{target} => genera el ejecutable de la plataforma indicada. Ejemplo, “grunt build:android”. Acepta los flags –release o –debug para indicar el tipo de versión que se quiere obtener.
6. Workflow altamente productivo
Buscando la forma más productiva de desarrollar este tipo de aplicaciones lo que se puede hacer es tener la pantalla dividida: a la izquierda el editor que más nos guste (Sublime Text, Eclipse, …) y a la derecha el emulador del dispositivo móvil.
Por si os ayuda yo tengo a la izquierda como editor Aptana que es un plugin de Eclipse y a la derecha tengo abierto un emulador de Genymotion. Como véis en la siguiente imagen:
Ahora desde un terminal ejecutamos:
grunt run:android --livereload
La aplicación se depliega en el emulador, utilizamos run porque los emuladores de Genymotion se tratan como si tuviéramos un dispositivo móvil enganchado al USB de nuestro ordenador, y con el flag «livereload» cualquier cambio en el código fuente de la aplicación inmediatamente lo vemos reflejado en el dispositivo.
Además en caso de no saber en algún momento por qué está fallando nuestra aplicación, si nuestro emulador tiene una versión superior a la 4.4, podemos utilizar el «Inspect Devices» de Chrome que nos permite depurar la apliación: ver los fuentes, las variales, los scopes, poner puntos de ruptura, etc…
7. Incluimos la librería ngCordova
Trabajando con AngularJs contamos con la librería ngCordova que facilita el uso de una gran cantidad de plugins de Cordova registrándolos por nosotros como servicios de AngularJS, lo que facilita su utilización mediante la inyección de dependencias. Para poder hacer uso de esta librería tenemos que registrarla en nuestra aplicación con bower:
bower install ngCordova --save
Ahora para que se incluya automáticamente la referencia a esta librería en nuestro index.html ejecutamos:
grunt init
Por último la incluimos como dependencia en la declaración del módulo de nuestra aplicación que se encuentra en el fichero app.js.
angular.module('PocCordova', ['ionic', 'config', 'PocCordova.controllers',’ngCordova’])
Siguiendo estos pasos ya podemos hacer uso de los servicios que se describen en esta página: http://ngcordova.com/docs
8. Caso de uso: crear una opción de menú que muestre la información del dispositivo
Por ejemplo, si queremos hacer uso plugin “Device” el cual nos devuelve información relativa a las caracteristicas del dispositivo, solo tenemos que registrar de la manera habitual el plugin de Cordova, en este caso:
cordova plugin add org.apache.cordova.device
o
grunt plugin:add:org.apache.cordova.device
Para añadir una nueva opción al menú tenemos que editar el fichero menu.html añadiendo el siguiente item a la lista en la posición deseada:
<ion-item nav-clear menu-close href="#/app/info_device"> Info Device </ion-item>
El siguiente paso será actualizar el router de nuestra aplicación. Para ello vamos a editar el fichero app.js y vamos a añadir un nuevo “state” al “routerProvider” que viene definido.
.state('app.info_device', { url: '/info_device', views: { 'menuContent' :{ templateUrl: 'templates/info_device.html', controller: 'InfoDeviceCtrl' } } })
Hemos establecido que la información se va a mostrar en la página “templates/info_device.html” por lo cual ahora vamos a crear este fichero con el siguiente contenido:
<ion-view title="Info Device"> <ion-nav-buttons side="left"> <button menu-toggle="left"class="button button-icon icon ion-navicon"></button> </ion-nav-buttons> <ion-content class="has-header"> <p>Cordova: {{cordova}}</p> <p>Model: {{model}}</p> <p>Platform: {{platform}}</p> <p>UUID: {{uuid}}</p> <p>Versión: {{version}}</p> </ion-content> </ion-view>
Y los valores los vamos a recuperar y setear en el controlador “InfoDeviceCtrl” por lo que ahora en el fichero controller.js lo creamos, inyectándole el servicio de ngCordova que recupera la información del dispositivo ($cordovaDevice) y el servicio de Ionic que nos permite saber si el dispositivo ya está preparado ($ionicPlatform), el contenido quedaría de esta forma:
.controller('InfoDeviceCtrl', function($scope, $cordovaDevice, $ionicPlatform) { $ionicPlatform.ready(function(){ $scope.device = $cordovaDevice.getDevice(); $scope.cordova = $cordovaDevice.getCordova(); $scope.model = $cordovaDevice.getModel(); $scope.platform = $cordovaDevice.getPlatform(); $scope.uuid = $cordovaDevice.getUUID(); $scope.version = $cordovaDevice.getVersion(); }); })
Ahora ejecutamos la aplicación en un dispositivo físico ya que estamos haciendo uso de una funcionalidad nativa, por ejemplo si queremos probarlo en Android haríamos
grunt platform:add:android grunt run:android
Y en la opción de menú correspondiente tendremos que ver algo parecido a esto:
9. Conclusiones
Como habéis podido comprobar la utilización del generator-ionic de Yeoman es un estupendo punto de partida para crear aplicaciones en la plataforma Apache Cordova
con las tecnologías AngulaJS e Ionic.
Cualquier duda o sugerencia en la zona de comentarios.
Saludos.
Hola Rubén:
Espero me puedas ayudar porque estoy un poco perdido, seguramente sea una tontería.. pero te explico:
Resulta que estoy haciendo un socket en java en el que lo tengo hecho en modo texto, tengo una clase servidor en la que se ejecuta continuamente (while(true)) y otra clase cliente la cual se va conectando al servidor. El problema lo tengo en que la clase servidor, es decir el código me lo he llevado a un Jframe con dos botones para poder iniciarlo y pararlo, el caso es que estoy teniendo problemas con el while(true) ya que no me responde como quisiera, ya que la interfaz como se bloquea.
Un saludo.
Hola Manuel,
Seguramente ya lo hayas resuelto pero para lo que comentas te aconsejo que mires este otro tutorial: http://adictosaltrabajo.com/tutoriales/ejemplo-swing-worker/
Saludos
HOla Rubén.
El tuturial está muy bien y te lo agradezco, tengo dos consultas: He sido durante años desarrollador de Java SE ahora quiero dedicarme a las apps, he estado bajando y viendo tutoriales de Android Studio pero leyendo tu tutorial creo que sería mejor que intentara con Cordova para diversificar las apps a otros sistemas operativos más allá de Android, entonces, ¿Crees que es una buena idea iniciar en un entorno multiplataforma en lugar de algo nativo? y ¿Dónde puedo encontrar tutoriales para iniciarme en Cordova?
Hola Ian,
Mi opinión es que el 95% de las aplicaciones móviles se pueden desarrollar como aplicaciones híbridas implementadas con tecnologías web (JS, CSS y HTML).
De hecho te aconsejo que le eches un vistazo a tecnologías como NativeScript o ReactNative que crean aplicaciones nativas implementadas con tecnologías web.
Además viniendo de Java estarás acostumbrado a la orientación objetos por lo que el nuevo TypeScript te viene como anillo al dedo, ya que introduce conceptos como las clases y las interfaces para el desarrollo de aplicaciones cliente web.
Realmente Cordova solo es el «wrapper» que encapsula la aplicación web para poder ser distribuida en las distintas plataformas móviles, así que lo que realmente necesitas es saber como crear aplicaciones cliente web, para lo que te recomiendo Angular y Angular 2.
Espero haber aclarado tus dudas.
Saludos
Hola Ruben tengo un serio problema no puedo agregar la plataforma android , no se como crear un config.XML y dar permisos a hook, tendrías algún ejemplo?
Hola Sebastian,
No entiendo muy bien el problema… El fichero config.xml se crea de forma automática cuando creas el proyecto el comando «cordova create myApp org.apache.cordova.myApp myApp» y para agregar la plataforma Android hay que ejecutar «cordova platform add android»
¿A qué te refieres con dar permisos al hook?
Saludos
Saludos Rubén.
Ayudame por favor. Tengo éste problema al ejectuar el comando.
ionic build android
me muestra lo siguiente:
(node:800) fs: re-evaluating native module sources is not supported. If you are using the graceful-fs module, please update it to a more recent version.
Updated the hooks directory to have execute permissions
Gracias por tu ayuda!
Hola Jaime,
Comprueba que estás usando las últimas versiones de las dependencias. Una forma muy fácil y rápida de verlo es siguiendo este otro tutorial: http://adictosaltrabajo.com/tutoriales/gestion-del-estado-de-las-dependencias-npm/
Espero que te ayude.
Saludos
ayúdame por favor a enlazar el contenido de la lista en mi proyecto, ya lo intente de varias maneras y no me sale, tengo 5 elementos en mi lista y en cualquiera que le de me manda al mismo contenido. estoy utilizando los estados: este es uno de los primeros y si funciona es el que enlaza con la pagina del contenido, pero todas me mandan a la misma pagina.
.state(‘app.campo limpio’, {
url: ‘/home/:contenidoid’,
views: {
‘menuContent’: {
templateUrl: ‘templates/contenido.html’,
controller: ‘contenidoCtrl’
}
}
})
y este es el controlador:
.controller(‘homeCtrl’, function($scope) {
$scope.home = [
{ title: ‘Campo limpio’, id:1 },
{ title: ‘Contaminación’, id:2 },
{ title: ‘7 habitos’, id:3 },
{ title: ‘Centro de acopio temporal’, id:4 },
{ title: ‘Transporte’, id:5 },
];
})
.controller(‘contenidoCtrl’, function($scope, $stateParams) {
});
disculpa no puedo instalar bower install ngCordova me dice que no encuentra el paquete
Hola Miguel,
Prueba con «bower install ng-cordova», también te digo que esta tecnología ya no se utiliza y ha sido sustituida por Ionic-Native con Angular. Te aconsejo que si recién empiezas con esto, lo hagas con Ionic 3, Ionic-Native y Angular.
Saludos