Cómo obtener documentos en un directorio de Android que PhoneGap verá

Me gustaría poder copiar algunos archivos en el directorio de documentos de PhoneGap / Cordova, para que se muestren cuando utilizo la API cordova-plugin-file para listar ese directorio. Desafortunadamente, parece haber cierta desconexión entre la API de archivos y lo que realmente está establecido en el almacenamiento de la tableta. Esto es lo que la especificación del complemento de archivo dice que la estructura del directorio del sistema debe verse así:

Diseño de sistema de archivos Android

  • file:///android_asset/ | cordova.file.applicationDirectory
  • file:///android_asset/data/data// | cordova.file.applicationStorageDirectory
  • file:///android_asset/data/data//cache | cordova.file.cacheDirectory
  • file:///android_asset/data/data//files | cordova.file.dataDirectory
  • file:///android_asset/data/data//Documents | cordova.file.documents
  • / | cordova.file.externalRootDirectory
  • /Android/data// | cordova.file.externalApplicationStorageDirectory
  • /Android/data//cache | cordova.file.externalCacheDirectry
  • /Android/data//files | cordova.file.externalDataDirectory

Lamentablemente, no veo esto cuando conecto mi dispositivo (4.4.2 / tableta Lenovo) a mi PC o Mac. En cambio, veo:

 - Internal Storage |- .IdeaDesktopHD |- .lelauncher |- .magic |- .powercenterhd |- Alarms |- Android |- Audio |- Bluetooth |- Contact |- data |- DCIM |- Document |- Download |- googleota |- legc |- LenovoReaper |- LesyncDownload |- Movies |- MyFavorite |- Notifications |- Others |- Pictures |- Podcasts |- powercenterhd |- Ringtones |- SHAREit 

¿Alguna idea de dónde debería copiar los archivos para que mi aplicación pueda verlos?

Bien ahora. Parte de mi problema fue que me tocó poco la naturaleza asíncrona del sistema de archivos / API cordova-plugin-file en cordova. Tuve que hacer un poco de refactorización de código para que la lista de archivos se mostrara correctamente, pero una vez que lo hice, los archivos se mostraban correctamente, independientemente de dónde estuvieran en el dispositivo.

Aquí está el código aplicable. Tenga en cuenta que necesitará el archivo cordova-plugin-agregado a su proyecto Cordova / PhoneGap, y que no funcionará en el navegador. De hecho, tengo este bloque dentro de otro bloque if / then – si se está ejecutando en un navegador, muestre html5 , si está en un dispositivo móvil, muestre este bloque:

 var localURLs = [ cordova.file.dataDirectory, cordova.file.documentsDirectory, cordova.file.externalApplicationStorageDirectory, cordova.file.externalCacheDirectory, cordova.file.externalRootDirectory, cordova.file.externalDataDirectory, cordova.file.sharedDirectory, cordova.file.syncedDataDirectory ]; var index = 0; var i; var statusStr = ""; var addFileEntry = function (entry) { var dirReader = entry.createReader(); dirReader.readEntries( function (entries) { var fileStr = ""; var i; for (i = 0; i < entries.length; i++) { if (entries[i].isDirectory === true) { // Recursive -- call back into this subdirectory addFileEntry(entries[i]); } else { fileStr += (entries[i].fullPath + "
"); // << replace with something useful index++; } } // add this directory's contents to the status statusStr += fileStr; // display the file list in #results if (statusStr.length > 0) { $("#results").html(statusStr); } }, function (error) { console.log("readEntries error: " + error.code); statusStr += "

readEntries error: " + error.code + "

"; } ); }; var addError = function (error) { console.log("getDirectory error: " + error.code); statusStr += "

getDirectory error: " + error.code + ", " + error.message + "

"; }; for (i = 0; i < localURLs.length; i++) { if (localURLs[i] === null || localURLs[i].length === 0) { continue; // skip blank / non-existent paths for this platform } window.resolveLocalFileSystemURL(localURLs[i], addFileEntry, addError); }

EDITAR (febrero de 2018) : incluso si puede ver los archivos en Android File Transfer , es posible que no obtenga ningún resultado de forma programática, incluso si tiene permisos de tiempo de comstackción configurados en su aplicación Cordova. Esto se debe a las comprobaciones de permisos de tiempo de ejecución agregadas a Android (creo que> 6.0). Hay un par de complementos que pueden ayudar a evitar esto; en algún momento, supongo que el complemento de archivo también agregará solicitudes automáticas. Esto es lo que hice desde Cordova cli-7.0.1 :

En su config.xml, establezca los permisos necesarios de la aplicación. Necesitará READ_EXTERNAL_STORAGE (y escriba también, si va a hacer eso). También estoy agregando dos complementos que se mencionan a continuación:

       

Luego, preferiblemente en algún lugar del código de inicio de su aplicación (es decir, el controlador para el evento ready del dispositivo), verifique los permisos de tiempo de ejecución y agréguelos si es necesario:

 if (device.platform === "Android") { // request read access to the external storage if we don't have it cordova.plugins.diagnostic.getExternalStorageAuthorizationStatus(function (status) { if (status === cordova.plugins.diagnostic.permissionStatus.GRANTED) { console.log("External storage use is authorized"); } else { cordova.plugins.diagnostic.requestExternalStorageAuthorization(function (result) { console.log("Authorization request for external storage use was " + (result === cordova.plugins.diagnostic.permissionStatus.GRANTED ? "granted" : "denied")); }, function (error) { console.error(error); }); } }, function (error) { console.error("The following error occurred: " + error); }); } 
 scan : function(url,fileType,callback) { var fileTypeCollection = []; var defer = $q.defer(); url.forEach(function(element, index) { //requestLocalFileSystemURL log(element); window.resolveLocalFileSystemURL(element,onRequestFileSystem, fail); log("Ends resolve"); }); function onRequestFileSystem(fileSystem) { var directoryReader = fileSystem.createReader(); directoryReader.readEntries(onReadEntries,fail); } /*onRequestFile Ends*/ function onReadEntries(entries) { if(entries.length==0) { log("Entries Length....Resolving"); defer.resolve(fileTypeCollection); } else { entries.forEach( function(element, index) { if (element.isDirectory === true) { // Recursive -- call back into this subdirectory onRequestFileSystem(element); } if(element.isFile == true) { fileType.forEach(function(type) { if(element.name.indexOf(type) != -1) { fileTypeCollection.push(element); } }); } /*is File ENds*/ }); /*Entries For Each Ends*/ } } /*OnRead Ends*/ function fail(resp) { log(resp); defer.reject(); } /*Fail Ends*/ return defer.promise; } //Scan Function Ends 

Tengo esto para Angularjs. Pero estoy teniendo problemas con esto. Si ejecuta esto, encontrará que los resultados se vuelven a asignar más de una vez cuando llamo esto, también prometo que no parece funcionar correctamente. pero funciona con callback, pero hasta volvería muitple veces y no habría forma de saber cuándo se completa el recorrido completo del archivo.