8

I am writing an application that should upload pictures taken by the camera which are stored in the DCIM/Camera folder on both internal memory and SD card.

This means that before every upload all available storages have to be checked for presence of any images.

I use Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) to access the primary storage, which can be either SD card or internal memory (depends on device).

From documentation:

Note: don't be confused by the word "external" here. This directory can better be thought as media/shared storage. It is a filesystem that can hold a relatively large amount of data and that is shared across all applications (does not enforce permissions). Traditionally this is an SD card, but it may also be implemented as built-in storage in a device that is distinct from the protected internal storage and can be mounted as a filesystem on a computer.

My question is, how can I access the secondary storage to check for presence of images in the DCIM/Camera folder without hard-coding the path, which does not work well since the SD card might be emulated in different path.

rds
  • 26,253
  • 19
  • 107
  • 134
Adam
  • 1,054
  • 1
  • 12
  • 26
  • Access is as always the same. Independend from the path. I think what you want instead is finding out paths to DCIM folders on external and removable media. – greenapps Apr 11 '15 at 09:35

6 Answers6

5

Try this code for choosing the last used DCIM/Camera folder.

String getDCIMCamera() {
    try {
        String[] projection = new String[]{
                MediaStore.Images.ImageColumns._ID,
                MediaStore.Images.ImageColumns.DATA,
                MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME,
                MediaStore.Images.ImageColumns.DATE_TAKEN,
                MediaStore.Images.ImageColumns.MIME_TYPE};

        Cursor cursor = getContentResolver().query(
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                projection,
                null,
                null,
                MediaStore.Images.ImageColumns.DATE_TAKEN + " DESC");
        if (cursor != null) {
            cursor.moveToFirst();
            do {
                String path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
                if (path.contains("/DCIM/")) {
                    File file = new File(path);
                    path = file.getParent();
                    cursor.close();
                    return path;
                }
            } while (cursor.moveToNext());
            cursor.close();
        }
    }
    catch (Exception e) {
    }
    return "";
}

See also @Pedram tips: https://stackoverflow.com/a/24189813/966789

Alexander Lubyagin
  • 1,346
  • 1
  • 16
  • 30
2

Try

File[] aDirArray = ContextCompat.getExternalFilesDirs(context, null);

See http://developer.android.com/reference/android/support/v4/content/ContextCompat.html#getExternalFilesDirs(android.content.Context, java.lang.String)

Remember that external storage (SD Card) is not emulated and all paths are visible to all users.

Return Value

  • null - In case of failure
  • Root path (File) of each mounted external storage.

So if aDirArray.length > 1, then the following gets you the DCIM path you are looking for on the removable storage.

File aExtDcimDir = new File(aDirArray[1], Environment.DIRECTORY_DCIM);

Maybe in your case, you want to check aDirArray[0], aDirArray[1], ... (all Files returned in the array) for the presence of Environment.DIRECTORY_DCIM.

user924
  • 8,146
  • 7
  • 57
  • 139
Dave Truby
  • 193
  • 1
  • 5
  • Sadly getExternalFilesDirs only returns one item on many KitKat devices. The same as returned by getExternalFileDir(). `external storage (SD Card) `. No. A micro SD card is removable storage. The external storage has nothing to do with it. – greenapps Apr 12 '15 at 16:58
  • As you stated at the end of your answer, it is different paths i tested on my phone(Lollipop). new File(aDirArray[0], Environment.DIRECTORY_DCIM).toString(); will return "/storage/sdcard0/Android/data/com.myapp.something/files/DCIM". While Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_DCIM).toString(); will return "/storage/sdcard0/DCIM" – HendraWD Mar 11 '16 at 08:45
  • `ContextCompat.getExternalFilesDirs` has nothing to do with public media folders like DCIM, please check https://stackoverflow.com/questions/68808504/mediastore-alternative-for-deprecated-context-externalmediadirs – user924 Aug 16 '21 at 20:48
  • and `Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)` IS NOT THE SAME AS `File(aDirArray[0], Environment.DIRECTORY_DCIM)`!!! – user924 Aug 16 '21 at 20:51
2

getExternalStorageDirectory retrieves only from internal storage data but not secondary storage images

This is the way we are getting secondary storage images from android or any folder accessing from secondary storage this is the code......

String secStore = System.getenv("SECONDARY_STORAGE");
File file = new File(secStore + "/DCIM");
File[] listFiles = file.listFiles();
sqluser
  • 5,502
  • 7
  • 36
  • 50
sivabrahma
  • 39
  • 2
  • it is error on my device, the file.toString(); will produce "/storage/extSdCard:/storage/UsbDriveA:/storage/UsbDriveB:/storage/UsbDriveC:/storage/UsbDriveD:/storage/UsbDriveE:/storage/UsbDriveF/DCIM" – HendraWD Mar 11 '16 at 08:39
  • File[] aDirArray = ContextCompat.getExternalFilesDirs(MyService.this, null); File path = new File(String.valueOf(aDirArray[z]), Environment.DIRECTORY_DCIM); String data = path.toString(); int index = data.indexOf("Android"); String subdata = data.substring(0, index); File sec = new File(subdata + "DCIM"); File[] dataFiles = sec.listFiles(); – sivabrahma May 31 '16 at 09:06
1
File[] aDirArray = ContextCompat.getExternalFilesDirs(SDCardExample.this, null);
        File path = new File(aDirArray[1], Environment.DIRECTORY_DCIM);
        String data=path.toString();
        int index=data.indexOf("Android");
        String subdata=data.substring(0,index);
        File sec=new File(subdata+"DCIM/Camera");
        File[] secs=sec.listFiles();

sivabrahma
  • 39
  • 2
0
File[] aDirArray = ContextCompat.getExternalFilesDirs(MainActivity.this, null);
File path = new File(aDirArray.length>1?aDirArray[1]:aDirArray[0], Environment.DIRECTORY_DCIM);

like Dave Truby wrote

Shimon Doodkin
  • 4,310
  • 34
  • 37
0

Here is the solution. Try it...

First get all files in a list

var file=new Java.IO.File("storage/");
var listOfStorages=file.ListFiles();

var isSDPresent=false;
if(listOfStorages[1].Name.Containes("emulated")||listOfStorages[0].Name.Containes("-"))
{
   isSDPresent=true;
   var sdCardName=listOfStorages[0].Name;
}

It works.

Greenonline
  • 1,330
  • 8
  • 23
  • 31
Uttam Suthar
  • 106
  • 6