Skip to content

Instantly share code, notes, and snippets.

@PauloLuan
Last active October 31, 2022 07:02
Show Gist options
  • Save PauloLuan/4bcecc086095bce28e22 to your computer and use it in GitHub Desktop.
Save PauloLuan/4bcecc086095bce28e22 to your computer and use it in GitHub Desktop.
how to get the external sd card path on android.
public static String getExternalSdCardPath() {
String path = null;
File sdCardFile = null;
List<String> sdCardPossiblePath = Arrays.asList("external_sd", "ext_sd", "external", "extSdCard");
for (String sdPath : sdCardPossiblePath) {
File file = new File("/mnt/", sdPath);
if (file.isDirectory() && file.canWrite()) {
path = file.getAbsolutePath();
String timeStamp = new SimpleDateFormat("ddMMyyyy_HHmmss").format(new Date());
File testWritable = new File(path, "test_" + timeStamp);
if (testWritable.mkdirs()) {
testWritable.delete();
}
else {
path = null;
}
}
}
if (path != null) {
sdCardFile = new File(path);
}
else {
sdCardFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath());
}
return sdCardFile.getAbsolutePath();
}
@JoeCodeswell
Copy link

Thanks, @lovelyelfpop this worked on my Samsung SM-T320 running Android version 4.4.2.

  1. I followed get Context in non-Activity class [duplicate] to get the context into my Util class from the MainActivity.
  2. Here's some things I imported. there might have been a couple more.
import android.os.storage.StorageManager;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

Thanks again. This worked like a champ

Copy link

ghost commented Nov 10, 2020

@lovelyelfpop Thank you, very much

@Alkwin
Copy link

Alkwin commented Feb 14, 2022

Hi,

After Android Q, the method getPath cannot be called through reflection.

For me, the following code works. Tested on around 6-7 devices, ranging from Android 4.3 up to Android 12.

private fun getExternalCardDirectory(): String {
        val storageManager = context.getSystemService(Context.STORAGE_SERVICE)
        try {
            val storageVolumeClassReflection = Class.forName("android.os.storage.StorageVolume")
            val getVolumeList = storageManager.javaClass.getMethod("getVolumeList")
            val getPath = if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                storageVolumeClassReflection.getMethod("getDirectory")
            } else {
                storageVolumeClassReflection.getMethod("getPath")
            }
            val isRemovable = storageVolumeClassReflection.getMethod("isRemovable")
            val result = getVolumeList.invoke(storageManager) as Array<StorageVolume>
            result.forEach {
                if (isRemovable.invoke(it) as Boolean) {
                    return when(val invokeResult = getPath.invoke(it)) {
                        is File -> invokeResult.absolutePath

                        is String -> invokeResult

                        else -> DEFAULT_VALUE.also {
                            log.debug { "Reflection unsupported type; Invoke result: $invokeResult" }
                        }
                    }
                }
            }
        } catch (e: Throwable) {
            log.debug { "Could not get SD card path; Exception: $e" }
        }
        return DEFAULT_VALUE
    }

With DEFAULT_VALUE = "N/A"
Credit @lovelyelfpop

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment