Vamos a crear una pequeña práctica con la que aprenderemos las características básicas de Cordova, manejar la API de para usar las características nativas del dispositivo y a crear una aplicación con una arquitectura óptima para móviles.
Objetivos
- Usar diferentes estrategias para el almacenamiento local de datos.
- Uso de las APIs de Cordova para Geolocalización, Contactos y Cámara.
- Como manejar ciertos problemas específicos de móviles como los eventos táctiles, scrolling, estilos, transiciones entre páginas, etc.
- Como construir una aplicación utilizando una arquitectura de una sola página (SPA – Single Page Application)
- Como compilar y empaquetar (build) una aplicación de forma local usando la CLI de Cordova.
Requerimientos:
- Conocimiento de html, JavaScript y jQuery.
- Un movil o emulador y el SDK de una plataforma (iOS, Android, etc.) instalado en el equipo. De no estar instalado solo se podrá testear la aplicación vía navegador.
- La práctica la he realizado con un sistema operativo Linux (Ubuntu 12.04). En principio se podría realizar también desde Windows o Mac
Referencias:
- Web del proyecto Apache Cordova
- Tutorial para crear una aplicación en PhoneGap en el que está basado este documento.
1. Crear un proyecto Cordova
- Asegúrate de tener una versión actualizada de Node.js instalada en tu equipo.
- Abre una terminal y ejecuta el siguiente comando para instalar cordova a nivel global (modificador -g):
1sudo npm install -g cordova - Colocate en el directorio donde quieras almacenar tus proyectos. Por ejemplo:
1cd ~/Proyectos - Crea un proyecto llamado Practica:
1cordova create practica com.tunombre.practica PracticaEl primer parámetro es el directorio donde se guardará e proyecto. El segundo es un identificador para el proyecto con estructura de DNS inverso, el tercero es el nombre del proyecto y título que mostrará la aplicación. Puede ser útil poner el modificador -d para mostrar el progreso de creación del proyecto
- Entra en el directorio del proyecto:
1cd practica - Añade las plataformas que quieras soportar:
1234cordova platform add ioscordova platform add androidcordova platform add wp8cordova platform lsOjo, necesitarás los sdk para añadir las plataformas y no siempre es posible: el de IOS solo va en Mac, el de Windows Phone en Windows :-(.
1234juanda@juandapc:~/proyectos/practica$ cordova platform lsInstalled platforms: android 3.4.0Available platforms: blackberry10, firefoxos, ubuntujuanda@juandapc:~/proyectos/practica$ - Asegurate que estás en el directorio “practica” y añade estos plugins básicos a tu proyecto:
12cordova plugin add org.apache.cordova.devicecordova plugin add org.apache.cordova.consoleExtraido de la documentación de los plugins:
Plugin console:
This plugin is meant to ensure that console.log() is as useful as it can be. If you are not unhappy with how console.log() works for you, then you probably don’t need this plugin.Plugin device:
This plugin defines a global device object, which describes the device’s hardware and software.Although the object is in the global scope, it is not available until after the deviceready event.123456789101112document.addEventListener("deviceready", onDeviceReady, false);function onDeviceReady() {console.log(device.cordova);}## Propertiesdevice.cordovadevice.modeldevice.namedevice.platformdevice.uuiddevice.version - Examina la estructura de directorios creada en tu proyecto.
2. Hacer el build del proyecto Cordova
iOS
Nos hará falta el SDK de iOS instalado en el ordenador para poder hacer el build de nuestra aplicación, siguiendo los siguientes pasos:
1 |
cordova build ios |
El proyecto se genera en la carpeta workshop/platforms/ios. Si haces doble clic en Workshop.xcodeproj puedes abrir el proyecto en XCode,
y ejecutarlo en el emulador o en tu dispositivo
Puedes ejecutar también la aplicación en el emulador directamente desde la línea de comandos. Primero instala ios_sim:
1 |
sudo npm install -g ios-sim |
Luego ejecuta la aplicación en el emulador iOS:
1 |
cordova emulate ios |
Android
Necesitas el SDK de Android instalado en tu ordenador.
Para generar el proyecto en la carpeta workshop/platforms/android y ejecutarlo en un dispositivo Android conectado a tu ordenador por USB:
1 |
cordova run android |
Para generar el proyecto en la carpeta workshop/platforms/android y ejecutarlo en un emulador:
1 |
cordova emulate android |
El propio parámetro emulate o run llevan intrínseco hacer un build. El build a su vez está compuesto de dos fases, prepare y compile, que se pueden hacer por separado.
3. Ficheros para la práctica
-
Descarga y descomprime los ficheros para trabajar o clona este repositorio.
1juanda@dpto-01:~$ git clone https://github.com/juanda99/phonegap-tutorial - Borra todos los contenidos de la carpeta practica/www con la excepción del fichero config.xml.
En el fichero config.xml se guardan las características generales de la aplicación y configuraciones (preferences) como el color de fondo o si bloqueamos la orientación del dispositivo
1234567891011121314<?xml version='1.0' encoding='utf-8'?><widget id="com.juanda.workshop" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0"><name>workshop</name><description>A sample Apache Cordova application that responds to the deviceready event.</description><author email="dev@cordova.apache.org" href="http://cordova.io">Apache Cordova Team</author><content src="index.html" /><access origin="*" /></widget><preference name="Orientation" value="landscape" /><preference name="BackgroundColor" value="0xff0000ff"/> - Copia los contenidos de cordova-tutorial/www en la carpeta de tu proyecto practica/www
- Si tienes un SDK instalado en tu sistema haz el build de tu aplicación según el punto anterior y ejecútala desde el móvil o el emulador. En caso contrario abre directamente el fichero index.html con un navegador
- Escribe unos pocos caracteres en la caja de búsqueda para buscar empleados por nombre. Posteriormente implementaremos enlaces a cada uno de los empleados
4. Elegir un método de almacenamiento
Los distintos métodos de almacenamiento están definidos mediante ficheros y clases independientes. La idea es que todas las clases presenten la misma interfaz de modo que utilizar uno u otro método de almacenamiento sea transparente para el desarrollo de la aplicación.
- Almacenamiento en memoria (fichero memory-adapter.js)
- Almacenamiento en remoto (fichero jsonp-adapter.js)
- Almacenamiento mediante LocalStorage (fichero localstorage-adapter.js)
- Almacenamiento en base de datos local (fichero websql-adapter.js)
- Abre cada uno de los ficheros anteriores para explorar cada uno de los métodos de almacenamiento.
- Prueba la aplicación con cada uno de los métodos de almacenamiento anteriores
La aplicación por defecto está configurada para trabajar con almacenamiento en memoria. Para cambiar el método de almacenamiento:
- En el fichero index.html, cambia el fichero memory-adapter.js por el que corresponda: jsonp-adapter.js, localstorage-adapter.js, o websql-adapter.js.
- En js/app.js, reemplaza la instanciación de MemoryAdapter con el que corresponda según el método de almacenamiento elegido: JSONPAdapter, LocalStorageAdapter, o WebSqlAdapter.
- Prueba la aplicación
5. Uso de notificación nativa
-
El típico alert de JavaScript puede ser algo rígido para tu aplicación PhoneGap que aparenta ser nativa. Puede ser que queramos personalizar la ventana de aviso mediante un título, un texto específico en el botón o incluso una función de callback. La función alert de JavaScript no nos lo va a permitir.
Para hacer una llamada a la ventana de diálogo nativa deberemos añadir el plugin correspondiente:
1cordova plugin add org.apache.cordova.dialogs -
Al utilizar nuestra aplicación algo nativo, deberemos añadir la librería cordova.js:
1<script src="cordova.js"></script>
Esta instrucción hara que Cordova inserte la versión específica de Cordova a la plataforma en la que estemos desarrollando en tiempo de compilación. Es decir, el fichero cordova.js no debería estar presente en la carpeta www de nuestro proyecto. -
Por último deberemos hacer un override de la función window.alert() cuando ejecutemos nuestra aplicación en un dispositivo que disponga del objeto navigator.notification.alert(). Añadiremos el siguiente código en nuestra aplicación (fichero app.js, en el bloque de registro de eventos):
123456789101112document.addEventListener('deviceready', function () {if (navigator.notification) { // Si disponemos de notificaciones nativas, sobreescribimos el alert del navegador:window.alert = function (message) {navigator.notification.alert(message, // mensajenull, // función de callback"Workshop", // título'OK' // Nombre botón);};}}, false); - Prueba a ejecutar la aplicación desde el dispositivo móvil o emulador y desde el navegador del PC. Observa que la notificación cambia en función del entorno.
6. Evita el retraso de 300ms en el clic
Si pulsas el botón de ayuda y según el dispositivo/emulador puedes notar cierto retraso hasta que aparece la ventana de diálogo.
Esto es debido a que el navegador puede esperar en torno a 300ms por si el usuario hace un doble clic. Para evitarlo podemos utilizar alguna librería de JavaScript como FastClick
-
Añade el script en el fichero index.html:
1<script src="lib/fastclick.js"></script> -
Registra FastClick en el fichero app.js. En la documentación de FastClick se explica como integrarlo, pero quizá lo más sencillo sea dentro de la función manejadora del evento deviceready que hemos utilizado en el paso anterior, añadiendo la siguiente instrucción:
1FastClick.attach(document.body); - Comprueba desde el emulador o movil que ha desaparecido el retraso si hubiese. En principio bajo Chrome y al tener el viewport con user-scalable=no, no sería necesario.
7. Arquitectura SPA
Vamos a configurar ahora nuestra aplicación para que se ejecute toda nuestra aplicación desde una sola página. Es muy conveniente este tipo de diseño en aplicaciones móviles porque su funcionamiento será más fluido y pretendemos que la velocidad de ejecución sea lo más parecido a ejecutar código nativo.
Si no estás familiarizado con aplicaciones de una sola página, te recomiendo que eches un ojo a este post sobre diseño y arquitecturas SPA.
- En el fichero index.html borramos todo el contenido del body (salvo los scripts) ya que lo generaremos mediante JavaScript
- Definiremos una función que será la encargada de renderizar el home de nuestra aplicación, dentro de la sección de funciones locales del script app.js:
123456789function renderHomeView() {var html = "<header>" +"<h1>Futbolistas</h1>" +"</header>" +"<input id='btnBuscar' type='search' placeholder='Introduce futbolista'/>" +"<ul id='lstFutbolistas'></ul>"$('body').html(html);$('#btnBuscar').on('keyup', encontrarPorNombre);} - Observa que hemos quitado el botón de ayuda y que el registro del evento keyup lo metemos dentro de la función renderHomeView, por lo que deberemos quitarlo de donde estaba anteriormente (sección registro de eventos). También quitaremos el manejador del botón de ayuda.
- Modificaremos la lógica de la aplicación, de modo que una vez que se inicialice el adaptador de datos se muestre la vista de la página inicial:
1234adapter.inicializar().done(function () {console.log("Inicializado: Adaptador de datos");renderHomeView();});
8. Elección de framework css
A la hora de mostrar nuestro html en pantalla es importante utilizar un framework css específico de móvil, es decir, diseñado para un renderizado rápido:
- Uso propiedades específicas de css para animaciones, que utilicen la GPU
- Evitar el uso de propiedades como box-shadow, border-radius, gradientes o text-align
Últimamente han salido muchos frameworks, como Ionic que viene “preparado” para funcionar con Angularjs y que se integra perfectamente con PhoneGap, Intel App Framework que viene preparado con un css específico para cada plataforma móvil, para simular más el aspecto nativo, y Topcoat de Adobe. Hay muchos más, utilizaremos este último.
9. Uso de templates: handlebars
Escribir código html desde JavaScript es propenso a errores (comillas simples en vez de dobles, alternar texto con variables…) y además poco legible.
Utilizaremos templates para desacoplar la definición de la interfaz de usuario (html) del código. Si no has usado nunca handlebars, echa un vistazo a la documentación oficial (es corta) y a un post de ejemplo de uso de handlebars y otro post de precompilación de handlebars.
-
Vamos a crear dos templates, una para la página de inicio y otra para mostrar los elementos de la lista de futbolistas, que guardaremos en la carpeta templates.
En la página de inicio y según la documentación de topcat.io necesitaremos los siguientes elementos:
- Navigation bar
- Search Input
- List
Plantilla para la página de inicio (fichero home.handlebars):
123456789101112<div class="topcoat-navigation-bar"><div class="topcoat-navigation-bar__item center full"><h1 class="topcoat-navigation-bar__title">Futbolistas</h1></div></div><div class="search-bar"><input type="search" value="" placeholder="buscar" class="topcoat-search-input" id="btnBuscar"></div><div class="topcoat-list"><ul class="topcoat-list__container list" id="lstFutbolistas"></ul></div>Plantilla para la lista de futbolistas (fichero listaJugadores.handlebars):
12345678910{{#.}}<li class="topcoat-list__item"><a href="#futbolistas/{{id}}"><img src="assets/img/{{imagen}}"><p>{{nombre}} {{apellido}}</p><p>{{equipo}}</p><span class="chevron"></span></a></li>{{/.}} -
Precompilamos las plantillas:
1$ handlebars templates/ -f js/templates.js
-
Cambiamos las funciones de app.js para que carguen el template:
123456789function renderHomeView() {$('body').html(Handlebars.templates.home());$('#btnBuscar').on('keyup', encontrarPorNombre);}function encontrarPorNombre() {adapter.encontrarPorNombre($('#btnBuscar').val()).done(function (futbolistas) {$("#lstFutbolistas").html(Handlebars.templates.listaJugadores(futbolistas));});}
-
Copiamos el framework de topcoat dentro de nuestro proyecto. Podemos elegir entre un theme claro y otro oscuro.
1<link href="assets/topcoat/css/topcoat-mobile-light.css" rel="stylesheet"> -
Cargamos también el script de handlebars (al precompilar, cogeremos el runtime) y los templates precompilados:
12<script src="lib/handlebars.runtime-v1.3.0.js"></script><script src="js/templates.js"></script> - Si probamos el resultado, vemos que se le puede dar un toque adicional de diseño. Debemos crear un fichero style.css que añadiremos a nuestro index.html:
1<link href="assets/css/styles.css" rel="stylesheet">
Contenido fichero style.css:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687/*Situamos la caja de búsqueda dentro de un div y le damos el 100% de anchura*/.search-bar {padding:10px 10px 12px 8px;}.search-bar > input {width: 100%;}a {text-decoration: none;color: inherit;-webkit-touch-callout: none;-webkit-tap-highlight-color: rgba(0, 0, 0);}.list {list-style-type: none;border-top: none !important;}.list > li {position: relative;clear: both;padding: 0px;margin: 0px;}.list > li:nth-of-type(1) {border-top: none;}.list > li > a {margin: 0px;display: block;height: 57px;padding: 4px;}.list > li > a > p:nth-of-type(1) {margin: 8px 0px 0px 0px;font-weight: bold;}/*El nombre del juegador en negro, el equipo en gris:*/.list > li p:nth-of-type(2) {margin: 0px;color: #777;}/*Las imágenes en la lista, con un ancho fijo, y el texto a su derecha:*/.list > li img {width: 57px;height: 57px;float: left;margin-right: 8px;}/*Cuando pulsamos en un elemento de la lista, le cambiamos el color*/.list li:active {background-color: #d6d6d6;}/*Añadimos para que el header no haga scroll:*/.scroller {overflow: auto;/*iOS 4 or lower required an esoteric two finger gesture to scroll elements but normality was achieved from iOS 5. Unlike other browsers, while overflow:auto works, momentum scrolling is disabled unless you also add -webkit-overflow-scrolling: touch.*/-webkit-overflow-scrolling: touch;position: absolute;top: 141px;bottom: 0px;left: 0px;right: 0px;}.chevron {background: transparent url(../img/next_blue.svg);background-repeat: no-repeat;background-size: contain;width: 20px;height: 20px;position: absolute;right: 12px;top: 22px;}
10. Crear una clase vista
Vamos a dar algo más de estructura a la aplicación, “adelgazando” el fichero app.js. Nos llevaremos toda la lógica de como crear las vistas a otro fichero-clase, HomeView.js, que encapsulará la lógica de creación y renderizado de la vista. Debemos pensar que puede haber muchas vistas, y de este modo, cada una de ellas estará en su propia clase, sin cargar en exceso el núcleo de nuestra aplicación, el fichero app.js.
- Creamos la clase HomeView
- Eliminamos las funciones renderHomeView y encontrarPorNombre de app.js
- Cargamos el script de HomeView.js en nuestro index.html antes de cargar app.js
1<script src="js/HomeView.js"></script> -
Modificamos la función de inicialización de app.js para que renderice la vista de inicio mediante la clase HomeView recién creada:
123adapter.inicializar().done(function () {$('body').html(new HomeView(adapter).render());});
El código será el siguiente:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
var HomeView = function (adapter) { this.inicializar = function () { // Definimos un div para la vista. Lo usaremos para añadir eventos. this.el = $('<div/>'); this.el.on('keyup', '#btnBuscar', this.encontrarPorNombre); }; this.render = function() { this.el.html(Handlebars.templates.home()); return this.el; //esto es lo que hemos movido de app.js aquí: //$('body').html(Handlebars.templates.home()); //La siguiente línea sobra, ya está puesta al inicializar: //$('#btnBuscar').on('keyup', encontrarPorNombre); }; //este método lo movemos tal cual de app.js: this.encontrarPorNombre = function() { adapter.encontrarPorNombre($('#btnBuscar').val()).done(function (futbolistas) { $("#lstFutbolistas").html(Handlebars.templates.listaJugadores(futbolistas)); }); }; this.inicializar(); } |
11. Implementar scrolling nativo
Cuando la lista de futbolistas es mayor que la ventana del navegador, si nos desplazamos, toda la vista hace scrolling (incluido el header).
Para que el scroll se produzca solo en la lista de futbolistas:
- Crea una clase adicional en el fichero assets/css/styles.css con el siguiente contenido:
123456789.scroller {overflow: auto;-webkit-overflow-scrolling: touch;position: absolute;top: 141px;bottom: 0px;left: 0px;right: 0px;} - Añade la clase scroller en el div de la lista de jugadores (plantilla home.handlebars)
1<div class="topcoat-list scroller"> - Por último, ¡no olvides hacer la precompilación del template antes de comprobar el resultado!
En IOS, puede que aún así el header también haga scroll. Deberemos configurar la siguiente línea en el fichero config.xml:
1 <preference name="DisallowOverscroll" value="true" />Podemos optar por soluciones más potentes con la ayuda de librerías como iScroll.
12. Enrutado de vistas
Vamos a crear otra vista en la que mostraremos los detalles de cada jugador. Al tener ahora nuestra aplicación más de una vista, habrá que implementar algún mecanismo de enrutado que determine si debemos mostrar la vista de inicio o la de detalle del jugador.
Implementamos la nueva vista
- Creamos nuestra nueva plantilla, mediante el fichero templates/jugador.handlebar:
1234567891011121314151617181920212223242526272829<div class="topcoat-navigation-bar"><div class="topcoat-navigation-bar__item left quarter"><a class="topcoat-icon-button--quiet back-button" href="#"><span class="topcoat-icon topcoat-icon--back"></span></a></div><div class="topcoat-navigation-bar__item center half"><h1 class="topcoat-navigation-bar__title">Futbolistas</h1></div></div><div class='detalles scroller'><img src="assets/img/{{imagen}}" class="imagen-futbolista"><h1>{{nombre}} {{apellido}}</h1><p><strong>Equipo:</strong> {{equipo}} </p><p><strong>Posición: </strong>{{posicion}}</p><p><strong>Dorsal:</strong> {{dorsal}}</p><p><em>{{desc}}</em></p><div class="topcoat-list__container clearfix"><ul class="topcoat-list list actions"><li class="topcoat-list__item"><a href="tel:+34606606606"><p>Llamar al móvil</p><p>+34606606606</p><div class="action-icon icon-call"/></a></li><li class="topcoat-list__item"><a href="tel:+34606606606"><p>Llamar al fijo</p><p>+34976414141</p><div class="action-icon icon-call"/></a></li><li class="topcoat-list__item"><a href="sms:+34606606606"><p>Enviar SMS</p><p>+34606606606</p><div class="action-icon icon-sms"/></a></li><li class="topcoat-list__item"><a href="mailto:micorreo@gmail.com"><p>Enviar correo electrónico</p><p>micorreo@gmail.com</p><div class="action-icon icon-mail"/></a></li><li class="topcoat-list__item"><a href="#" class="add-location-btn"><p>Añadir posición</p></a></li><li class="topcoat-list__item"><a href="#" class="add-contact-btn"><p>Añadir a contactos</p></a></li><li class="topcoat-list__item"><a href="#" class="change-pic-btn"><p>Hacer una foto nueva</p></a></li></ul></div></div> - Precompilamos las plantillas al haber creado una nueva:
1$ handlebars templates/ -f js/templates.js - Creamos la clase JugadorView con el siguiente contenido (fichero js/FutbolistaView.js):
12345678910var JugadorView = function(adapter, futbolista) {this.inicializar = function() {this.el = $('<div/>');};this.render = function() {this.el.html(Handlebars.templates.jugador(futbolista));return this.el;};this.inicializar();} -
Cargamos el script FutbolistaView.js en el fichero index.html antes del script app.js
1<script src="js/JugadorView.js"></script>
Implementamos el enrutado
La función de enrutado tendrá que ir en el fichero app.js.
- Creamos una variable con la expresión regular que utilizaremos para mostrar o no la vista de un jugador en concreto. La guardaremos en la sección de variables locales del fichero app.js:
1var futbolistaURL = /^#futbolistas\/(\d{1,})/; -
Definiremos un nuevo listener para cuando haya cambios en el hash de la url, dentro de la sección registro de eventos del fichero app.js
1$(window).on('hashchange', route); -
En la sección de funciones locales, definiremos la función route, que se encargará de enrutar a la vista concreta.
123456789101112function route() {var hash = window.location.hash;if (!hash) {$('body').html(new HomeView(adapter).render());return;}var match = hash.match(futbolistaURL);if (match) {adapter.encontrarPorId(Number(match[1])).done(function(futbolista) {$('body').html(new JugadorView(adapter, futbolista).render());});} -
Cambiaremos la lógica de la inicialización del adaptador, para que llame a la función de enrutado (fichero app.js) para que cargue la vista que corresponda en función de la url, en vez de cargar siempre la de HomeView:
12345adapter.inicializar().done(function () {console.log("Inicializado: Adaptador de datos");//$('body').html(new HomeView(adapter).render());route();}); -
He añadido varios varias líneas al fichero
1assets/css/style.css
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374/*Todo lo siguiente lo añadimos para modificar la presentación de la vista de jugador:*/.back-button {position: absolute;top: 10px;}.topcoat-icon--back {background: url("../img/back_light.svg") no-repeat;-webkit-background-size: cover;-moz-background-size: cover;background-size: cover;}.detalles {margin: auto;/*para no utilizar el top que he puesto en scroller:*/top: 71px !important;}.detalles>img {float:left;margin:10px;width: 250px;height: 250px;}.detalles h1 {padding: 12px 0px 4px 0px;margin: 0px 0px 0px 0px;font-size: 1.2rem;}.detalles p {padding: 0px 0px 4px 0px;margin: 0px 0px 0px 0px;}.actions > li > a {padding-left: 12px;}.action-icon {position: absolute !important;top: 18px;right: 20px !important;width: 28px !important;height: 28px;}.actions li p:nth-of-type(1) {color: #5DC1FF;font-size: 0.9em;font-weight: lighter;}.actions li p:nth-of-type(2) {color: inherit;}.icon-call {background: transparent url(../img/call.svg);background-repeat: no-repeat;-webkit-background-size: cover;-moz-background-size: cover;background-size: cover;}.icon-sms {background: transparent url(../img/chat.svg);background-repeat: no-repeat;-webkit-background-size: cover;-moz-background-size: cover;background-size: cover;}.icon-mail {background: transparent url(../img/email.svg);background-repeat: no-repeat;-webkit-background-size: cover;-moz-background-size: cover;background-size: cover;}.clearfix{clear: both;} - Por último probamos que el enrutamiento funcione y se muestre la nueva vista.
13. Uso del API de localización
Vamos a mostrar las coordenadas (longitud y latitud) mediante una alerta. En una aplicación real, lo guardaríamos en una base de datos como parte de la información del futbolista y al visualizar la ficha mostraríamos los datos de localización en un mapa.
Para utilizar APIs deberíamos ver la doc de Cordova
- Añadimos el plugin de geolocalización a nuestro proyecto:
1$ cordova plugin add org.apache.cordova.geolocation -
Registramos en la función inicializar() de clase JugadorView un event listener para el evento clic en el elemento de la lista “Añadir Localización” (fichero js/JugadorView.js):
1this.el.on('click', '.add-location-btn', this.addLocation); - Comprobamos su funcionamiento
Registramos también en la clase JugadorView el manejador de evento addLocation:
1 2 3 4 5 6 7 8 9 10 11 |
this.addLocation = function(event) { event.preventDefault(); navigator.geolocation.getCurrentPosition( function(position) { alert(position.coords.latitude + ',' + position.coords.longitude); }, function() { alert('Error obteniendo localización'); }); return false; }; |
14. Uso del API de contactos
Vamos a permitir añadir a cualquier futbolista a nuestra lista de contactos.
El código siguiente solo funciona al ejecutar la aplicación en un dispositivo como aplicación Cordova. No se puede probar desde un navegador en el PC.
Para utilizar APIs deberíamos ver la doc de Cordova
-
Añadimos el plugin a nuestro proyecto:
1$ cordova plugin add org.apache.cordova.contacts -
Registramos en la función inicializar() de clase JugadorView un event listener para el evento clic en el elemento de la lista “Añadir a Contactos” (fichero js/JugadorView.js):
1this.el.on('click', '.add-contact-btn', this.addToContacts); - Comprobamos su funcionamiento
Registramos también en la clase JugadorView el manejador de evento addToContacts:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
this.addToContacts = function(event) { event.preventDefault(); console.log('Añadiendo a Contactos'); if (!navigator.contacts) { alert("El API de contactos no está soportada", "Error"); return; } /*Según doc de Cordova: https://github.com/apache/cordova-plugin-contacts/blob/master/doc/index.md: */ // create a new contact object var contact = navigator.contacts.create(); contact.displayName = "Futbolista"; contact.nickname = "Futbolista"; // specify both to support all devices // populate some fields var name = new ContactName(); name.givenName = futbolista.nombre; name.familyName = futbolista.apellido; contact.name = name; // save to device contact.save( function () { alert ("Futbolista guardado en los contactos del teléfono"); }, function () { alert("uppps, no ha ido bien: " + contactError.code) } ); }; |
15. Uso del API para la cámara de fotos
El código siguiente solo funciona al ejecutar la aplicación en un dispositivo como aplicación Cordova. No se puede probar desde un navegador en el PC.
No guardamos la foto de forma persistente, tan solo probamos la captura de una nueva foto.
Para utilizar APIs deberíamos ver la doc de Cordova
-
Añadimos el plugin a nuestro proyecto:
1$ cordova plugin add org.apache.cordova.camera -
Registramos en la función inicializar() de clase JugadorView un event listener para el evento clic en el elemento de la lista “Hacer una foto nueva” (fichero js/JugadorView.js):
1this.el.on('click', '.change-pic-btn', this.cambiarFoto); - Comprobamos su funcionamiento
Registramos también en la clase JugadorView el manejador de evento cambiarFoto:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
this.cambiarFoto = function(event) { event.preventDefault(); if (!navigator.camera) { alert("Camera API no soportada", "Error"); return; } var options = { quality: 50, destinationType: Camera.DestinationType.DATA_URL, sourceType: 1, // 0:Photo Library, 1=Camera, 2=Saved Album encodingType: 0 // 0=JPG 1=PNG }; navigator.camera.getPicture( function(imageData) { $('.imagen-futbolista', this.el).attr('src', "data:image/jpeg;base64," + imageData); }, function() { alert('Error al obtener la foto', 'Error'); }, options); return false; }; |