apache / cordova-plugin-file

Apache Cordova File Plugin
https://cordova.apache.org/
Apache License 2.0
741 stars 756 forks source link

Not seeing files that are stored on the Android device #239

Closed artisanphil closed 1 year ago

artisanphil commented 5 years ago

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

janpio commented 5 years ago

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

artisanphil commented 5 years ago

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 commented 5 years ago

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

premtemp1 commented 5 years ago

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

artisanphil commented 5 years ago

@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.

janpio commented 5 years ago

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

artisanphil commented 5 years ago

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

sabrinetseng commented 5 years ago

8.1.2 (cordova-lib@8.1.1), API level 27 android 5.0 is OK. android 8.1 dirReader.readEntries is not seeing files in directory.

moridianmess commented 5 years ago

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.

gsdiama commented 5 years ago

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:

<?xml version='1.0' encoding='utf-8'?> <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
<description>XXXXX</description>
<author email="hi@ionicframework" href="http://ionicframework.com/">Ionic Fr

amework Team

<access origin="*" />
<allow-intent href="http://*/*" />
<allow-intent href="https://*/*" />
<allow-intent href="tel:*" />
<allow-intent href="sms:*" />
<allow-intent href="mailto:*" />
<allow-intent href="geo:*" />
<preference name="ScrollEnabled" value="false" />
<preference name="android-minSdkVersion" value="16" />
<preference name="BackupWebStorage" value="none" />
<preference name="SplashMaintainAspectRatio" value="true" />
<preference name="FadeSplashScreenDuration" value="300" />
<preference name="SplashShowOnlyFirstTime" value="false" />
<preference name="SplashScreen" value="screen" />
<preference name="SplashScreenDelay" value="3000" />
<preference name="loadUrlTimeoutValue" value="700000" />
<platform name="android">
    <allow-intent href="market:*" />
    <icon density="ldpi" src="resources/android/icon/drawable-ldpi-icon.png"

/> <icon density="mdpi" src="resources/android/icon/drawable-mdpi-icon.png" /> <icon density="hdpi" src="resources/android/icon/drawable-hdpi-icon.png" />

<plugin name="ionic-plugin-keyboard" spec="^2.2.1" />
<plugin name="cordova-plugin-whitelist" spec="^1.3.1" />
<plugin name="cordova-plugin-device" spec="^1.1.4" />
<plugin name="cordova-plugin-splashscreen" spec="^4.0.3" />
<plugin name="cordova-plugin-ionic-webview" spec="^1.1.16" />
<plugin name="cordova-sqlite-storage" spec="^2.0.4" />
<allow-navigation href="http://192.168.0.227:8100" />
<allow-navigation href="http://192.168.0.227:8101" />
<allow-navigation href="http://192.168.0.227:8102" />
<allow-navigation href="file://*/*" />
<allow-navigation href="*" />
<plugin name="cordova-plugin-actionsheet" spec="^2.3.3" />
<plugin name="cordova-plugin-camera" spec="^4.0.3" />
<plugin name="cordova-android-support-gradle-release" spec="^2.1.0">
    <variable name="ANDROID_SUPPORT_VERSION" value="27.+" />
</plugin>
<plugin name="cordova-plugin-file-transfer" spec="^1.7.1" />
<plugin name="cordova-plugin-file-opener2" spec="^2.2.0">
    <variable name="ANDROID_SUPPORT_V4_VERSION" value="27.+" />
</plugin>
<engine name="android" spec="^6.4.0" />

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`

fragatak commented 4 years ago

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 commented 4 years ago

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.

Zi1989 commented 4 years ago

@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)

bastifix commented 3 years ago

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

fragatak commented 3 years ago

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.

bastifix commented 3 years ago

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

breautek commented 1 year ago

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.