cordova-plugin-file icon indicating copy to clipboard operation
cordova-plugin-file copied to clipboard

Not seeing files that are stored on the Android device

Open artisanphil opened this issue 6 years ago • 16 comments

The issue has been described in this question: https://stackoverflow.com/questions/42490558/not-seeing-files-that-are-store-on-the-android-device-using-cordova-file-plugin

I'm facing the same issue and was only able to solve it by downgrading to Android API 22 as the author in the Stackoverflow question did.

When looping through all directories on the phone, it will only see files in the directory where the app is stored, but not files stored for example in the download folder of the SD Card.

This is my function:

 var localURLs    = [
      this.file.cacheDirectory,
      this.file.applicationDirectory,
      this.file.applicationStorageDirectory,
      this.file.dataDirectory,
      this.file.documentsDirectory,
      this.file.externalApplicationStorageDirectory,
      this.file.externalCacheDirectory,
      this.file.externalRootDirectory,
      this.file.externalDataDirectory,
      this.file.sharedDirectory,
      this.file.syncedDataDirectory
    ];
 loopThroughDirectories(localURLs, function(){
    });

function loopThroughDirectories(localURLs, callback) {
      for (i = 0; i < localURLs.length; i++) {

        console.log("directory: " + localURLs[i]);
        if(i == (localURLs.length - 1))
        {
          loading.dismiss();
          callback();
        }
        if (localURLs[i] === null || localURLs[i].length === 0) {
          continue; // skip blank / non-existent paths for this platform
        }
        window.resolveLocalFileSystemURL(localURLs[i], addFileEntry, addError);
      }
    }

var that = this;
    var addFileEntry = function (entry) {
      console.log("addFileEntry");
      var dirReader = entry.createReader();
      dirReader.readEntries(
        function (entries) {
          console.log("nr of entries: " + entries.length);
          var i;
          for (i = 0; i < entries.length; i++) {
            console.log(entries[i].fullPath);
            if (entries[i].isDirectory === true) {
              // Recursive -- call back into this subdirectory
              addFileEntry(entries[i]);
            } else {
              if(entries[i].fullPath.endsWith(".apkg") && entries[i].fullPath.search("/AnkiDroid/") == -1)
              {
                console.log(i + ": " + entries[i].fullPath);
                that.arrFiles.push({nr: i, fullPath: entries[i].fullPath, nativeURL: entries[i].nativeURL}); 
              }
            }
          }
        },
        function (error) {
          console.error("readEntries error: " + error.code);
        }
      );
    };

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

It's used in this project for finding all files on a phone with the apkg extension: https://github.com/phil4literacy/TeachMeWords

artisanphil avatar Aug 16 '18 08:08 artisanphil

So API level <= 22 could see all files, API level >22 can only see application files?

janpio avatar Aug 16 '18 08:08 janpio

Yes, mostly. For example with API 28 it found files here: file:///storage/emulated/0/Android/data/com.sil.teachmewords/files/

and also under the plugin folders:

/www/plugins/cordova-plugin-zip/ /www/plugins/cordova-plugin-file/www/browser/

but none under any of the folders that are not related to the app, e.g. /Download

artisanphil avatar Aug 16 '18 09:08 artisanphil

BTW, new apps created with API 22 are no longer allowed to be uploaded to Google Play, so I'm currently stuck...

artisanphil avatar Aug 16 '18 09:08 artisanphil

I am having the same issue.. Did you find a solution?

premtemp1 avatar Sep 30 '18 17:09 premtemp1

@premtemp1 : Sadly no. Still waiting and hoping somebody will work on fixing this. Looks like the plugin has been abandoned though, as if people no longer use files but do everything in the cloud... But apparently I'm not the only one who needs access to the filesystem.

artisanphil avatar Oct 01 '18 04:10 artisanphil

It has not been abandoned, there is just a pretty massive backlog of stuff in general regarding Cordova core plugins that has to be taken care of. I am currently working through all the testing issues for example: https://github.com/apache/cordova/issues/28

janpio avatar Oct 01 '18 08:10 janpio

@janpio : That's good to know. Thanks for all your hard work!

artisanphil avatar Oct 01 '18 09:10 artisanphil

8.1.2 ([email protected]), API level 27 android 5.0 is OK. android 8.1 dirReader.readEntries is not seeing files in directory.

sabrinetseng avatar Nov 06 '18 10:11 sabrinetseng

Hey all, has there been any movement on this? 6 months later I can confirm this is still an issue. I need to be able to access users files on both iOS and android, but I also need the ability to restrict by mime types and choose whether multi-select is enabled or not, depending on the scenario. There seems to be a lack of plugins that are able to do this, file-chooser and file-picker both seem to be limited to one file at a time. I have written a component in Ionic but obviously I need the android users folders to be accessible to be able to use it. Any information or work around to gain access to file.externalRootDirectory would be massively appreciated.

Thanks Marc

Edit: Looking into this further it is a permissions issue. If I also install the camera plugin and approve it's permissions to take a photo, I can then use my file manager component to access file.externalRootDirectory.

moridianmess avatar Feb 12 '19 15:02 moridianmess

Hi everybody,

Any news? I have exactly the same problem. I'm programming an hybrid Ionic 3 app, that works perfectly except in Android 9.0(API Level 28) that asks for permissions (and I accept) but when I try to access local files, the device returns no folders. In Android 8 and less there is no problem. I use cordova-file.

I will much appreciate if anyone could answer me.

Thanks in advance.

Yours faithfully,

GSDiama


`

cordova info

Collecting Data...

Node version: v8.11.3

Cordova version: 8.0.0

Config.xml file:

<widget android-versionCode="20003" id="com.XXXXXX.YYYYYYYY" version="2.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0 "> XXXX XXXXX Ionic Fr amework Team <icon height="120" src="resources/ios/icon/[email protected]" width="120" /

    <icon height="50" src="resources/ios/icon/icon-50.png" width="50" />
    <icon height="100" src="resources/ios/icon/[email protected]" width="100" /
    <icon height="60" src="resources/ios/icon/icon-60.png" width="60" />
    <icon height="120" src="resources/ios/icon/[email protected]" width="120" /
    <icon height="180" src="resources/ios/icon/[email protected]" width="180" /
    <icon height="72" src="resources/ios/icon/icon-72.png" width="72" />
    <icon height="144" src="resources/ios/icon/[email protected]" width="144" /
    <icon height="76" src="resources/ios/icon/icon-76.png" width="76" />
    <icon height="152" src="resources/ios/icon/[email protected]" width="152" /
    <icon height="167" src="resources/ios/icon/[email protected]" width="167"

/>

Plugins:

cordova-android-support-gradle-release,cordova-plugin-actionsheet,cordova-plugin -camera,cordova-plugin-device,cordova-plugin-fcm,cordova-plugin-file,cordova-plu gin-file-opener2,cordova-plugin-file-transfer,cordova-plugin-ionic-webview,cordo va-plugin-network-information,cordova-plugin-splashscreen,cordova-plugin-whiteli st,cordova-sqlite-storage,ionic-plugin-keyboard

Android platform:

Available Android targets:

id: 1 or "android-23" Name: Android 6.0 Type: Platform API level: 23 Revision: 3 Skins: HVGA, QVGA, WQVGA400, WQVGA432, WSVGA, WVGA800 (default), WVGA854, W XGA720, WXGA800, WXGA800-7in Tag/ABIs : no ABIs.

id: 2 or "android-24" Name: Android 7.0 Type: Platform API level: 24 Revision: 2 Skins: HVGA, QVGA, WQVGA400, WQVGA432, WSVGA, WVGA800 (default), WVGA854, W XGA720, WXGA800, WXGA800-7in Tag/ABIs : android-tv/x86, default/x86, default/x86_64

id: 3 or "android-25" Name: Android 7.1.1 Type: Platform API level: 25 Revision: 3 Skins: HVGA, QVGA, WQVGA400, WQVGA432, WSVGA, WVGA800 (default), WVGA854, W XGA720, WXGA800, WXGA800-7in Tag/ABIs : no ABIs.

id: 4 or "android-26" Name: Android 8.0.0 Type: Platform API level: 26 Revision: 2 Skins: HVGA, QVGA, WQVGA400, WQVGA432, WSVGA, WVGA800 (default), WVGA854, W XGA720, WXGA800, WXGA800-7in Tag/ABIs : no ABIs.

id: 5 or "android-27" Name: Android 8.1.0 Type: Platform API level: 27 Revision: 3 Skins: HVGA, QVGA, WQVGA400, WQVGA432, WSVGA, WVGA800 (default), WVGA854, W XGA720, WXGA800, WXGA800-7in Tag/ABIs : no ABIs.

id: 6 or "android-28" Name: Android 9 Type: Platform API level: 28 Revision: 6 Skins: HVGA, QVGA, WQVGA400, WQVGA432, WSVGA, WVGA800 (default), WVGA854, W XGA720, WXGA800, WXGA800-7in, AndroidWearRound, AndroidWearRound360x360, Android WearRound390x390, AndroidWearRound400x400, AndroidWearRound454x454, AndroidWearR ound480x480, AndroidWearRoundChin320x290, AndroidWearRoundChin320x300, AndroidWe arRoundChin360x325, AndroidWearRoundChin360x326, AndroidWearRoundChin360x330, An droidWearSquare, AndroidWearSquare240x240, AndroidWearSquare320x320 Tag/ABIs : android-wear/x86, google_apis_playstore/x86, google_apis_playstore/x 86_64

id: 7 or "android-Q" Name: Android 10 (Preview) Type: Platform API level: Q Revision: 3 Skins: HVGA, QVGA, WQVGA400, WQVGA432, WSVGA, WVGA800 (default), WVGA854, W XGA720, WXGA800, WXGA800-7in Tag/ABIs : google_apis_playstore/x86, google_apis_playstore/x86_64


ionic info

Ionic:

ionic (Ionic CLI) : 4.12.0 (C:\Users\jc\AppData\Roaming\npm\node_mod ules\ionic) Ionic Framework : ionic-angular 3.9.2 @ionic/app-scripts : 3.0.1

Cordova:

cordova (Cordova CLI) : not installed Cordova Platforms : android 6.4.0 Cordova Plugins : not available

System:

(C:\Program Files (x86)\Android\android-sdk) NodeJS : v8.11.3 (C:\Program Files\nodejs\node.exe) npm : 6.4.1 OS : Windows 7`

gsdiama avatar May 23 '19 08:05 gsdiama

I think I have got this working in initial testing.

I added <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> to the AndroidManifest.xml. I also added the cordova-plugin-android-permissions aswell. So I am not completely sure which one might have made it work.

I can now see the Downloads off of cordova.file.externalRootDirectory and when doing 'file:///sdcard' (device root internal directory for shared files) I can now see everything.

I am using API level 26 currently. I added a view from Chrome remote console.

Annotation 2020-01-15 154430

fragatak avatar Jan 15 '20 20:01 fragatak

It looks like the cordova-pluging-android-permissions is doing something the Manifest.xml is not checking for. I removed the permissions from the Manifest and did the checking via the pluging, everything works now.

fragatak avatar Jan 16 '20 22:01 fragatak

@fragatak how did you do the checking via the plugin. I am currently trying to store an image file as shown in the documentation, but like everyone else I am unable to locate the files created (as the code shows no error, i assume the works)

Zi1989 avatar Jan 19 '20 17:01 Zi1989

@Zi1989 did you find anything? The permissions plugin says that is has the PERMISSION.READ_EXTERNAL_STORAGE

bastifix avatar Aug 24 '20 23:08 bastifix

This is the code that is used with the app first starts up to check permission.

`function androidPermissions() { let permissions = cordova.plugins.permissions; let list = [ permissions.WRITE_EXTERNAL_STORAGE, permissions.READ_EXTERNAL_STORAGE ];

function error() {
    console.warn('External Read or Write permission is not turned on');
}

permissions.checkPermission(list, function (status) {
    if (!status.hasPermission) {
        permissions.requestPermissions(
        list,
        function(status) {
            if (!status.hasPermission) error();
        },
        error
        );
    }
}, null);

}

document.addEventListener("deviceready", androidPermissions, null);`

Just adding to the manifest.xml wasn't working so I ended up checking and requesting it directly for the user through the plugin.

and to read

`function Fail(evt) { console.log(evt.target.error.code); }

    function error(e)
    {
        console.error("error in " + e);
    }

    function readConfig(entry)
    {
        entry.file((file) =>
        {
            var reader = new FileReader();

            reader.onloadend = () =>
            {
                // do whatever you need to do for reading the file.
            };

            reader.readAsText(file);

        }, () =>
        {
            console.error("error loading config file.")
        });
    }

    let cordova = window.cordova || null;
    if (cordova)
    {
        document.addEventListener("deviceready", () =>
        {
            window.requestFileSystem(1, 0, null, Fail);
            window.resolveLocalFileSystemURL('file:///sdcard/{whatever file here]', readConfig.bind(this), error);
        });
    }`

You might have to startup android studio to see how the local file system looks for you.

fragatak avatar Aug 26 '20 20:08 fragatak

@fragatak thanks! I've the permissions for the storage, but the file content is just "null". Do you have any idea?

bastifix avatar Aug 28 '20 04:08 bastifix

With Android's Scoped Storage model (enforced in API 30 and later), the external storage is no longer discoverable. Some directories are simply not readable (they will give a File not Found error, even if they do exists, such as the externalRootDirectory), and other directories will only list files that have been created by your app, but not files created by other apps.

Closing as not a bug.

breautek avatar Dec 19 '22 03:12 breautek