Skip to content
Christian Gastrell edited this page Jul 7, 2015 · 2 revisions

Como sabemos, cada vez que iniciamos una entrevista **pre-**generamos el archivo de audio. Esto lo hacemos porque necesitamos tenerlo listo o simplemente porque no somos mas listos como para hacerlo de otra forma. Como sea, la situacion es que quedan archivos, que si bien no ocupan nada, es basura que queda por ahi y deberiamos limpiarla.

Para poder determinar que archivos debemos eliminar vamos a:

  • obtener una lista de archivos en la carpeta de audio
  • obtener una lista de paths que estan almacenados en las entrevistas que tenemos guardadas en entrevistas.lista
  • cruzaremos un listado con el otro y, todos aquellos archivos que no existan en el listado extraido de las entrevistas, deberian ser eliminados

Para esto vamos a agregar metodos en entrevistas y en fileApi.

fileApi

La ultima version que tenemos de fileApi tiene estos metodos:

var fileApi = {
  ready: false, // <--solo por las dudas
  initialize: function(callback){
    var path = cordova.file.externalDataDirectory;
    //si no hay problemas, llamamos a callback con el primer
    //parametro en null (lo que seria el error)
    var onResolve = function(directoryEntry) {
      fileApi.dir = directoryEntry;
      fileApi.ready = true;
      callback && callback(null, fileApi);
    }
    //si hay un error llamamos a callback con el error
    //como primer parametro (ver arriba)
    var onError = function(err){
      callback && callback(err, fileApi);
    }
    window.resolveLocalFileSystemURL(path, onResolve, onError);
  },
  writeTextFile: function(file, content, callback) {
    var onFile = function(fileEntry) {
      fileEntry.createWriter(
        function(fileWriter){
          fileWriter.write(content);
          callback && callback(content);
        }, fileApi.onError);
    }
    fileApi.dir.getFile(file, {create: true}, onFile, fileApi.onError);
  },
  onError: function(err) {
    console.log(err);
  },
  getDir: function(dir, callback) {
    var onDir = function(dir){
      callback && callback(null, dir);
    }
    var onError = function(err) {
      callback && callback(err, null);
    }
    fileApi.dir.getDirectory(dir, {create:true}, onDir, onError);
  }
}

fileApi es nuestra interfaz con el sistema de archivos. La idea es que se encargue de la parte pesada y nos devuelva resultados, asi que parece un buen lugar para implementar un metodo que lea el contenido de un directorio y nos arroje el resultado.

En la documentacion del file plugin de phonegap vemos un listado de objetos y clases que el plugin puede manejar para devolvernos funcionalidad. Entre ellos figuran 3 que vamos a necesitar:

  • DirectoryEntry
    • en particular el metodo createReader que, segun documentacion, createReader: Create a new DirectoryReader that can read entries from a directory
  • DirectoryReader
    • cuyo unico metodo es readEntries cuya descripcion es readEntries: Read the entries in a directory
  • FileEntry
    • en la documentacion figura el metodo remove() ...

Entonces, crearemos en fileApi el metodo readDir. Este metodo tomara como argumentos:

  • dir - {String}: el nombre del directorio cuyo contenido queremos listar
  • callback - {Function}: un callback para devolver el resultado

Agreguemos el metodo justo debajo del metodo getDir ya que va a estar intimamente relacionado:

  getDir: function(dir, callback) {
    var onDir = function(dir){
      callback && callback(null, dir);
    }
    var onError = function(err) {
      callback && callback(err, null);
    }
    fileApi.dir.getDirectory(dir, {create:true}, onDir, onError);
  }, // <-- no se olviden esta coma
  readDir: function(directoryEntry, callback) {
    directoryEntry.createReader().readEntries(callback);
  },

Por que estan relacionados los 2 metodos? Porque el metodo createReader es de un DirectoryEntry, es decir, no podemos pasarle un String con el nombre del archivo, necesitamos pasarle el objeto que nos devuelve getDir. Si se fijan, getDir si puede recibir el nombre del directorio que queremos como un {String}. Entonces, la llamada para obtener el contenido de un directorio sera algo asi (recordando que son todas funciones asincronicas):

fileApi.getDir('audio', function(directoryEntry) {
  directoryEntry.readEntries(function(entries){
    // aca finalmente tenemos entries, que
    // es un array con FileEntries
  });
});

Con este metodo implementado ya podemos cerrar fileApi y empezar a agregar metodos en entrevistas

entrevistas

En el objeto entrevistas agregaremos el metodo obtenerListaDeArchivosDeAudio al final del objeto (antes del ultimo cierre de llave, separado con una coma):

  obtenerListaDeArchivosDeAudio: function(callback) {
    fileApi.getDir('audio', function(err, dirEntry){
      if(err){
        callback && callback(err, []);
      }
      fileApi.readDir(dirEntry, function(entries){
        callback && callback(null, entries);
      });
    });
  },

Este metodo tambien lo haremos asincronico, que llamara el callback que le proveamos con:

  • err - {Error}: un error, si lo hubiese
  • entries - {Array}: un array de FileEntries, resultado del fileApi.readDir()

Tambien necesitamos el listado de entrevistas, pero necesitamos un listado mas simple, uno que solo contenga el path de los archivos de audio de las entrevistas, entonces generaremos el metodo obtenerArchivosDeAudioDeEntrevistas(), que tambien sera asincronico. La magia de este metodo sera levantar todo el listado en entrevistas.lista e iterarlo para extraer un array simple con los paths a los archivos de audio:

  obtenerArchivosDeAudioDeEntrevistas: function(callback) {
    var filePaths = [];
    $.each(entrevistas.lista, function(idx, item){
      filePaths.push(item.audioPath);
    });
    callback(filePaths);
  },

Y por ultimo, un metodo que llame a los dos metodos anteriores, encadenado uno con otro, y luego itere por sobre cada archivo de audio y conforme un nuevo listado con aquellos que no figuren entre los archivos de audio de las entrevistas y lo devuelva, tambien de manera asincronica.

Para cruzar los 2 arrays usaremos el metodo Array.indexOf, que nos devuelve un entero representando el indice del array donde se encontro el valor que estamos buscando. Si no se encuentra devolvera -1

Agreguen el metodo encontrarArchivosHuerfanos():

  encontrarArchivosHuerfanos: function(callback) {
    var huerfanos = [];
    entrevistas.obtenerArchivosDeAudioDeEntrevistas(function(paths){
      entrevistas.obtenerListaDeArchivosDeAudio(function(err, files){
        if(err) {
          //si hay error devuelvo el array vacio
          return callback && callback(huerfanos);
        }
        $.each(files, function(i,e){
          // por cada archivo en el directorio
          // buscamos el nativeURL en el array
          // de paths que obtuvimos de las entrevistas
          if(paths.indexOf(e.nativeURL) == -1) {
            // si NO se encuentra
            // es un archivo huerfano
            huerfanos.push(e);
          }
        });
        callback && callback(huerfanos);
      });
    });
  },

Funcionalidad

Como bien nombramos el metodo encontrarArchivosHuerfanos la idea es que solo los busque y los devuelva, no que los borre. Lo que hagamos con ellos sera parte de la funcionalidad donde lo querramos usar.

Podriamos hacerlo al arrancar la aplicacion, o silenciosamente al salir de una entrevista. Pero por el momento vamos a crear un boton con la funcion especifica de buscarlos y borrarlos.

Crearemos el boton en la pagina #home, debajo del boton para entrevistar, en el archivo index.html y le pondremos el id limpiarHuerfanos:

  <div data-role="content">
    <a href="#entrevista-list" class="ui-btn">Archivo de entrevistas</a>
    <a href="#guia-list" class="ui-btn">Entrevistar</a>
    <a href="#" id="limpiarHuerfanos" class="ui-btn">Borrar archivos temporales</a>
  </div>

Luego, en el archivo js/index.js agregaremos un handler para el evento pagecreate de la pagina #home (hasta el momento no existia dado que no inicializabamos nada en #home):

$('#home').on('pagecreate', function(){
  $('#limpiarHuerfanos').on('click', function(evt){

    // cancelamos el comportamiento del boton
    evt.preventDefault();

    // mostramos el spinner, por si demora mucho
    $.mobile.loading('show');

    // y llamamos a nuestro metodo en entrevistas
    entrevistas.encontrarArchivosHuerfanos(function(archivos){
      // contamos cuantos volvieron
      var cantidad = archivos.length;

      // luego iteramos por el resultado
      $.each(archivos, function(i,e){
        // y como sabemos que son FileEntries
        // ejecutamos .remove() en cada uno
        e.remove();
      });
      // mostramos un mensaje y escondemos el spinner
      alert('Se eliminaron '+cantidad+' archivos huerfanos');
      $.mobile.loading('hide');
    });
  });
});
  1. Repaso y conceptos basicos
  2. Ejercicios para repasar
  3. Problematica de desarrollo mobile
  4. Phonegap
  5. Requerimientos e instalacion
  6. Phonegap CLI
  7. [Primeros ejercicios con Phonegap](Ejercicio Phonegap)
  8. Plugins
  9. Hello world
  10. Estructura de un proyecto Phonegap
  11. Plugin Device
  12. Debugging
  13. Incorporando un framework CSS
  14. Plugin Vibration
  15. Sumando partes
  16. Plugin Battery Status
  17. Un poco de jQuery
  18. jQuery Mobile
  19. Navegacion
  20. Plugin Dashboard
  21. Revision de Plugin Dashboard
  22. Paginas extra
  23. ToDo
  24. Persistencia
  25. ToDo Persistente
  26. Plugin Camera
  27. Opciones de camara
  28. App Mi Galeria
  29. Revision de Galeria
  30. Plugin File
  31. Escribir y leer texto
  32. Escribir archivos binarios
  33. Guardando fotos
  34. Debugger: weinre
  35. Inspeccionar con weinre
  36. Phonegap Developer App
  37. Refactor de apps
  38. Plugin Media
  39. Pruebas con audio
  40. Control y monitoreo de audio
  41. Encapsular play/pausa
  42. Hacks
  43. Formato de tiempos
  44. Grabar y reproducir
  45. Proyecto Integrador
  46. Revision de interfaz
  47. Interfaz basica
  48. Entrevista: modelo
  49. Funcionalidad: revision
  50. Seleccion de framework
  51. iRec: navegacion
  52. iRec: fileApi
  53. iRec: guias
  54. iRec: entrevistas
  55. iRec: recordApi
  56. iRec: helpers
  57. iRec: mediaApi
  58. iRec: inicializar paginas
  59. iRec: refactor
  60. iRec: mediaApi refactor
  61. iRec: recordApi refactor
  62. iRec: helpers
  63. iRec: guias.js
  64. iRec: entrevistas.js
  65. iRec: crear guias
  66. iRec: re-inicializando
  67. iRec: re-ordenando
  68. iRec: pendientes
  69. iRec: reporte ux
  70. iRec:revision: volver
  71. iRec:entrevista: volver
  72. iRec:revision: cambios
  73. iRec:revision: stop
  74. iRec:revision: Rew 10"
  75. iRec:revision: tag Go
  76. iRec: limpieza
  77. Firma de apps
  78. Android
  79. Generacion de key
  80. Firma de apk
  81. Alineacion de zip
  82. Firmar con Phonegap
  83. iOS
  84. Detalles finales
  85. Config.xml
  86. Iconos
  87. Splash
Clone this wiki locally