jueves, 12 de junio de 2014

Solución Made In Miguel

Seguimos trabajando en la aplicación de Cordova-Pet y nos está llevando por el camino de la amargura. La incapacidad para el correcto funcionamiento de los plugins hace resurgir de las sombras un héroe.

El problema: no nos vibraba el dispositivo. Comprobamos que está bien escrita la sentencia, que tenemos el plugin instalado que los permisos estaban bien escritos, ....

Solución aportada por Miguel:
Borra los permisos del AndroidManifest.xml, genera el apk; y vuelve a escribir los permisos a mano.
Bueno pues lo que parece una tontería, funciona a la perfección. La explicación que le damos es que Eclipse no nos actualiza correctamente los proyectos, así pues cuando instalas/desinstalas plugins se quedan "restos" dentro de los ficheros .xml, que consiguen que no nos vaya bien la aplicación.

miércoles, 11 de junio de 2014

Aplicaciones web en Chrome y Android


Google ha desarrollado, o mejor dicho, esta desarrollando una serie de herramientas para poder desarrollar aplicaciones Chrome que se ejecuten tanto en Android como en iOS como si fueran nativas basadas en Apache Cordova, hacia donde ha derivado este proyecto ya que estas herramientas están aun en un estado de desarrollo muy temprano.
            Se pueden empaquetar las aplicaciones Chrome para ser distribuidas por medio de Google Play o App Store.
            Estas aplicaciones estan desarrolladas con HTML, CSS y Javascript, que son los lenguajes con los que se trabaja en Apache Cordova.
            En la documentación de Chrome Apps Developer Tools, podemos ver las direcciones de trabajo que nos indican el proceso desde la creacion de la app, hasta su ejecución. Siendo estos dos caminos:
  • Por medio de la línea de comandos
  • A través del IDE o del SDK de las plataformas XCode o Eclipse

(Como podemos observar muy similar a Apache Cordova, por no decir que idéntico.)
            De hecho esta forma de trabajo pone a nuestra disposición todas las APIs de Apache Cordova.
            Para comenzar a desarrollar en este sistema existen una serie de aplicaciones de ejemplos y un proyecto en gitgub.

            De hecho tras investigar un poco, podemos ver que para desarrollar en la tecnología de Chrome, son necesarios los mismos requisitos que para Cordova o Phonegap:
  • nodejs
  • JAVA JDK 7
  • Andorid SDK version 4.4.2
  • Apache-ant

            A la hora de desarrollar proyectos, emular dispositivos... tan solo hay que cambiar la palabra cordoba por cca:

Chrome
Cordova
cca create HolaMundo
cordova create HolaMundo
cca emulate android
cordova emulate android
cca run android
cordova run android

            Incluso para realizar cambios en nuestros códigos HTML, CSS y Javascript es necesario acceder al directorio www.
            De hecho en la propia documentación puesta en githud:
(https://github.com/MobileChromeApps/mobile-chrome-apps/blob/master/docs/CordovaConsiderations.md) sobre el proyecto, derivan a ciertas consideraciones que hay que tener cuando se desarrolla en Chrome.

            Las diferencias más notables que hemos podido encontrar son:
  • En la tecnología desarrollada por Chrome, en principio solo se puede desarrollar para Android e iOs, mientras que en Apache Cordova entran también windows phone, windows 8 y BlackBerry
  • La forma de subir las aplicaciones a Play Store es directa con Chrome con tan solo una secuencia de comandos, mientras que no ocurre esto en Apache Cordova.

Aplicación de ZPAS.net

Aqui os dejamos la aplicación de ZPAS.net que hemos desarrollado con algunos plugins y que conlleva parte del catalogo

sábado, 7 de junio de 2014

Instalación de Cordova en Ubuntu

Uno de los inconvenientes de Apache Cordova es que hay muy buena documentación sobre sistemas Windows/MacOS. Por eso aquí trataremos la instalación de Cordova en un sistema Linux como es Ubuntu.
  • Instalación de ant:
    • $sudo apt-get install python-software-properties python g++ make ant
  •  Instalar Android SDK:
    • Puede que haya problemas con algunos repositorios de Android que fueron instalados en el sistema. Una manera de purgar y dejar limpia la instalación sería lanzando la siguiente sentencia:
      • $sudo apt-get remove android-tools-adb android-tools-fastboot
    • Descargamos el SDK de la página oficial y lo descomprimimos en el directorio que queramos. (Recordad y mantened la ruta porque será la utilizada para establecer el PATH).
  • Editamos el archivo ~/.bashrc:
    • $sudo gedit ~/.bashrc
  • Y añadimos al principio del fichero el siguiente PATH:
    • export PATH=${PATH}:/ruta-del-sdk/adt-bundle/sdk/platform-tools:/ruta-del-sdk/adt-bundle/sdk/tools
    • Donde ruta-del-sdk será donde tengamos alojado el SDK dentro de nuestro sistema.
    • Solo se enlazan los directorios platform-toos y tools.
    • Se recargan las variables del bash con:
      • $source ~/.bashrc
  • Instalación de node.js:
    • Añadimos el repositorio:
      • $sudo add-apt-repository ppa:chris-lea/node.js
    • Actulizamos:
      • $sudo apt-get update
    • Lanzamos instalación:
      • $sudo apt-get install python-software-properties python g++ make nodejs
  • Instalación de Cordova:
    • $sudo npm install -g cordova
Con esto hemos conseguido instalar Apache Cordova satisfactoriamente en Ubuntu. Vuelvo a remarcar la importancia de los PATH porque pueden dar problemas al intentar añadir la plataforma Android a un proyecto que hayamos creado, por poner un ejemplo.

Fuente

jueves, 5 de junio de 2014

Cuidad vuestras mascotas

Hemos comenzado la producción de una nueva aplicación bajo Cordova. Esta aplicación será un juego basado en el "lindo gatito", el cual conocemos muy bien todos. Pero esta vez la mascota será el logotipo de Cordova.

Primero decidimos que lo íbamos a basar en el clásico tamagotchi; así pues la mascota comerá, dormirá, jugará, hasta hará sus propias cacas. Pero el peso importante lo tenemos que decantar con la utilización de los plugins más punteros. Hemos decidido la introducción de: una pantalla de carga para usar splashscreen, que los mensajes los mostráramos en dialogs, el uso del acelerómetro para jugar con tu mascota, mostrar contenido web con ayuda de inappbrowser, vibración para alertar al jugador, almacenamiento de mascotas difuntas en bases de datos...

El siguiente paso obligatorio sería el diseño del mock-up para ayudarnos a estructurar y agilizar el desarrollo de la aplicación. Primero trasladado en papel como bocetos y luego digitalizado para la posterior documentación a presentar.

Entonces actualmente nos encontramos con la mayoría de ventanas ya programadas, un interfaz completamente definido a falta de la funcionalidad del "bichito", iconos y botones ya diseñados, logotipo finalizado y trabajando la documentación a la par.

miércoles, 4 de junio de 2014

Documentación Version 1.0

Por fin hemos culminado el trabajo con el exelearning, la documentación esta completa para realizar proyectos utilizando casi cualquier plugin, evento, e incluso bases de datos.
En esta versión 1.0, se pueden encontrar:
  • La instalación y los requisitos mínimos para que tu maquina pueda crear proyectos en Apache Cordova.
  • Como crear una aplicación desde cero, creando el proyecto y utilizar html5 y css3 para ello
  • Los plugins y eventos más importantes con ejemplos, vídeos demostrativos y enlaces a proyectos completos.
  • Información básica sobre la lectura, creación y borrado de archivos
  • Almacenamiento de datos por medio de la BD; SQLite
  • Como utilizar la línea de comandos (CLI)
  • Utilización del archivo config.xml
  • Como utilizar la privacidad con Apache Cordova y algunos consejos para que esta no se rompa.
  • Listas blancas
  • Como actualizar a la última versión de Apache Cordova.
Para acceder a esta documentación haz click sobre la imagen, y estarás listo para hacer tus propias aplicaciones en Android en muy poco tiempo.
http://apachecordova.esy.es/ 

Nota: Esta versión esta pendiente de la revisión gramatical y ortográfica final.


API de FileSystem

El API se divide en varios temas:
  • lectura y manipulación de archivos (File/Blob, FileList, FileReader),
  • creación y escritura (BlobBuilder, FileWriter),
  • acceso a sistemas de archivos y directorios (DirectoryReader, FileEntry/DirectoryEntry, LocalFileSystem).

Solicitud de un sistema de archivos

Una aplicación web puede solicitar acceso al sistema de archivos de prueba con window.requestFileSystem():

window.requestFileSystem(type, size, successCallback, opt_errorCallback)
  • type: Indica si el almacenamiento de archivos debe ser permanente. Los valores que se pueden utilizar son window.TEMPORARY y window.PERSISTENT. Los datos almacenados con el tipo TEMPORARY se pueden eliminar a elección del navegador. Los datos almacenados con el tipo PERSISTENT no se pueden borrar a menos que el usuario o la aplicación lo autoricen expresamente y requieren que el usuario otorgue espacio de almacenamiento a la aplicación.
  • size: Indica el espacio (en bytes) de almacenamiento que necesitará la aplicación.
  • successCallback. Indica la devolución de llamada que se activa cuando se autoriza el acceso a un sistema de archivos. Su argumento es un objeto FileSystem.
  • opt_errorCallback: Corresponde a una devolución de llamada opcional para la gestión de errores o para los casos en los que se deniega la solicitud de acceso al sistema de archivos. Su argumento es un objeto FileError.

Cómo crear un archivo

Para buscar o crear archivos, se puede utilizar el método getFile() de la interfaz DirectoryEntry del sistema de archivos. Una vez que se ha solicitado un sistema de archivos, se transmite a la devolución de llamada de operación correcta un objeto FileSystem que contiene una interfaz DirectoryEntry (fs.root) que señala al directorio raíz del sistema de archivos de la aplicación.

window.requestFileSystem(window.TEMPORARY, 1024*1024, onInitFs, errorHandler);
function onInitFs(fs) {

  fs.root.getFile('log.txt', {create: true, exclusive: true}, function(fileEntry) {

    // fileEntry.isFile === true
    // fileEntry.name == 'log.txt'
    // fileEntry.fullPath == '/log.txt'

  }, errorHandler);

}

Una vez que se ha solicitado el sistema de archivos, se transmite un objeto FileSystem al controlador de operación correcta. Dentro de la devolución de llamada, se puede solicitar fs.root.getFile() indicando el nombre del archivo que se va a crear. Se puede especificar una ruta absoluta o relativa, pero debe ser una ruta válida. Por ejemplo, es un error intentar crear un archivo cuyo elemento inmediatamente anterior no exista. El segundo argumento de getFile() es una cadena literal de objeto que describe el comportamiento que debe tener la función si el archivo no existe. En este ejemplo, create: true hace que se cree el archivo si no existe y que se genere un error en caso contrario (exclusive: true). Por su parte, create: false hace que el archivo simplemente se extraiga y se muestre. En ambos casos, el contenido del archivo no se sobrescribe, ya que solo se está obteniendo una entrada de referencia al archivo en cuestión.

Cómo leer un archivo por nombre

El código que aparece a continuación permite recuperar el archivo "log.txt", leer su contenido con el API FileReader e incorporarlo a una nueva área de texto (<textarea>) en la página. Si el archivo "log.txt" no existe, se genera un error.

function onInitFs(fs) {

  fs.root.getFile('log.txt', {}, function(fileEntry) {

    // Get a File object representing the file,
    // then use FileReader to read its contents.
    fileEntry.file(function(file) {
       var reader = new FileReader();

       reader.onloadend = function(e) {
         var txtArea = document.createElement('textarea');
         txtArea.value = this.result;
         document.body.appendChild(txtArea);
       };

       reader.readAsText(file);
    }, errorHandler);

  }, errorHandler);

}

window.requestFileSystem(window.TEMPORARY, 1024*1024, onInitFs, errorHandler);

Cómo escribir en un archivo

El código que aparece a continuación permite crear un archivo vacío llamado "log.txt" (en caso de que no exista) y escribir en él el texto "Lorem Ipsum".

window.requestFileSystem(window.TEMPORARY, 1024*1024, onInitFs, errorHandler);

function onInitFs(fs) {

  fs.root.getFile('log.txt', {create: true}, function(fileEntry) {

    // Create a FileWriter object for our FileEntry (log.txt).
    fileEntry.createWriter(function(fileWriter) {

      fileWriter.onwriteend = function(e) {
        console.log('Write completed.');
      };

      fileWriter.onerror = function(e) {
        console.log('Write failed: ' + e.toString());
      };

      // Create a new Blob and write it to log.txt.
      var bb = new BlobBuilder(); // Note: window.WebKitBlobBuilder in Chrome 12.
      bb.append('Lorem Ipsum');
      fileWriter.write(bb.getBlob('text/plain'));

    }, errorHandler);

  }, errorHandler);

}

Esta vez, se utiliza el método createWriter() de FileEntry para obtener un objeto FileWriter. Dentro de la devolución de llamada de operación correcta, se definen controladores para los eventos error y writeend. Para escribir los datos del texto en el archivo, se crea un objeto Blob, se le añade texto y se transmite el objeto a FileWriter.write().

Cómo añadir datos a un archivo

El código que aparece a continuación permite añadir el texto "Hello World" al final del archivo de registro. Si el archivo no existe, se genera un error.

window.requestFileSystem(window.TEMPORARY,1024*1024, onInitFs, errorHandler);

function onInitFs(fs) {

  fs.root.getFile('log.txt',{create: false}, function(fileEntry) {

    // Create aFileWriter object for our FileEntry (log.txt).
    fileEntry.createWriter(function(fileWriter){

      fileWriter.seek(fileWriter.length);
      // Start write position at EOF.

      // Create a new Blob and write it to log.txt.

      var bb = new BlobBuilder();

      bb.append('Hello World');

      fileWriter.write(bb.getBlob('text/plain'));

    }, errorHandler);

 }, errorHandler);

}

Cómo eliminar un archivo

El código que aparece a continuación permite eliminar el archivo "log.txt".

window.requestFileSystem(window.TEMPORARY, 1024*1024, function(fs) {
  fs.root.getFile('log.txt', {create: false}, function(fileEntry) {

    fileEntry.remove(function() {
      console.log('File removed.');
    }, errorHandler);

  }, errorHandler);
}, errorHandler);

Cómo copiar entradas, cambiarles el nombre y moverlas

Las interfaces FileEntry y DirectoryEntry comparten algunas operaciones.

Cómo copiar una entrada

Tanto FileEntry como DirectoryEntry cuentan con el método copyTo() para la duplicación de entradas. Este método permite hacer una copia recurrente en diferentes carpetas.
El código del ejemplo que aparece a continuación permite copiar el archivo "me.png" de un directorio en otro:

function copy(cwd, src, dest) {
  cwd.getFile(src, {}, function(fileEntry) {

    cwd.getDirectory(dest, {}, function(dirEntry) {
      fileEntry.copyTo(dirEntry);
    }, errorHandler);

  }, errorHandler);
}

window.requestFileSystem(window.TEMPORARY, 1024*1024, function(fs) {
  copy(fs.root, '/folder1/me.png', 'folder2/mypics/');
}, errorHandler);

Cómo mover una entrada o cambiarle el nombre

El método moveTo() de FileEntry y DirectoryEntry permite mover archivos y directorios y cambiarles el nombre. El primer argumento especifica el directorio principal al que se debe mover el archivo y el segundo argumento indica un nuevo nombre opcional para el archivo. Si no se especifica un nombre nuevo, se utilizará el nombre original del archivo.
El código de ejemplo que aparece a continuación permite sustituir el nombre del archivo "me.png" por "you.png" sin mover el archivo:

function rename(cwd, src, newName) {
  cwd.getFile(src, {}, function(fileEntry) {
    fileEntry.moveTo(cwd, newName);
  }, errorHandler);
}

window.requestFileSystem(window.TEMPORARY, 1024*1024, function(fs) {
  rename(fs.root, 'me.png', 'you.png');
}, errorHandler);

El código de ejemplo que aparece a continuación permite mover el archivo "me.png" (ubicado en el directorio raíz) a una carpeta llamada "newfolder".

function move(src, dirName) {
  fs.root.getFile(src, {}, function(fileEntry) {

    fs.root.getDirectory(dirName, {}, function(dirEntry) {
      fileEntry.moveTo(dirEntry);
    }, errorHandler);

  }, errorHandler);
}

window.requestFileSystem(window.TEMPORARY, 1024*1024, function(fs) {
  move('/me.png', 'newfolder/');
}, errorHandler);

martes, 3 de junio de 2014

Intentar guardar ficheros en local

La idea de esta incursión era poder escribir, leer y borrar ficheros que se encontraran en nuestro dispositivo. Antes de leer he pensado que sería mejor poder escribirlos con algún tipo de contenido. Algo sencillo: un documento de texto (.txt) con algún texto escrito.

Obviamente el plugin para poder manejar esta máquina será File. Como anteriormente se habría comentado el comando para instalar el plugin en nuestro proyecto sería:

cordova plugin add org.apache.cordova.file

He optado por no pedirle datos al usuario y que dándole a un simple botón automáticamente hiciera todo lo necesario para crear el fichero, escribirlo y alojarlo en nuestro dispositivo (en este caso se guarda en la tarjeta de memoria, que en realidad es donde se instala el apk, en otras palabras, donde se encuentra la aplicación instalada).

Lo primero sería especificar mediante JavaScript que queremos guardar un fichero. Nos ayudaremos del método requestFileSystem al que le especifico un guardado persistente, de un tamaño de 100 bytes y las dos llamadas éxito y de fallo:

window.requestFileSystem(LocalFileSystem.PERSISTENT,
                         100, 
                         gotFileSystem, 
                         fail);

Si este objeto se crea nos llevaría a la función gotFileSystem especificada anteriormente para que ahora nos cree físicamente el archivo en nuestro dispositivo. Nos ayudamos del método getFile, al que le paso el nombre del archivo, unas cuantas opciones y las dobles funciones de éxito y fallo:

fileSystem.root.getFile("readme2.txt",
                             {create: true, exclusive: false}, 
                             gotFileEntry, 
                             fail);

Si se ha creado satisfactoriamente el fichero en el dispositivo tenemos que crear un objeto FileWriter que nos sirva de manejador para escribir en el fichero en cuestión. Nos ayudamos del método createWriter, el cual solo recibe el éxito o el fallo:

fileEntry.createWriter(gotFileWriter, fail);

Una vez tenemos el manejador podremos escribir en nuestro documento con el método write. Automáticamente nos reemplazará el contenido con el texto que le hayamos pasado por argumento y lo guardará.

Todo esto está tal cual de la documentación oficial de Cordova. El problema con el que me he encontrado es que a veces solo crea los escuchadores, otras solo crea el fichero vacío, otras lo hace todo bien y una solución burda para que lo hiciera bien de primeras era tener que darle muchas veces repetidas al botón. He de decir que este ejemplo está copiado totalmente de la documentación y se supone que está testeado por los propios desarrolladores. Sin embargo, no conseguimos crear a la primera el fichero con el texto que le hayamos puesto.

Aplicación real con Apache Cordova

Como parte del proyecto, y con el fin de poder trabajar en él durante las prácticas, propusimos a la empresa, ZPAS.net, hacerle una aplicación para ellos, cuya página ni ten siquiera es responsive.
En respuesta ellos nos dijeron que querían una especie de presentación tipo catalogo, y es lo que le estamos haciendo, aunque aun estamos en la fase de desarrollarlo tipo web, podemos determinar varias cosas:
  • Las transiciones, overs, focus... de css3 no funcionan bien y hemos tenido que no recurrir a ellas
  • Se debe de producir primero en formato web local para poder desarrollarla entera y después introducir todos los plugins de Cordova y utilizarlos.
Esperamos tenerla terminada para dentro de poco, aunque como es normal, ahora mismo no podemos mostrar mucho, ya que esta en desarrollo, pero aun así ponemos aquí el menú principal.

lunes, 2 de junio de 2014

Primero incursión DataStorage

Hemos querido implementar un par de aplicaciones que nos sirviera para comprobar el manejo de bases de datos. Por un lado ha imperado el almacenamiento por Web SQL Database que se ha enfrentado al LocalStorage.

Ambos cuentan con sentencias potentes; por un lado el Web SQL se sirve de sentencias en lenguaje SQL, mucho más numerosas y potentes pero hay que remarcar que la W3C ha dejado de darle soporte ( no por ello, signifique que no podemos seguir utilizándola ). El LocalStorage utiliza menos sentencias y la disposición de sus datos se basa en claves y valores indexados.

La primera prueba sobre LocalStorage daba positivo pero en un navegador web convencional como en el que teníamos en nuestra máquina. Sin embargo al portarlo a Apache Cordova, la aplicación no lanzaba ningún resultado satisfactorio. Simplemente no aparecían los valores y claves que habíamos introducido. Aún tratamos de esclarecer porque funciona en un navegador y no en la aplicación nativa.

La segunda apuesta por Web SQL guarda y muestra bien los datos en toda la ejecución de la aplicación sin embargo, desconocemos donde se encuentran estos datos almacenados.

De ahí nuestro interés de que podamos administrar dichos datos para guardarlos en ficheros de extensión .sql por ejemplo. Será nuestra próxima arremetida contra este inconveniente.