Apache Cordova

Es un conjunto de librerías que permite empaquetar aplicaciones HTML5 de manera que puedan ser usadas como apps para móviles. También nos permite acceder a servicios nativos del móvil a través de Javascript.

Server: irc.freenode.net
Channel: #phonegap

Phonegap Build

Permite compilar en la nube. De esta forma no será necesario instalar los SDK de los sistemas para los que queremos compilar. Por otra parte, para compilar una aplicación para IOS es necesario un ordenador MAC. Esto lo podremos salvar utilizando PhoneGap Build.
https://build.phonegap.com/

Una vez registrados, la opción
upload an archive or index.html file
Nos permite subir tanto un archivo .zip como un archivo .html

Luego podremos instalar la aplicación en el móvil escaneando su código de barras la aplicación de Android barcode scanner o bien descargar el apk.

Consideraciones a tener en cuenta antes de subir la app a PhoneGap Build

Habrá que eliminar el fichero phonegap.js del proyecto. Hacemos esto porque phonegapbuild requiere una librería diferente por cada plataforma y poner nosotros una librería concreta ocasionaría problemas al ejecutar la aplicación.

Para cargar la librería que phonegapbuild colocará utilizaremos la siguiente línea:

<script src="phonegap.js"></script>

Notas:

En las últimas versiones de Phonegap Build la compilación para BlackBerry, Web OS y Symbian no funciona.

Plugin Ripple para emular nuestra aplicación en el navegador

Simulador de aplicaciones móviles. Sirve tanto para aplicaciones web para móviles como para phonegap.

Podemos instalarlo desde la chrome store.

Tras la instalación, aparecerá el logo de Ripple a la derecha de la url de direcciones del navegador.

Para probar nuestra aplicación basta con acceder a la url de la misma y habilitar ripple (en lo sucesivo quedará habilitado para esta url).

Ya que estamos trabajando con la última versión de phonegap, esta será la que habrá que establecer por defecto en Ripple.

Por seguridad chrome no permite que los plugins (Ripple) accedan al sistema de archivos local. Por tanto, para poder testear nuestra aplicación necesitaremos que esté subida a un servidor, aunque sea local.

Si no funcionase Ripple (al pulsar en enable no hace nada), podemos pulsar en preferencias → herramientas → extensiones → Allow access to file URLs

Instalación de Apache Cordova

npm install -g cordova

Crear una nueva aplicación

$  sudo su 
$ cordova create my-app com.pablomonteserin.myapp #Es conveniente indicar un nombre de paquete o de lo contrario, cuando compilemos para subir a la tienda correspondiente se nos indicará que ese paquete ya estaba en uso
$ cd my-app
$ cordova platform add android

Cómo compilar una aplicación con Apache Cordova

Compilar sin firma

Debug

sudo cordova build android

Ejecutado desde la raíz de nuestro proyecto cordova, mueve el contenido de la carpeta www a las carpetas de las plataformas que hayamos añadido a nuestro proyecto.

Release

cordova build --release android
  • Necesitaremos tener la licencia que estamos usando del SDK de Android aceptada. Para aceptarlas todas:/[ruta-del-sdk-de-Android]/tools/bin/sdkmanager --licenses

Generar una firma (keystore)

Si estamos usando el Android Studio, podemos generar una firma o vincular nuestro proyecto a una firma ya existente desde el menú Build -> Generate Signed APK

Compilar con firma

cordova build --release android

Debemos crear un fichero en la raíz de nuestro proyecto Cordova:

build.json{
	"android": {
    	"debug": {
    	    "keystore": "..\mykeystore\CordovaDebug.keystore",
    	    "storePassword": "secretpassword",
    	    "alias": "CordovaDebug",
			"password" : "secretpassword",
			"keystoreType": ""
    	},
    	"release": {
			"keystore": "..\mykeystore\CordovaRelease.keystore",
			"storePassword": "",
			"alias": "CordovaRelease",
			"password" : "secretpassword",
			"keystoreType": ""
    	}
	}
}

Recomendaciones para compilar con Cordova

  • En linux y mac, lugar de ejecutar los comandos con ‘sudo’ delante, te recomiendo mucho loguearte directamente como super asministrador:sudo su
  • Debemos tener Java 8 instalado, no sirve una versión superior
  • Debemos tener las variables de entorno ANDROID_HOME y JAVA_HOME exportadas. Si ejecutamos este código desde la consola (con las rutas correctas) en linux y Mac las variables estarán exportadas hasta que cerremos la consola:En Linux:export ANDROID_HOME=/home/monty/Android/Sdk export PATH=${PATH}:$ANDROID_HOME/tools:$ANDROID_HOME/platform-tools export JAVA_HOME=/usr/lib/jvm/java-8-oracle/
  • spawn EACCES: Este es un problema de permisos en mac y Linux. Lo solucionamos así:sudo chmod -R a+rwx carpeta-de-la-aplicacion/

Compilación con Android Studio

Abriremos la carpeta platforms/android desde el Android Studio y compilaremos desde aquí

Arrancar el emulador desde Cordova

Ejecutaremos el siguiente comando:

cordova emulate android

Consideraciones (lo siguiente, es más cómodo gestionarlo desde el propio Android Studio):

  • Tras ejecutar este comando, en las primeras trazas de la consola, se nos indica la versión de Android para la que estamos compilando. Debemos tener esa versión de Android añadida con el Android Virtual Device Manager.
  • Debemos tener arrancado ya el emulador.

Fichero config.xml de una aplicación de Cordova

Versionado

Modificaré el atributo version del nodo widget del fichero config.xml situado en la raíz de nuestro proyecto cordova. Esto modificará automáticamente atributo opcional android-versionCode del mismo nodo, que es el que a su vez modificará el atributo android:versionCode del AndroidManifest.xml generado.

Aplicación horizontal y a pantalla completa

	<preference name="Orientation" value="landscape" />
	<preference name="Fullscreen" value="true" />
</widget>

Posibles errores al subir la aplicación a google play (https://play.google.com/apps/publish) utilizando el apk generado por phonegap build

You need to use a different package name because «com.phonegap.www» already exists in Google Play.
→ habrá que definir un paquete para la aplicación:

  • Si estamos usando phonegap build online: phonegapbuild page → settings → configuration
  • Si estamos usando cordova en nuestro equipo: config.xml en la raíz de nuestro proyecto

You uploaded an APK that was signed in debug mode. You need to sign your APK in release mode.
Habrá que firmar la aplicación.

Hola mundo – Phonegap

<doctype html>
<html>
	<head>
		<meta charset="UTF-8">
		<!-- la siguiente línea evita que los números de teléfono se conviertan en links clickables-->
		<meta name="format-detection" content="telephone-no">
		<!-- la siguiente línea evita que el usuario pueda hacer zoom sobre la aplicación, como ocurre con una página web, -->
		<meta name="viewport" content="user-scalable=no, initial-scale=1, minimum-scale=1, maximum-scale=1, width=device-width, height=device-height, target-densitydpi=device-dpi">
		<title>Mi aplicación</title>
		<link rel="stylesheet" href="css/estilos.css">
		<script src="cordova-2.5.0.js"></script>
		<script>
			document.addEventListener("deviceready", onDeviceReady, false);
			function onDeviceReady(){
				alert("hola mundo!");
			}
		</script>
	</head>
	<body>
		<div>Place holder</div>
	</body>
</html>
Ver ejemplo

Notificaciones (beep, vibrate alert)

navigator.notification.alert("Este es un mensaje");

// Beep three times
navigator.notification.beep(3);

// Vibrate for 2 seconds
navigator.notification.vibrate(2000);
Ver ejemplo

Reproducción multimedia

document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady(){
	//var reproductor = new Media("https://www.pablomonteserin.com/curso/javascript/phonegap_exercises/2_media/Hakuna.mp3", onSuccess, onError);

	//Para cargar archivos locales (en android) tendremos que indicar la ruta de la siguiente forma:
	var reproductor = new Media("/android_asset/www/Hakuna.mp3", onSuccess, onError);

	reproductor.play();
}
function onSuccess(){
	alert("reproduccionOK");
}

function onError(error){
	console.log(error.message);
}	
Ver ejemplo

Geolocalización

<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>
<link rel="stylesheet" type="text/css" href="http://code.google.com/apis/maps/documentation/javascript/examples/default.css">
<script type="text/javascript">
/*
-PhoneGap Documentation: The Android 2.x simulators will not return a geolocation result unless the enableHighAccuracy option is set to true.
- Para que se ejecute deviceReady, será necesario ejecutar la aplicación en Ripple, en el emulador, o en móvil; no basta sólo con ejecutar en un navegador, aunque sea a través de localhost.
- Si ejecutamos en el emulador es probable que sea necesario mandar las coordenadas de nuestra ubicación para que funcione la geolocalización (En eclipse: Window → show view → Emulator Control Location Controls → Manual → Send)
*/
document.addEventListener("deviceReady", deviceReady, false);
function deviceReady(){
	navigator.geolocation.getCurrentPosition(onGeoSuccess, onGeoError, { enableHighAccuracy: true });
}

function onGeoSuccess(position){
	var lat = position.coords.latitude;
	var lon = position.coords.longitude;
	var currentPosition = new google.maps.LatLng(lat, lon);
	var mapoptions = {
		zoom : 12,
		center: currentPosition,
		mapTypeId: google.maps.MapTypeId.ROADMAP
	};
	var map = new google.maps.Map(document.getElementById("map"), mapoptions);
	var marker = new google.maps.Marker({
		position: currentPosition,
		map: map
	});
}
function onGeoError(error){
	if(error==1){
		alert("turn on geolocation services")
	}else{
		alert("geoError: " + error);
		alert("geoError: " + error.message);
	}
}
Ver ejemplo

Uso de la cámara de fotos

document.addEventListener("deviceready", onDeviceReady, false);
var valores;

function onDeviceReady(){
	alert("inicia");
	capturador = navigator.device.capture;
}

function captura_audio(){
	alert("captura audio");
	capturador.captureAudio(capturaOK, capturaError);
}
function captura_video(){
	alert("captura video");
	capturador.captureVideo(capturaOK, capturaError);
        navigator.camera.getPicture(onSuccess, onFail, { quality: 50 }); 
}
function captura_imagen(){
	alert("captura imagen");
	capturador.captureImage(capturaOK, capturaError);

}
function capturaOK(archivos){
	alert("capturaOK")	
	for(var i =0; i<archivos.length; i++){
		var ruta = archivos[i].fullPath;
			alert(ruta)	
	}
}
function capturaError(){
	alert("error en la captura");
}
Descargar APK

Notas:

En el caso de Android, si un Activity es totalmente eclipsado por otro, será parado, almacenando su estado e información. Sin embargo, es posible que sea eliminado por el sistema cuando los requerimientos de memoria así lo estimen. Por tanto, al volver del capturador de multimedia es posible que la aplicación sea reiniciada, en lugar de ir al método capturaOK.

Lectura de ficheros


document.addEventListener("deviceready", function(){
	alert("deviceready");
	window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, archivosDisponibles, function(){
		alert("No esta disponible el sistema de archivos");
	});
}, false);

function archivosDisponibles(fileSystem){
//fileSystem.root nos da la carpeta de almacenamiento persistente asociada a nuesta aplicación, de donde podremos escribir y leer archivos
	alert(fileSystem.root.fullPath);
	fileSystem.root.getFile("readme.txt", null, archivoLeido, function(){
		alert("No esta disponible el sistema de archivos 2");
	});
}

function archivoLeido(archivo){
	alert("archivo leido");
	archivo.file(function(archivo){
		var reader = new FileReader();
		reader.onloadend = function(evento){
			alert(evento.target.result);
		}
		reader.readAsText(archivo);
	}, function(){
		alert("Error");
	});
}
		

Notas:

Probablemente tengamos que editar el contenido de un fichero readme.txt ubicado en la raíz del sistema de ficheros que vemos al conectar nuestro móvil al ordenador para tener una información que leer.

Consideraciones a tener en cuenta antes de subir la app a PhoneGap Build →

Aviso Legal | Política de privacidad