Unable to access external sd card on Android

586 Views Asked by At

I have easily accessed Internal Storage Files using

File internalStorage = new File( Environment.getExternalStorageDirectory().getAbsolutePath() );     
internalStorage.listFiles();

And i am getting all the files. But i am unable to get any file from my mounted sd-card. i have checked. if SD-Card is mounted

boolean isSdCard = android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED);

And i have also tried different solutions like.

File sdCardFolder = new File(System.getenv("SECONDARY_STORAGE"));   
//RESULT.    
sdCardFolder.getName() //sdcard0.   
sdCardFolder.listFile() //null.

Here it's giving the folder name but sending null for listFile.

And also i have tried different other methods to listFiles from my SD Card but unable to find a working one.

in build.gradle.

compileSdkVersion 31.    
targetSdkVersion 31
3

There are 3 best solutions below

1
Rachid Le Laborantin On

Check and ask for permission to access external cards in your manifest or by code

0
Saqib Rehman On

After a lot of research and time consumed, I finally got a solution for my question. There are plenty of questions asking for the same problem, but not any relevant and working solution is available, up-till my exposure.

I am answering my own question to help others facing the same problem. I have used the following code to get the path of SD card. And then I accessed it normally as I had accessed the internal storage of the Android device.

// The following function will return the path of the SD card
// or NULL, if no SD card is mounted.

public static String getExternalStoragePath(Context mContext, boolean is_removable) {

    StorageManager mStorageManager = 
        (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE);
    Class<?> storageVolumeClazz = null;
    try {
        storageVolumeClazz = Class.forName("android.os.storage.StorageVolume");
        Method getVolumeList = mStorageManager.getClass().getMethod("getVolumeList");
        Method getPath = storageVolumeClazz.getMethod("getPath");
        Method isRemovable = storageVolumeClazz.getMethod("isRemovable");
        Object result = getVolumeList.invoke(mStorageManager);
        final int length = Array.getLength(result);
        for (int i = 0; i < length; i++) {
            Object storageVolumeElement = Array.get(result, i);
            String path = (String) getPath.invoke(storageVolumeElement);
            boolean removable = (Boolean) isRemovable.invoke(storageVolumeElement);
            if (is_removable == removable) {
                return path;
            }
        }
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
    return null;
}
0
ScryptX On

To add on to @Saqib's answer, I've simplified the code by removing the need to use his helper/wrapper class.

 StorageManager storageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
 List<StorageVolume> storageArray = storageManager.getStorageVolumes();
 String path = "";
 for (StorageVolume item : storageArray)
     if (item.isRemovable())
           if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
                path = item.getDirectory().getPath();

To handle null case, simply check if the path string is empty or null and handle that appropriately.