App mòbil Phonegap WebMapping

L'objectiu del taller és desenvolupar una APP amb Phonegap Build que permeti visualitzar damunt un mapa d'OpenStreetMap la posició del dispositiu obtinguda a partir del GPS i els contenidors de recollida selectiva més popers. Es podrà emprar l'API de dades de la IDE Menorca per a obtenir els contendors de recollida i la seva ubicació:

 

 

 

PhoneGap Build és un servei freemium que et permet compilar una aplicació híbrida directament en el núvol. És a dir, una eina ubicada al cloud que permet convertir codi HTML/CSS/Javscript en aplicacions per a dispositius mòbils, vàlides per a la majoria de plataformes (Android, IOS, Windows Phone, etc.)

 

Muntar tot l'entorn d'Android perquè funcioni correctament amb PhoneGap no és trivial. PhoneGap ofereix aquest servei (gratuït per a una sola app) juntament amb una àmplia documentació.

 

És doncs, un servei basat en el núvol que permet empaquetar les seves aplicacions webs com aplicacions mòbils natives. PhoneGap Build admet l'empaquetat d'aplicacions natives per als sistemes operatius de dispositius mòbils:

 
 

 

 

 

 

Aquest framework dóna la possibilitat d'interactuar amb el maquinari del mòbil: Acceleròmetre, càmera, contactes, geolocalització, sistema d'arxiu, emmagatzematge (bases de dades SQLite).

 

 

 

 

Per obtenir més informació sobre el servei PhoneGap Build, consulteu el lloc web de PhoneGap Build:

 

https://build.phonegap.com/

 

 

 

 

1.- Alta d'un nou usuari

 

El primer que cal fer és accedir al portal de Phonegap Build i crear un nou usuari en cas que no en tingurm cap de creat (Sign Up)

 

 

 

Veureu que hi ha diverses modalitats, però si volem fer una única app que no excedeixi de cert tamany, podem emprar un compte gratuït.

 

 
 

 

 

Només necessitem un email i un password:

 

 
 

 

 

 

Un cop creat l'usuari, només caldrà que ens acreditem (sign in) amb l'email i el password per entrar al nostre compte :

 

 

 

En accedir a Phonegap Build, ens apareixeran les apps que tenim penjades, en aquest cas inicial, cap:

 

 

 

 

 

 

2.- Preparant el codi:
 

És important mirar de tenir totes les llibreries Javscript i recursos en local enlloc d'estirar-los directament de servidors externs. Per tal de facilitar aquesta integració, hem preparat un arxiu .zip de descàrrega on hi ha totes les llibreries Jquery Mobile, OpenLayers i altres reursos que sovint s'empren alhora de desenvolupar aplicacions web mobile.

 

Feu un click al següent enllaç, guardeu l'arxiu i descomprimiu-lo a una carpeta del vostre servidor web:

 

 

Obre l'explorador d'arxius i observa l'estructura d'arxius: clàssica d'una aplicació web.

 

  • css: Carpeta d'Estils
  • img: Carpeta d'imatges
  • js: Carpeta d'arxius JavaScript
  • libs: Carpeta de recursos Javascript (OpenLayers, JQuery Mobile, etc.)
  • index.html: El nostre arxius principal

 

 

Veuràs que també hi ha alguna carpeta i arxiu que no són ben bé arxius "web" i que corresponen a arxius necessaris de Phonegap Build per a fabricar l'app.

 

 

  • Les carpetes "res/icon" i "res/splash" contenen les icones i imatges necessàries per a fer les icones de les app i les imatges de benvinguda
  • config.xml: Arxiu que configura els paràmetres de l'app (nom del paquet, autor, email, permisos, recursos, etc.)

 

 

 

 

Obre la pàgina index.html des d'un navegador web, accedint-hi com a servidor local i comprova que es mostra alguna cosa similar a aquesta:

 

 

 

 

 

Anem a veure el codi de l'arxiu index.html:

	<!DOCTYPE html>
	<html>
		<head>
			<meta charset="utf-8" />
			<meta name="format-detection" content="telephone=no" />
			<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, target-densitydpi=medium-dpi" />

			<link rel="stylesheet"  href="libs/jQM-flat/jquery.mobile.flatui.css">
			<link rel="stylesheet" type="text/css" href="css/index.css" />
			
			<title>Títol</title>

		</head>
		<body>
			<div id="app">

			
			
				<!-- 
				===========================
				PANTALLA INCIAL
				===========================
				-->
				<div id="pageHome" data-role="page" data-theme="b">
					<div data-role="header" data-position="fixed" data-id="headerFixed" data-tap-toggle="false" data-theme="a">
						<h1><div id="splashTitol">Titol</div></h1>
						<a href="#pageCredits" class="ui-btn-right" data-role="button" data-icon="info" data-iconpos="notext" data-rel="dialog" data-transition="fade">Crèdits</a>                    
					</div>
					<div data-role="content" role="main" style="padding:0px;">
						<div style="padding:10px;">
							<center>
								Contingut
							</center>
						</div>
						
					</div>
				</div> 		
			
				
				<!-- 
				===========================
				PANTALLA CREDITS
				===========================
				-->
				<div id="pageCredits" data-role="page" data-theme="b">
					<div data-role="header">
						<h1><div id="creditsTitol">Credits</div></h1>
					</div>
					<div data-role="content" role="main" style="padding: 10px;" data-theme="b">
						<center>
							<div style="font-size:20px;font-weight:bold;">Recollida selectiva</div>
							<div style="font-size:16px;">App IV Jornades Geogràfiques de Menorca</div>
							<p> </p>
							<center><img id="logoCredits" src="img/logo.png" style="width:85%;opacity:0.5;z-index:-1;"></center>
						</center>
					</div>

				</div> 	            
				
				
			</div>       
			

			<script type="text/javascript" src="libs/fastclick.min.js"></script>
			<script type="text/javascript" src="cordova.js"></script>
			<script type="text/javascript" src="libs/jquery-2.0.3.min.js"></script>
			<script type="text/javascript" src="libs/jQueryMobile/jquery.mobile-1.3.2.min.js"></script>
			
			
			<script type="text/javascript" src="js/index.js"></script>

			
			<script type="text/javascript">
				app.initialize();
			</script>
		</body>
	</html>

	 
							

 

 

 

 

 

No deixa de ser codi JQuery Mobile, amb les llibreries i estils en local, però amb dues particularitats:

 

  • Linea 82: cordova.js: Es crida un arxiu cordova.js que conté les llibreries Javascript necessàries per activar Phonegap-Cordova
  • Linea 101: app.initialize(): Es crida la funció initialize de l'objecte app definit a l'arxiu index.js

 

 

Quan totes les llibreries de Phonegap s'ha carregat dins l'aplicació, s'executa la funció "OnDeviceReady" que es troba a l'arxiu js/index.js. Tot el codi que implementem s'ha d'executar a partir d'aquesta funció.

 

En un navegador web, mai es carregarà cordova.js correctament, però si aconseguim crear una app, i executar-la en un dispoisitiu o navegador, sí que podem arribar al "OnDeviceReady".

 

 

 

 

 

 

3.- Config.xml: Els paràmetres d'una aplicació
 

Quan creem una aplicació, tant Amdroid com IOS, hem de definir certs paràmetres que la fan única:

 

  • id: Identificador de l'app (package name). Acostuma a ser alguna cosa del tipus "es.team.example" (pais.empresa.nomAplicacio)/li>
  • name: : Nom de l'app.
  • description: : breu descripció de l'app.
  • Autor: : Autor i web.
  • Permisos: : Quins permisos tindrà l'app sobre el dispositiu.
  • Preferències: : Orientació, instal·lació, etc..

 

Tots aquests paràmetres els podem gestionar amb l'arxiu config.xml que farem a constinuació a partir de l'arxiu config_PGBuild.xml. Farem els següents passos:

 

  • 1.- Edita l'arxiu config.xml amb un editor de textes i observa com és
  • 2.- Canvia els paràmetres que calgui segons la teva app. es proposa un exemple de com podria quedar:

 


		<?xml version="1.0" encoding="UTF-8"?>

		<!-- config.xml reference: https://build.phonegap.com/docs/config-xml -->
		<widget xmlns     = "http://www.w3.org/ns/widgets"
				xmlns:gap = "http://phonegap.com/ns/1.0"
				id        = "es.jornadeside.basicApp"
				version   = "1.0.0">

			<name>Recollida selectiva</name>

			<description>
				Aplicació que mostra els contenidors de recollida selectiva més propers a la teva ubicació
			</description>

			<author href="http://phonegap.com" email="support@phonegap.com">
				PhoneGap Team
			</author>

			<!--
				If you do not want any permissions to be added to your app, add the
				following tag to your config.xml; you will still have the INTERNET
				permission on your app, which PhoneGap requires.
			-->
			<preference name="permissions"                value="none"/>

			<!-- Customize your app and platform with the preference element. -->
			<preference name="orientation"                value="default" />        <!-- all: default means both landscape and portrait are enabled -->
			<preference name="target-device"              value="universal" />      <!-- all: possible values handset, tablet, or universal -->
			<preference name="fullscreen"                 value="false" />           <!-- all: hides the status bar at the top of the screen -->
			<preference name="webviewbounce"              value="true" />           <!-- ios: control whether the screen 'bounces' when scrolled beyond the top -->
			<preference name="prerendered-icon"           value="true" />           <!-- ios: if icon is prerendered, iOS will not apply it's gloss to the app's icon on the user's home screen -->
			<preference name="stay-in-webview"            value="false" />          <!-- ios: external links should open in the default browser, 'true' would use the webview the app lives in -->
			<preference name="ios-statusbarstyle"         value="black-opaque" />   <!-- ios: black-translucent will appear black because the PhoneGap webview doesn't go beneath the status bar -->
			<preference name="detect-data-types"          value="true" />           <!-- ios: controls whether data types (such as phone no. and dates) are automatically turned into links by the system -->
			<preference name="exit-on-suspend"            value="false" />          <!-- ios: if set to true, app will terminate when home button is pressed -->
			<preference name="show-splash-screen-spinner" value="true" />           <!-- ios: if set to false, the spinner won't appear on the splash screen during app loading -->
			<preference name="auto-hide-splash-screen"    value="true" />           <!-- ios: if set to false, the splash screen must be hidden using a JavaScript API -->
			<preference name="disable-cursor"             value="false" />          <!-- blackberry: prevents a mouse-icon/cursor from being displayed on the app -->
			<preference name="android-installLocation"    value="auto" />           <!-- android: app install location. 'auto' will choose. 'internalOnly' is device memory. 'preferExternal' is SDCard. -->
			<!--
				Define a specific version of PhoneGap to build into your app.
				<preference name="phonegap-version"       value="3.5.0" />
			-->

			<!-- Plugins -->

			<!-- Core plugins -->
			<!--
			<plugin name="cordova-plugin-battery-status" />
			<plugin name="cordova-plugin-camera" />
			<plugin name="cordova-plugin-media-capture" />
			<plugin name="cordova-plugin-console" />
			<plugin name="cordova-plugin-contacts" />
			<plugin name="cordova-plugin-device" />
			<plugin name="cordova-plugin-device-motion" />
			<plugin name="cordova-plugin-device-orientation" />
			<plugin name="cordova-plugin-dialogs" />
			<plugin name="cordova-plugin-file" />
			<plugin name="cordova-plugin-file-transfer" />
			<plugin name="cordova-plugin-globalization" />
			<plugin name="cordova-plugin-inappbrowser" />
			<plugin name="cordova-plugin-media" />
			<plugin name="cordova-plugin-network-information" />
			<plugin name="cordova-plugin-splashscreen" />
			<plugin name="cordova-plugin-vibration" />
			-->

			<plugin name="cordova-plugin-geolocation" spec="2.4.3" />
			
			<!-- Third party plugins -->
			<!-- A list of available plugins are available at https://build.phonegap.com/plugins -->
			<!--
				<plugin name="com.phonegap.plugins.barcodescanner" />
			-->

			<!-- Define app icon for each platform. -->
			<icon src="icon.png" />
			<icon src="res/icon/android/icon-36-ldpi.png"   gap:platform="android"    gap:qualifier="ldpi" />
			<icon src="res/icon/android/icon-48-mdpi.png"   gap:platform="android"    gap:qualifier="mdpi" />
			<icon src="res/icon/android/icon-72-hdpi.png"   gap:platform="android"    gap:qualifier="hdpi" />
			<icon src="res/icon/android/icon-96-xhdpi.png"  gap:platform="android"    gap:qualifier="xhdpi" />
			<icon src="res/icon/blackberry/icon-80.png"     gap:platform="blackberry" />
			<icon src="res/icon/blackberry/icon-80.png"     gap:platform="blackberry" gap:state="hover"/>
			<icon src="res/icon/ios/icon-57.png"            gap:platform="ios"        width="57" height="57" />
			<icon src="res/icon/ios/icon-72.png"            gap:platform="ios"        width="72" height="72" />
			<icon src="res/icon/ios/icon-57-2x.png"         gap:platform="ios"        width="114" height="114" />
			<icon src="res/icon/ios/icon-72-2x.png"         gap:platform="ios"        width="144" height="144" />
			<icon src="res/icon/webos/icon-64.png"          gap:platform="webos" />
			<icon src="res/icon/windows-phone/icon-48.png"  gap:platform="winphone" />
			<icon src="res/icon/windows-phone/icon-173.png" gap:platform="winphone"   gap:role="background" />

			<!-- Define app splash screen for each platform. -->
			<gap:splash src="res/screen/android/screen-ldpi-portrait.png"       gap:platform="android" gap:qualifier="port-ldpi" />
			<gap:splash src="res/screen/android/screen-mdpi-portrait.png"       gap:platform="android" gap:qualifier="port-mdpi" />
			<gap:splash src="res/screen/android/screen-hdpi-portrait.png"       gap:platform="android" gap:qualifier="port-hdpi" />
			<gap:splash src="res/screen/android/screen-xhdpi-portrait.png"      gap:platform="android" gap:qualifier="port-xhdpi" />
			<gap:splash src="res/screen/blackberry/screen-225.png"              gap:platform="blackberry" />
			<gap:splash src="res/screen/ios/screen-iphone-portrait.png"         gap:platform="ios"     width="320" height="480" />
			<gap:splash src="res/screen/ios/screen-iphone-portrait-2x.png"      gap:platform="ios"     width="640" height="960" />
			<gap:splash src="res/screen/ios/screen-iphone-portrait-568h-2x.png" gap:platform="ios"     width="640" height="1136" />
			<gap:splash src="res/screen/ios/screen-ipad-portrait.png"           gap:platform="ios"     width="768" height="1024" />
			<gap:splash src="res/screen/ios/screen-ipad-landscape.png"          gap:platform="ios"     width="1024" height="768" />
			<gap:splash src="res/screen/windows-phone/screen-portrait.jpg"      gap:platform="winphone" />

			<gap:config-file platform="ios" parent="CFBundleShortVersionString">
			<string>100</string>
			</gap:config-file>

			<!--
				Define access to external domains.

				<access />            - a blank access tag denies access to all external resources.
				<access origin="*" /> - a wildcard access tag allows access to all external resource.

				Otherwise, you can specify specific domains:

				<access origin="http://phonegap.com" />                    - allow any secure requests to http://phonegap.com/
				<access origin="http://phonegap.com" subdomains="true" />  - same as above, but including subdomains, such as http://build.phonegap.com/
				<access origin="http://phonegap.com" browserOnly="true" /> - only allows http://phonegap.com to be opened by the child browser.
			-->

			<access origin="*"/>
			<!-- Added the following intents to support the removal of whitelist code from base cordova to a plugin -->
			<!-- Whitelist configuration. Refer to https://cordova.apache.org/docs/en/edge/guide_appdev_whitelist_index.md.html -->
			<plugin name="cordova-plugin-whitelist" version="1" />
			<allow-intent href="http://*/*" />
			<allow-intent href="https://*/*" />
			<allow-intent href="tel:*" />
			<allow-intent href="sms:*" />
			<allow-intent href="mailto:*" />
			<allow-intent href="geo:*" />
			<platform name="android">
				<allow-intent href="market:*" />
			</platform>
			<platform name="ios">
				<allow-intent href="itms:*" />
				<allow-intent href="itms-apps:*" />
			</platform>

		</widget>





							

 

 

 

 

 

 

4.- Creant una app
 

Ara ja ho tenim tot a apunt per a convertir el nostre web en una app. Només caldrà segur els següents passos:

 

1.- Prepara un ZIP Crea un arxiu .ZIP de tota la carpeta www  

2.- Puja el zip a Phonegap Build Retorna al teu compte de Phonegap Build i apreta el botó Upload a zip file. Selecciona el zip que has creat i observa com s'ha creat una app:

3.- Apreta el botó Ready to build  

4.- Apreta el botó Rebuild all  

5.- Fes un click damunt el títol de l'app per a veure més detall

 

 

 

 

 

Ja tenim llesta l'app per a ser instal·lada!!

 

 

 

5.- Instal·lant una app
 

Per a instal·lar una app a un dispositiu mòbil, només ens cal alguna app que sigui capaç de llegir codis QR (QR Code Reader o similiar) i seguir els següents passos:

 

1.- Obre una aplicació QR des del dispositiu.  

2.- Apunta al codi QR que es mostra a la pantalla de Phonegap Build  

3.- Segueix els passos

 

 

 

 

 

 

 

 

Pot passar que el nostres dispositiu no ens permeti instal·lar aplicacions que no vinguin del Play Store o que no consideri segures. Per evitar això, cal indicar al dispositiu que ens permeti instal·lar aquestes aplicacions d'origen desconegut. Ves a "Configuració" --> "Seguretat" i marca les caselles tal com s'indica:

 

 

 

 

 

 

Un cop descarregada l'apk, només cal instal·lar-la. Fes un click damunt l'arxiu .apk que t'has descarregat i segueix els passos. Si tot va bé, s'instal·larà l'app i ara sí que apareixerà el missatge de que tot està llest que es dispara quan s'ha carregat Phonegap (líniea 43 de l'arxiu index.js):

 

 

 

 

 

Observa a més, com l'app queda instal·lada com qualsevol altra app:

 

 

 

 

 

 

6.- Adaptant el codi a partir de l'exercici de Leaflet
 

A continuació adaptarem l'actual codi amb el codi referent a l'exercici Leaflet, amb la incorporació de JQuery Mobile. Edita l'arxiu index.html i deixa'l tal com s'indica:

		<!DOCTYPE html>
		<html>
			<head>
				<meta charset="utf-8" />
				<meta http-equiv="Content-Security-Policy" content="default-src *; style-src * 'unsafe-inline'; script-src * 'unsafe-inline' 'unsafe-eval'; img-src * data: 'unsafe-inline'; connect-src * 'unsafe-inline'; frame-src *;" />
				<meta name="format-detection" content="telephone=no" />
				<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, target-densitydpi=medium-dpi" />

				<link rel="stylesheet"  href="libs/jQM-flat/jquery.mobile.flatui.css">
				<link rel="stylesheet" type="text/css" href="css/index.css" />
				
				<title>Recollida Selectiva</title>

				<script defer="defer" language="javascript">
				
					var mymap;
					var POI;
					var layerPOI;
					var layerGPS;
					var layerContenidors_PL;
					var layerContenidors_PA;
					var layerContenidors_VI;
					var mapLng = 4.149678;
					var mapLat = 39.9338723;		

					//Iniciem el mapa
					function initMap(){

						//Capes
						var layerOSM = L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
							maxZoom: 19,
							attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
						});

						var EsriLayer = L.tileLayer('http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
								attribution: '© <a href="http://www.esri.com/">Esri</a>',
								maxZoom: 19
						});   

						//Creem la capa de punts d'interès POI
						layerPOI = L.layerGroup();

						//Creem la capa de punts de contenidors
						layerContenidors_PL = L.layerGroup();
						layerContenidors_PA = L.layerGroup();
						layerContenidors_VI = L.layerGroup();

						//Creem la capa per la ubicació del GPS
						layerGPS = L.layerGroup();
						
						//Creem un mapa amb Leaflet que continguin la capa OSM i POI amb centre a les coordenades inicials
						mymap = L.map('mapDiv',{
							center: [mapLat, mapLng]
							, zoom: 15
							, layers: [layerOSM, layerPOI, layerGPS, layerContenidors_PL, layerContenidors_VI, layerContenidors_PA]
						});

						//Definim les capes base
						var baseLayers = {
							"Mapa": layerOSM
							 ,"Satèl·lit" : EsriLayer
						};

						//Definim les capes sobreposades
						var overlays = {
							"Punts interès": layerPOI
							, "Ubicació": layerGPS
							, "Paper": layerContenidors_PA
							, "Plàstic": layerContenidors_PL
							, "Vidre": layerContenidors_VI
						};

						//Afegim el control de capes al mapa
						L.control.layers(baseLayers, overlays).addTo(mymap);  
						
						//Afegim el marcador del Parc BIT
						addMarker(39.9338723, 4.149678, "IV Jornades d'Informació Geogràfica de Menorca","6 d'octubre - Centre Bit - Alaior",layerPOI, "");
					}

					//Funció genèrica per afegir marcadors
					function addMarker(lat, lon, _nom, _descripcio, _layer, icona){
						if (icona=="") icona = 'ICON_RED';
						var Icon = L.icon({
							iconUrl: 'img/icones/' + icona + '.svg',
							iconSize: [32, 32], // size of the icon
						}); 
						marker = L.marker([lat, lon], {icon:Icon}).bindPopup("<b>" + _nom + "</b><br />" + _descripcio).addTo(_layer);
					}
					
					//Adapta el contingut del mapa a cada mòbil
					function adaptaEstil()
					{
						document.getElementById('mapDiv').style.height = ((window.innerHeight) - 45) + 'px';    
						document.getElementById('mapDiv').style.width = ((window.innerWidth)) + 'px';    
					}			
				</script>

			</head>
			<body  id="body" style="background-color: transparent">
				<div id="app">
				  
					<!-- 
					===========================
					UBICACIO
					===========================
					-->
					<div id="pageMapa" data-role="page" data-theme="b">
						<div data-role="header" data-position="fixed" data-id="headerFixed" data-tap-toggle="false"  data-theme="a">
							<h1><div id="ubicacioTitol">Mapa</div></h1>
						</div>
						<div data-role="content" role="main" style="padding: 0px;" >
								<div style="padding:0px;">
									<center>
										<div id="mapDiv" style="width:100%;height:400px;">
										</div>
									</center>
								</div>            
						</div>
					</div>        
		  


					
				</div>       
				
				<!--Leaflet-->
				<link rel="stylesheet" href="libs/leaflet/leaflet.css"/>
				<script src="libs/leaflet/leaflet.js" ></script>

				<script type="text/javascript" src="libs/fastclick.min.js"></script>
				<script type="text/javascript" src="cordova.js"></script>
				<script type="text/javascript" src="libs/jquery-2.0.3.min.js"></script>
				<script type="text/javascript" src="libs/jQueryMobile/jquery.mobile-1.3.2.min.js"></script>
				<script type="text/javascript" src="js/index.js"></script>
				
				<script type="text/javascript">
					app.initialize();
					
					//Adaptem la mida del mapa quan girem el mòbil
					$(document).ready(function(){
						$(window).resize(function() {
							adaptaEstil()   
						});		
					})			
				</script>
			</body>
		</html>

						  
							
 

Edita l'arxiu index.js i fes que quan el dispositu estgui llest, cridi la funció initMap() tal com s'indica:

		var app = {
			SOME_CONSTANTS : false,  // some constant


			// Application Constructor
			initialize: function() {
				console.log("console log init");
				this.bindEvents();
				this.initFastClick();
			},
			// 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);
			},
			initFastClick : function() {
				window.addEventListener('load', function() {
					FastClick.attach(document.body);
				}, false);
			},
			// Phonegap is now ready...
			onDeviceReady: function() {
				alert("device ready, start making you custom calls!");
				// Start adding your code here....
				adaptaEstil();
				initMap();		
			}
		};

		function alertDismissed() {
			//alert("hola");
		}
	
 

Torna a comprimir la carpeta de treball, torna a penjar el codi a PhonegapBuild, torna a generar l'app i reinstal·la-la al dispositiu escanejant el codi QR. Aquest és l'aspecte que hauria de tenir:

 

 

 

 

 

7.- Afegint plugins
 

Phonegap dóna la possibilitat d'interactuar amb el maquinari del mòbil: Acceleròmetre, càmera, contactes, geolocalització, sistema d'arxiu, emmagatzematge (bases de dades SQLite).

 
 

 

 

 

 

 

Per a instal·lar un plugin, editarem l'arxiu config.xml i permetrem l'accés al plugin que vulguem. Per habilitar la geolocalització, deixarem descomentada la línea 68 de l'arxiu config.xml, tal com es mostra:

 
 


	<?xml version="1.0" encoding="UTF-8"?>

	<!-- config.xml reference: https://build.phonegap.com/docs/config-xml -->
	<widget xmlns     = "http://www.w3.org/ns/widgets"
			xmlns:gap = "http://phonegap.com/ns/1.0"
			id        = "es.jornadeside.basicApp"
			version   = "1.0.0">

		<name>Recollida selectiva</name>

		<description>
			Aplicació que mostra els contenidors de recollida selectiva més propers a la teva ubicació.
		</description>

		<author href="http://phonegap.com" email="support@phonegap.com">
			PhoneGap Team
		</author>

		<!--
			If you do not want any permissions to be added to your app, add the
			following tag to your config.xml; you will still have the INTERNET
			permission on your app, which PhoneGap requires.
		-->
		<preference name="permissions"                value="none"/>

		<!-- Customize your app and platform with the preference element. -->
		<preference name="orientation"                value="default" />        <!-- all: default means both landscape and portrait are enabled -->
		<preference name="target-device"              value="universal" />      <!-- all: possible values handset, tablet, or universal -->
		<preference name="fullscreen"                 value="false" />           <!-- all: hides the status bar at the top of the screen -->
		<preference name="webviewbounce"              value="true" />           <!-- ios: control whether the screen 'bounces' when scrolled beyond the top -->
		<preference name="prerendered-icon"           value="true" />           <!-- ios: if icon is prerendered, iOS will not apply it's gloss to the app's icon on the user's home screen -->
		<preference name="stay-in-webview"            value="false" />          <!-- ios: external links should open in the default browser, 'true' would use the webview the app lives in -->
		<preference name="ios-statusbarstyle"         value="black-opaque" />   <!-- ios: black-translucent will appear black because the PhoneGap webview doesn't go beneath the status bar -->
		<preference name="detect-data-types"          value="true" />           <!-- ios: controls whether data types (such as phone no. and dates) are automatically turned into links by the system -->
		<preference name="exit-on-suspend"            value="false" />          <!-- ios: if set to true, app will terminate when home button is pressed -->
		<preference name="show-splash-screen-spinner" value="true" />           <!-- ios: if set to false, the spinner won't appear on the splash screen during app loading -->
		<preference name="auto-hide-splash-screen"    value="true" />           <!-- ios: if set to false, the splash screen must be hidden using a JavaScript API -->
		<preference name="disable-cursor"             value="false" />          <!-- blackberry: prevents a mouse-icon/cursor from being displayed on the app -->
		<preference name="android-installLocation"    value="auto" />           <!-- android: app install location. 'auto' will choose. 'internalOnly' is device memory. 'preferExternal' is SDCard. -->
		<!--
			Define a specific version of PhoneGap to build into your app.
			<preference name="phonegap-version"       value="3.5.0" />
		-->

		<!-- Plugins -->

		<!-- Core plugins -->
		<!--
		<plugin name="cordova-plugin-battery-status" />
		<plugin name="cordova-plugin-camera" />
		<plugin name="cordova-plugin-media-capture" />
		<plugin name="cordova-plugin-console" />
		<plugin name="cordova-plugin-contacts" />
		<plugin name="cordova-plugin-device" />
		<plugin name="cordova-plugin-device-motion" />
		<plugin name="cordova-plugin-device-orientation" />
		<plugin name="cordova-plugin-dialogs" />
		<plugin name="cordova-plugin-file" />
		<plugin name="cordova-plugin-file-transfer" />
		<plugin name="cordova-plugin-globalization" />
		<plugin name="cordova-plugin-inappbrowser" />
		<plugin name="cordova-plugin-media" />
		<plugin name="cordova-plugin-network-information" />
		<plugin name="cordova-plugin-splashscreen" />
		<plugin name="cordova-plugin-vibration" />
		-->

		<plugin name="cordova-plugin-geolocation" spec="2.4.3" />		
		
		<!-- Third party plugins -->
		<!-- A list of available plugins are available at https://build.phonegap.com/plugins -->
		<!--
			<plugin name="com.phonegap.plugins.barcodescanner" />
		-->

		<!-- Define app icon for each platform. -->
		<icon src="icon.png" />
		<icon src="res/icon/android/icon-36-ldpi.png"   gap:platform="android"    gap:qualifier="ldpi" />
		<icon src="res/icon/android/icon-48-mdpi.png"   gap:platform="android"    gap:qualifier="mdpi" />
		<icon src="res/icon/android/icon-72-hdpi.png"   gap:platform="android"    gap:qualifier="hdpi" />
		<icon src="res/icon/android/icon-96-xhdpi.png"  gap:platform="android"    gap:qualifier="xhdpi" />
		<icon src="res/icon/blackberry/icon-80.png"     gap:platform="blackberry" />
		<icon src="res/icon/blackberry/icon-80.png"     gap:platform="blackberry" gap:state="hover"/>
		<icon src="res/icon/ios/icon-57.png"            gap:platform="ios"        width="57" height="57" />
		<icon src="res/icon/ios/icon-72.png"            gap:platform="ios"        width="72" height="72" />
		<icon src="res/icon/ios/icon-57-2x.png"         gap:platform="ios"        width="114" height="114" />
		<icon src="res/icon/ios/icon-72-2x.png"         gap:platform="ios"        width="144" height="144" />
		<icon src="res/icon/webos/icon-64.png"          gap:platform="webos" />
		<icon src="res/icon/windows-phone/icon-48.png"  gap:platform="winphone" />
		<icon src="res/icon/windows-phone/icon-173.png" gap:platform="winphone"   gap:role="background" />

		<!-- Define app splash screen for each platform. -->
		<gap:splash src="res/screen/android/screen-ldpi-portrait.png"       gap:platform="android" gap:qualifier="port-ldpi" />
		<gap:splash src="res/screen/android/screen-mdpi-portrait.png"       gap:platform="android" gap:qualifier="port-mdpi" />
		<gap:splash src="res/screen/android/screen-hdpi-portrait.png"       gap:platform="android" gap:qualifier="port-hdpi" />
		<gap:splash src="res/screen/android/screen-xhdpi-portrait.png"      gap:platform="android" gap:qualifier="port-xhdpi" />
		<gap:splash src="res/screen/blackberry/screen-225.png"              gap:platform="blackberry" />
		<gap:splash src="res/screen/ios/screen-iphone-portrait.png"         gap:platform="ios"     width="320" height="480" />
		<gap:splash src="res/screen/ios/screen-iphone-portrait-2x.png"      gap:platform="ios"     width="640" height="960" />
		<gap:splash src="res/screen/ios/screen-iphone-portrait-568h-2x.png" gap:platform="ios"     width="640" height="1136" />
		<gap:splash src="res/screen/ios/screen-ipad-portrait.png"           gap:platform="ios"     width="768" height="1024" />
		<gap:splash src="res/screen/ios/screen-ipad-landscape.png"          gap:platform="ios"     width="1024" height="768" />
		<gap:splash src="res/screen/windows-phone/screen-portrait.jpg"      gap:platform="winphone" />

		<gap:config-file platform="ios" parent="CFBundleShortVersionString">
		<string>100</string>
		</gap:config-file>

		<!--
			Define access to external domains.

			<access />            - a blank access tag denies access to all external resources.
			<access origin="*" /> - a wildcard access tag allows access to all external resource.

			Otherwise, you can specify specific domains:

			<access origin="http://phonegap.com" />                    - allow any secure requests to http://phonegap.com/
			<access origin="http://phonegap.com" subdomains="true" />  - same as above, but including subdomains, such as http://build.phonegap.com/
			<access origin="http://phonegap.com" browserOnly="true" /> - only allows http://phonegap.com to be opened by the child browser.
		-->

		<access origin="*"/>
		<!-- Added the following intents to support the removal of whitelist code from base cordova to a plugin -->
		<!-- Whitelist configuration. Refer to https://cordova.apache.org/docs/en/edge/guide_appdev_whitelist_index.md.html -->
		<plugin name="cordova-plugin-whitelist" version="1" />
		<allow-intent href="http://*/*" />
		<allow-intent href="https://*/*" />
		<allow-intent href="tel:*" />
		<allow-intent href="sms:*" />
		<allow-intent href="mailto:*" />
		<allow-intent href="geo:*" />
		<platform name="android">
			<allow-intent href="market:*" />
		</platform>
		<platform name="ios">
			<allow-intent href="itms:*" />
			<allow-intent href="itms-apps:*" />
		</platform>

	</widget>


						  
							
 

Intentarem ser ordenats i crearem arxius .js segons la seva funció. Així:

 

  1. Crearem un arxiu "js/location.js" on hi posarem tot el codi refernt a la localització
  2. Vincularem l'arxiu creat a la pàgina index.html
  3. Iniciarem les funcions que calguin sempre després que el dispoistiu estigui llest (OnDeviceReady)
 

 

 

 

Crea l'arxiu "js/location.js" i afegeix-hi el següent codi:

 

 
 

			var watchID = null;
			var currentLat=null;
			var currentLon=null;
			var GPSresponse=false;

			function initGeolocation()
			{
				var optionsGeolocation={ frequency: 10000, enableHighAccuracy: true, timeout: 20000};
				if (watchID == null) watchID = navigator.geolocation.watchPosition(onSuccessGeolocation, onErrorGeolocation, optionsGeolocation);	
			}

			var onSuccessGeolocation = function(position) {
				GPSresponse=true;
				currentLat = position.coords.latitude;
				currentLon = position.coords.longitude;
				locateMobile();
			};


			function onErrorGeolocation(error) {
				if (GPSresponse==false){
					alert("Error en accedir al GPS");    
				}
				GPSresponse=true;
			}

			function locateMobile(){
				var GpsIcon = L.icon({
					iconUrl: 'img/target.png',
					iconSize: [32, 32], // size of the icon
				});    
				layerGPS.clearLayers()
				GPS = L.marker([currentLat, currentLon], {icon:GpsIcon}).bindPopup("Ubicació actual
Lat: " + currentLat + "
Lon:" + currentLon).addTo(layerGPS); }
fes una referència a l'arxiu creat al final de de l'index.html:

 

 
 

		<script type="text/javascript" src="js/location.js"></script>
	
Inciarem la funció initGeolocation() quan el dispositiu estigui llest. Edita l'arxiu js/index.js:

 

 
 

		 onDeviceReady: function() {
				//alert("device ready, start making you custom calls!");
				// Start adding your code here....
				adaptaEstil();
				initMap();
				initGeolocation();
		}
	
 

Torna a comprimir la carpeta de treball, torna a penjar el codi a PhonegapBuild, torna a generar l'app i reinstal·la-la al dispositiu escanejant el codi QR. Aquest és l'aspecte que hauria de tenir:

 

 

 

 

 

 

7.- WebServices: Obtinguent dades de la IDE
 

La IDE menorca ofereix serveis de dades que retornen informació geogràfica en format JSON, és a dir, dades en format de texte que es poden editar i manipular per a ser tractades dins una aplicació client. És el que s'anomena serveis web. Podeu trobar més informació sobre la API de de dades de menorca en aquest enllaç

 

 

Per exemple, podríem obtenir els contenidors de recollida de paper, plàstic, vidre, oli, roba i rebuig que es trobin en un radi d'acció de 50 metres de la porta del IES Ramis, a partir de la següent url:

 

	http://ide.cime.es/api20/aprop.aspx?tipus=infraestructures-equipaments&categoria=RESIDUS&cerca=&radiaccio=50&posX=607298&posY=4416023&srs=25831
	

 

 

I el resultat serà un JSON amb la informació resultant:

 

		{
			resposta: {
				status: "ok",
				totalEncerts: "3",
				boundingBox: {
					min: {
					x: "607308",
					y: "4416045"
					},
					max: {
					x: "607309",
					y: "4416052"
					}
				},
				encerts: [
					{
						encert: {
							tipus: "CONTENIDOR_PL",
							gid: "833",
							municipi: "07032",
							location: {
								x: "607308",
								y: "4416052",
								dist: "30,6757233003559"
							}
						}
					},
					{
						encert: {
							tipus: "CONTENIDOR_PA",
							gid: "908",
							municipi: "07032",
							location: {
								x: "607309",
								y: "4416045",
								dist: "24,5967477524977"
							}
						}
					},
					{
						encert: {
							tipus: "CONTENIDOR_VI",
							gid: "983",
							municipi: "07032",
							location: {
								x: "607308",
								y: "4416048",
								dist: "26,9258240356725"
							}
						}
					}
				]
			}
		}
	

 

 

Emprarem aquest servei de la IDE menorca, consultarem els contenidors més propers a la nostra ubicació i cada resultat que ens torni, l'afegirem al mapa com un marcador. Crea l'arxiu :

 

Intentarem ser ordenats i crearem arxius .js segons la seva funció. Així:

 

  1. Crearem un arxiu "js/wsJson.js" on hi posarem tot el codi refernt a la crida de webServices
  2. Vincularem l'arxiu creat a la pàgina index.html
  3. Iniciarem les funcions que calguin sempre després que el dispoistiu estigui llest (OnDeviceReady)
 

 

 

 

Crea l'arxiu "js/wsJson.js" i afegeix-hi el següent codi:

 

 
 

		var matRecycle;

		function findRecycle(){


			//Esborrem les capes de contenidors
			layerContenidors_PL.clearLayers();
			layerContenidors_PA.clearLayers();
			layerContenidors_VI.clearLayers();
			
			//Fem una petició a la API de dades de la IDE menorca amb la nostra posició i un radi de 500 metres
			var url = "http://ide.cime.es/api20/aprop.aspx?tipus=infraestructures-equipaments&categoria=residus&cerca=&radiaccio=500&posX=" + currentLon + "&posY=" + currentLat + "&srs=4326";
			$.ajax({
				type: "GET",
				url: url
			}).done(function (data) {
				//Creem una nova matriu de resultats, de moment buïda
				matRecycle = new Array();			
			
				var contenidors = JSON.parse(data);
				//Per a cada contenidor, l'afegim a la matriu de resultats i creem un marcador diferent segons si és plàstic, paper o vidre a la capa corresponent
				for (var i=0; i< contenidors.resposta.encerts.length;i++)
				{
					matRecycle[i] = {idCont: contenidors.resposta.encerts[i].encert.gid, tipus: contenidors.resposta.encerts[i].encert.tipus, lon: contenidors.resposta.encerts[i].encert.location.x, lat: contenidors.resposta.encerts[i].encert.location.y, dist: contenidors.resposta.encerts[i].encert.location.dist}
					if (matRecycle[i].tipus=='CONTENIDOR_PL') addMarker(matRecycle[i].lat, matRecycle[i].lon, "CONTENIDOR_PL: " + matRecycle[i].idCont,"
Distància: " + matRecycle[i].dist,layerContenidors_PL, matRecycle[i].tipus); if (matRecycle[i].tipus=='CONTENIDOR_PA') addMarker(matRecycle[i].lat, matRecycle[i].lon, "CONTENIDOR_PA: " + matRecycle[i].idCont,"
Distància: " + matRecycle[i].dist,layerContenidors_PA, matRecycle[i].tipus); if (matRecycle[i].tipus=='CONTENIDOR_VI') addMarker(matRecycle[i].lat, matRecycle[i].lon, "CONTENIDOR_VI: " + matRecycle[i].idCont,"
Distància: " + matRecycle[i].dist,layerContenidors_VI, matRecycle[i].tipus); } }); }
fes una referència a l'arxiu creat al final de de l'index.html:

 

 
 

		<script type="text/javascript" src="js/wsJson.js"></script>
	
Inciarem la funció findRecycle() quan el dispositiu tingui resposta del GPS i trobi la seva ubicació. Edita l'arxiu js/location.js i modifica la funció onSuccessLocation:  

		var onSuccessGeolocation = function(position) {
			GPSresponse=true;
			currentLat = position.coords.latitude;
			currentLon = position.coords.longitude;
			locateMobile();
			if (matRecycle==null) findRecycle();
		};	
	
 

Torna a comprimir la carpeta de treball, torna a penjar el codi a PhonegapBuild, torna a generar l'app i reinstal·la-la al dispositiu escanejant el codi QR. Aquest és l'aspecte que hauria de tenir:

 

 

 

 

Finalment, podem afegir un botó a la barra del títol per a cridar de nou la API de dades, per exemple en el cas que ens haguem desplaçat. Només caldrà deixar el codi de la pàgina principal (index.html) de la següent manera:  

            <!-- 
            ===========================
            UBICACIO
            ===========================
            -->
            <div id="pageMapa" data-role="page" data-theme="b">
                <div data-role="header" data-position="fixed" data-id="headerFixed" data-tap-toggle="false"  data-theme="a">
                    <h1><div id="ubicacioTitol">Mapa</div></h1>
                    <a href="#" id="btnReload" class="ui-btn-right" data-icon="refresh" data-iconpos="right" onclick="findRecycle()">Reload</a>
                </div>
                <div data-role="content" role="main" style="padding: 0px;" >
                        <div style="padding:0px;">
                            <center>
                                <div id="mapDiv" style="width:100%;height:400px;">
                                </div>
                            </center>
                        </div>            
                </div>
            </div>   	
	
 

Torna a comprimir la carpeta de treball, torna a penjar el codi a PhonegapBuild, torna a generar l'app i reinstal·la-la al dispositiu escanejant el codi QR.

 

 

 

 

8.- AR: Realitat augmentada
 

La realitat augmentada (RA) és el terme per a definir una visió directa o indirecta d'un entorn físic en el món real, els elements del qual es combinen amb elements virtuals per a la creació d'una realitat mixta a temps real.

 

Consisteix en un conjunt de dispositius que afegeixen informació virtual a la informació física ja existent. Aquesta és la principal diferència amb la realitat virtual, ja que no substitueix la realitat física, sinó que afegeix un entorn fictici (per exemple, dades informàtiques) al món real. Amb l'ajuda de la tecnologia (per exemple, afegint la visió per ordinador i el reconeixement d'objectes) la informació del món real que envolta l'usuari es converteix en interactiva i manipulable. La informació digital sobre l'entorn i els objectes pot ser superposada al món real. A tall d'exemple, podem entrar dins d’un llibre i formar part de la història que ens explica; també podem visualitzar imatges que prenen vida o entorns canviants.

 

 

 

 

És un terreny relativament nou, on hi ha molt poques empreses que ofereixin Plugins o entorns SDK. A més, les poques que hi ha, tenen preus molt elevats (Wikitude, cratAR - catchoom)

 

 

Menys mal que hi emprenedors que sempre apsyten pel Software lliure. Un exemple és EzarTech, que ofereix plugins de realitat augmentada per a Phonegap de forma gratuïta. No són tant potents com els d'empreses privades, però suficients per a mostrar damunt la nostra càmara la distància als contenidors més propers

 

 

Per a fer-ho, seguirem els següenrts passos:

 

 

1.- Afegir nous plugins a l'app: la brúixula

 

Per habilitar la brúixula del nostre dispositiu, caldrà afegir la següent línia al nostre arxiu config.xml, just després d'especificar el plugin de locatizació (línia 68):


		...
		<plugin name="cordova-plugin-geolocation" spec="2.4.3" />		
		<plugin name="cordova-plugin-device-orientation" />
		...
	
 

Intentarem ser ordenats i crearem arxius .js segons la seva funció. Així:

 

  1. Crearem un arxiu "js/compass.js" on hi posarem tot el codi refernt a la brúixula
  2. Vincularem l'arxiu creat a la pàgina index.html
  3. Iniciarem les funcions que calguin sempre després que el dispoistiu estigui llest (OnDeviceReady)
 

 

 

 

Crea l'arxiu "js/compass.js" i afegeix-hi el següent codi:

 

 
 

		// Start watching the compass
		function startCompass() {
			var options = { frequency: 100 };
			watchCompassID = navigator.compass.watchHeading(onCompassSuccess, onCompassError, options);
		}
		// Stop watching the compass
		function stopCompass() {
			if (watchCompassID) {
				navigator.compass.clearWatch(watchCompassID);
				watchCompassID = null;
			}
		}
		// onSuccess: Get the current heading
		function onCompassSuccess(heading) {
			var directions = ['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW', 'N'];
			var direction = directions[Math.abs(parseInt((heading.magneticHeading) / 45) + 1)];
			//document.getElementById('compass').innerHTML = heading.magneticHeading + "
" + direction; document.getElementById('direction').innerHTML = parseInt(heading.magneticHeading).toFixed(0) + ' ' + direction; var degree = heading.magneticHeading; if ($.mobile.activePage.is('#pageAR')){ calculateDirection(degree); } } // onError: Failed to get the heading function onCompassError(compassError) { document.getElementById('log').innerHTML += "onError=."+compassError.code; }
fes una referència a l'arxiu creat al final de de l'index.html:

 

 
 

		<script type="text/javascript" src="js/compass.js"></script>
	
Inciarem la funció initGeolocation() quan el dispositiu estigui llest. Edita l'arxiu js/index.js:

 

 
 

		 onDeviceReady: function() {
				//alert("device ready, start making you custom calls!");
				// Start adding your code here....
				adaptaEstil();
				initMap();
				initGeolocation();
				startCompass();
		}
	

 

 

El compass llegirà l'orientació i intentarà posar el seu valor a un contenidor anomenat "direction". Per tant, crearem una nova pàgina a l'aplicació per a vincular tot l'entorn AR. Afegeix aquest tros de codi a la pàgina index.html, just després de la pàgina "pageMapa":

 

 
 


			<!-- 
            ===========================
            AR
            ===========================
            -->
            <div id="pageAR" data-role="page" data-theme="b" style="background-color: transparent">
                <div data-role="header" data-position="fixed" data-id="headerFixed" data-tap-toggle="false"  data-theme="a">
                    <a href="#" id="btnBackAR" class="ui-btn-left" data-icon="arrow-l" data-iconpos="left">Tornar</a>
                    <h1><div id="resultatTitol">AR</div></h1>
                </div>
                <div data-role="content" role="main" style="padding: 0px;">
		        <div id="arView" style="background-color: transparent">
		            <div class="arMessage">↑<br>Tilt down to see all places</div>
		            <br>
		            <div class="arMessage">← Move the device around to find spots →</div>
		            <br>
		            <div id="direction"></div>
		            <div id="compass"></div>
		            <br>
		            <div id="spot"></div>
		        </div>                    
                </div>
            </div> 	
	
	

 

 

I afegirem el següent codi d'estils al final l'arxiu css/index.css:

 

 
 


            body {background-color:transparent;font-family:Arial;margin:0;overflow-x:hidden;-webkit-user-select: none;}
            #arView, {display:none;}
            #pageAR{padding:30px 0; height:70px;text-align:center}
            .arMessage {color:#ddd;font-size:14px}
            #spot {text-align:center}
            .name, .distance {text-shadow:0 1px #666}
            .name {padding:15px;font-weight:bold;background-color:rgba(204,34,34,0.5);border-radius:40px;margin-bottom:10px}
            #direction {color:#fff;font-size:20px;padding:15px;font-weight:bold;background-color:#a22;border-radius:40px;display:inline-block;margin-bottom:10px;width:40px;line-height:40px}
            .distance {font-size:14px;font-weight:normal;}
            #debug {border:1px solid #999;display:none}
            .heading {background-color:#999;color:#eee;padding:5px;}
            #compass, #accelerometer, #geolocation {padding:5px}
			
	

 

 

 

2.- Afegir nous plugins externs a l'app: Video Overlay

 

Hi ha infinitat de plugins desenvolupats per tercers que incorporen noves funcionalitats a Phonegap. Per a cercar-ne un, només cal buscar-lo a través de la caixa de cerca de plugins de Phonegap. Per exemple, si volem incorporar un plugin per a tractar missatges de twiter:

 

 

 

 

Tots aquests plugins sempre ens acaben portant a un repositori de github on hi ha el codi font del plugin. Nomes cal que sapoguem la url d'aquest repositori per a integrar el plugin a la nostra app. El repositori on hi ha el plugin de AR d'EzarTech és:

https://github.com/marcroses/ar.git

 

Per a incloure el plugin, caldrà afegir la següent línia al nostre arxiu config.xml, just després d'especificar el plugin de compass (línia 69):


		...
		<plugin name="cordova-plugin-geolocation" spec="2.4.3" />		
		<plugin name="cordova-plugin-device-motion" />
		<plugin spec="https://github.com/marcroses/ar.git" source="git"/>
		...
	
 

Intentarem ser ordenats i crearem arxius .js segons la seva funció. Així:

 

  1. Crearem un arxiu "js/ar.js" on hi posarem tot el codi refernt a la realitat augmentada
  2. Vincularem l'arxiu creat a la pàgina index.html
  3. Iniciarem les funcions que calguin sempre després que el dispoistiu estigui llest (OnDeviceReady)
 

 

Crea l'arxiu "js/ar.js" i afegeix-hi el següent codi:

 

			var bearing, distance;
			var dataStatus = 0; 

			function startCamera() {
				ezar.initializeVideoOverlay(
					function() {
						ezar.getBackCamera().start();
					},
					function(error) {
						alert("ezar initialization failed");
					});
			} 

			function stopCamera() {
				ezar.getBackCamera().stop();
			} 

			function colorSpot(tipus)
			{
				var spotColor = '(204,34,34,0.5)';
				switch (tipus) {
					case 'CONTENIDOR_PL':
						spotColor = '(128,0,56,0.5)';
						break; 
					case 'CONTENIDOR_PA':
						spotColor = '(71,33,246,0.5)';
						break; 
					case 'CONTENIDOR_VI':
						spotColor = '(116,207,75,0.5)';
						break; 

					default: 
						spotColor = '(204,34,34,0.5)';
				}
				return spotColor;
			}


			// calulate distance and bearing value for each of the points wrt gps lat/lng        
			function relativePosition() {

				for (var i=0; i<matRecycle.length; i++)
				{    
					var dLat = (currentLat-matRecycle[i].lat)* Math.PI / 180;
					var dLon = (currentLon-matRecycle[i].lon)* Math.PI / 180;
					var lat1 = matRecycle[i].lat * Math.PI / 180;
					var lat2 = currentLat * Math.PI / 180;
					var y = Math.sin(dLon) * Math.cos(lat2);
					var x = Math.cos(lat1)*Math.sin(lat2) - Math.sin(lat1)*Math.cos(lat2)*Math.cos(dLon);
					bearing = Math.atan2(y, x) * 180 / Math.PI;
					bearing = bearing + 180;
					matRecycle[i].bearing = bearing;

					var a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2); 
					var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
					distance = 3958.76  * c;
					distance = (distance / 1.609344)*1000
					matRecycle[i].distance = distance;        
				}

			}


			// calculate direction of points and display        
			function calculateDirection(degree){
				var detected = 0;
				$("#spot").html("");
				for(var i=0;i<matRecycle.length;i++){
					if(Math.abs(matRecycle[i].bearing - degree) <= 20){
						var away, fontSize, fontColor;
						// varry font size based on distance from gps location
						if(matRecycle[i].distance<150){
							if(matRecycle[i].distance<20){
								away = Math.round(matRecycle[i].distance);
								fontSize = "30";
								fontColor = "#ccc";
							} else if(matRecycle[i].distance<50){
								away = Math.round(matRecycle[i].distance);
								fontSize = "24";
								fontColor = "#ddd";
							} else {
								away = matRecycle[i].distance.toFixed(2);
								fontSize = "16";
								fontColor = "#eee";
							}

							var colorDiv = colorSpot(matRecycle[i].tipus)
							$("#spot").append('
'+matRecycle[i].tipus + ': ' + matRecycle[i].idCont+'
'+ away +' m.
'); detected = 1; } } else { if(!detected){ $("#spot").html(""); } } } }
fes una referència a l'arxiu creat al final de de l'index.html:

 

 
 

		<script type="text/javascript" src="js/ar.js"></script>
	

 

Crea l'arxiu "js/events.js" i afegeix-hi el següent codi:

 

		var currentPage="";


		//==================
		//PAGE UBICACIO
		//==================
		$(document).on ('pageshow', '#pageMapa', function (event) {
			currentPage = "pageMapa";
			document.getElementById('body').style.background = "#fff";
		});



		//==================
		//PAGE pageAR
		//==================
		$(document).on ('pagecreate', '#pageAR', function (event) {
			$("#btnBackAR").bind('click', function(event, ui){
				stopCamera();
				$.mobile.changePage("#pageMapa");
			});  
		});
		$(document).on ('pageshow', '#pageAR', function (event) {
			relativePosition();
			startCamera();
			currentPage = "pageAR";
			document.getElementById('body').style.background = "transparent";
		});
						
		
fes una referència a l'arxiu creat al final de de l'index.html:

 

 
 

		<script type="text/javascript" src="js/events.js"></script>
	
Finalment, podem afegir un botó a la barra del títol per a cridar la pàgina AR. Només caldrà deixar el codi de la pàgina principal (index.html) de la següent manera:  

            <!-- 
            ===========================
            UBICACIO
            ===========================
            -->
            <div id="pageMapa" data-role="page" data-theme="b">
                <div data-role="header" data-position="fixed" data-id="headerFixed" data-tap-toggle="false"  data-theme="a">
					<a href="#pageAR" class="ui-btn-left" data-icon="arrow-l" data-iconpos="left">AR</a>
                    <h1><div id="ubicacioTitol">Mapa</div></h1>
                    <a href="#" id="btnReload" class="ui-btn-right" data-icon="refresh" data-iconpos="right" onclick="findRecycle()">Reload</a>
                </div>
                <div data-role="content" role="main" style="padding: 0px;" >
                        <div style="padding:0px;">
                            <center>
                                <div id="mapDiv" style="width:100%;height:400px;">
                                </div>
                            </center>
                        </div>            
                </div>
            </div>   	
	
 

Torna a comprimir la carpeta de treball, torna a penjar el codi a PhonegapBuild, torna a generar l'app i reinstal·la-la al dispositiu escanejant el codi QR.