How to get documents in the Android directory that PhoneGap sees

I would like to be able to copy some files to my PhoneGap / Cordova Documents directory so that they appear when I use the cordova-plugin-file API to list this directory. Unfortunately, there seems to be some disconnect between the file API and what is actually laid out on the tablet storage. Here, that the specification of the File plugin says that the structure of the system directory should look like this:

Android file system format

  • file:///android_asset/ | cordova.file.applicationDirectory
  • file:///android_asset/data/data/<app-id>/ | cordova.file.applicationStorageDirectory
  • file:///android_asset/data/data/<app-id>/cache | cordova.file.cacheDirectory
  • file:///android_asset/data/data/<app-id>/files | cordova.file.dataDirectory
  • file:///android_asset/data/data/<app-id>/Documents | cordova.file.documents
  • <sdcard>/ | cordova.file.externalRootDirectory
  • <sdcard>/Android/data/<app-id>/ | cordova.file.externalApplicationStorageDirectory
  • <sdcard>/Android/data/<app-id>/cache | cordova.file.externalCacheDirectry
  • <sdcard>/Android/data/<app-id>/files | cordova.file.externalDataDirectory

Unfortunately, I do not see this when I connect my device (tablet 4.4.2 / Lenovo) to a computer or Mac. Instead, I see:

 - 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 

Any idea where I should copy the files so that my application can see them?

+4
android cordova cordova-plugins
source share
2 answers

Good. Part of my problem was that I got the slightly asynchronous nature of the file system API / cordova -plugin-file on the cord. I needed to refactor the code to get a list of files in order to display correctly, but as soon as I did, the files displayed correctly, regardless of where they are on the device.

Here is the applicable code. Please note that you will need the cordova-plugin file added to your Cordova / PhoneGap project and that it will not work in the browser. I actually have this block inside another if / then block - if it works in a browser, show html5 <input type=file> , if it is on a mobile device, show this block:

 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 + "<br>"); // << replace with something useful index++; } } // add this directory 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 += "<p>readEntries error: " + error.code + "</p>"; } ); }; var addError = function (error) { console.log("getDirectory error: " + error.code); statusStr += "<p>getDirectory error: " + error.code + ", " + error.message + "</p>"; }; 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); } 

EDIT (February 2018) : even if you can see files in Android File Transfer, you may not receive any results programmatically, even if you have time to build permissions set in the Cordova application. This is because runtime checks have been added in Android (I believe> 6.0). There are a couple of plugins that can help get around this; at some point, I assume that the plugin file will also add automatic queries to it. Here is what I did with cli-7.0.1 :

In your config.xml set the necessary permissions for the application. You will need READ_EXTERNAL_STORAGE (and also write if you are going to do this). I also add two plugins that are referenced below:

 <plugin name="cordova-plugin-device" source="npm" spec="1.1.6" /> <plugin name="cordova.plugins.diagnostic" spec="^3.7.1" /> <config-file platform="android" parent="/manifest" mode="replace"> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> </config-file> 

Then, preferably somewhere in your application’s start code (i.e., the device’s ready event handler), check the execution permissions and add them if necessary:

 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); }); } 
+8
source share
 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 

I have this for Angularjs. But I have problems with that. If you run this, you will find that the output is repeated more than once, when I call it, the promise is not working properly. but it works with a callback, but until the runtime returns, and there is no way to know when the full file walk has been completed.

+1
source share

All Articles