Encuentra una ubicación de tarjeta SD externa

¿Hay una forma universal de encontrar la ubicación de una tarjeta SD externa?

Por favor, no se confunda con almacenamiento externo . Environment.getExternalStorageState() devuelve la ruta al punto de assembly SD interno como “/ mnt / sdcard”. Pero la pregunta es sobre SD externo. ¿Cómo obtener una ruta como “/ mnt / sdcard / external_sd” (puede variar de un dispositivo a otro)?

Supongo que terminaré con el filtrado del comando mount por nombre del sistema de archivos. Pero no estoy seguro de que este camino sea lo suficientemente robusto.

Environment.getExternalStorageState() devuelve la ruta al punto de assembly SD interno como “/ mnt / sdcard”

No, Environment.getExternalStorageDirectory() refiere a cualquier cosa que el fabricante del dispositivo considere como “almacenamiento externo”. En algunos dispositivos, este es un medio extraíble, como una tarjeta SD. En algunos dispositivos, esta es una porción del flash en el dispositivo. Aquí, “almacenamiento externo” significa “lo que se puede acceder a través del modo de almacenamiento masivo USB cuando está montado en una máquina host”, al menos para Android 1.xy 2.x.

Pero la pregunta es sobre SD externo. ¿Cómo obtener una ruta como “/ mnt / sdcard / external_sd” (puede variar de un dispositivo a otro)?

Android no tiene ningún concepto de “SD externa”, aparte del almacenamiento externo, como se describió anteriormente.

Si el fabricante de un dispositivo ha elegido que el almacenamiento externo esté a bordo del flash y también tenga una tarjeta SD, deberá ponerse en contacto con ese fabricante para determinar si puede usar o no la tarjeta SD (no se garantiza) y para qué sirven las reglas. usándolo, como qué camino usar para ello.


ACTUALIZAR

Dos cosas recientes de la nota:

En primer lugar, en Android 4.4+, no tiene acceso de escritura a medios extraíbles (por ejemplo, “SD externa”), a excepción de cualquier ubicación en ese medio que getExternalFilesDirs() y getExternalCacheDirs() . Vea el excelente análisis de Dave Smith sobre esto, particularmente si desea los detalles de bajo nivel.

En segundo lugar, para que nadie discuta si el acceso a medios extraíbles forma parte o no del SDK de Android, aquí está la evaluación de Dianne Hackborn :

… tenga en cuenta: hasta Android 4.4, la plataforma oficial de Android no admite tarjetas SD, excepto dos casos especiales: el diseño de almacenamiento de la vieja escuela donde el almacenamiento externo es una tarjeta SD (que todavía es compatible con la plataforma) , y una pequeña característica agregada a Android 3.0 en la que escanearía tarjetas SD adicionales y las agregaría al proveedor de medios, y les daría a las aplicaciones acceso de solo lectura a sus archivos (que también es compatible con la plataforma actual).

Android 4.4 es el primer lanzamiento de la plataforma que ha permitido que las aplicaciones usen tarjetas SD para almacenamiento. Cualquier acceso a ellos antes era a través de API privadas y no compatibles. Ahora contamos con una API bastante rica en la plataforma que permite a las aplicaciones hacer uso de las tarjetas SD de una manera compatible, en mejores formas que lo han podido hacerlo anteriormente: pueden hacer uso gratuito de su área de almacenamiento específica de la aplicación sin necesidad de permisos en la aplicación, y puede acceder a cualquier otro archivo en la tarjeta SD, siempre y cuando pasen por el selector de archivos, nuevamente sin necesitar ningún permiso especial.

Se me ocurrió la siguiente solución basada en algunas respuestas que se encuentran aquí.

CÓDIGO:

 public class ExternalStorage { public static final String SD_CARD = "sdCard"; public static final String EXTERNAL_SD_CARD = "externalSdCard"; /** * @return True if the external storage is available. False otherwise. */ public static boolean isAvailable() { String state = Environment.getExternalStorageState(); if (Environment.MEDIA_MOUNTED.equals(state) || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) { return true; } return false; } public static String getSdCardPath() { return Environment.getExternalStorageDirectory().getPath() + "/"; } /** * @return True if the external storage is writable. False otherwise. */ public static boolean isWritable() { String state = Environment.getExternalStorageState(); if (Environment.MEDIA_MOUNTED.equals(state)) { return true; } return false; } /** * @return A map of all storage locations available */ public static Map getAllStorageLocations() { Map map = new HashMap(10); List mMounts = new ArrayList(10); List mVold = new ArrayList(10); mMounts.add("/mnt/sdcard"); mVold.add("/mnt/sdcard"); try { File mountFile = new File("/proc/mounts"); if(mountFile.exists()){ Scanner scanner = new Scanner(mountFile); while (scanner.hasNext()) { String line = scanner.nextLine(); if (line.startsWith("/dev/block/vold/")) { String[] lineElements = line.split(" "); String element = lineElements[1]; // don't add the default mount path // it's already in the list. if (!element.equals("/mnt/sdcard")) mMounts.add(element); } } } } catch (Exception e) { e.printStackTrace(); } try { File voldFile = new File("/system/etc/vold.fstab"); if(voldFile.exists()){ Scanner scanner = new Scanner(voldFile); while (scanner.hasNext()) { String line = scanner.nextLine(); if (line.startsWith("dev_mount")) { String[] lineElements = line.split(" "); String element = lineElements[2]; if (element.contains(":")) element = element.substring(0, element.indexOf(":")); if (!element.equals("/mnt/sdcard")) mVold.add(element); } } } } catch (Exception e) { e.printStackTrace(); } for (int i = 0; i < mMounts.size(); i++) { String mount = mMounts.get(i); if (!mVold.contains(mount)) mMounts.remove(i--); } mVold.clear(); List mountHash = new ArrayList(10); for(String mount : mMounts){ File root = new File(mount); if (root.exists() && root.isDirectory() && root.canWrite()) { File[] list = root.listFiles(); String hash = "["; if(list!=null){ for(File f : list){ hash += f.getName().hashCode()+":"+f.length()+", "; } } hash += "]"; if(!mountHash.contains(hash)){ String key = SD_CARD + "_" + map.size(); if (map.size() == 0) { key = SD_CARD; } else if (map.size() == 1) { key = EXTERNAL_SD_CARD; } mountHash.add(hash); map.put(key, root); } } } mMounts.clear(); if(map.isEmpty()){ map.put(SD_CARD, Environment.getExternalStorageDirectory()); } return map; } } 

USO:

 Map externalLocations = ExternalStorage.getAllStorageLocations(); File sdCard = externalLocations.get(ExternalStorage.SD_CARD); File externalSdCard = externalLocations.get(ExternalStorage.EXTERNAL_SD_CARD); 

Tenía una aplicación que usaba una ListPreference donde el usuario debía seleccionar la ubicación donde deseaba guardar algo. En esa aplicación, escaneé / proc / mounts y /system/etc/vold.fstab para los puntos de assembly de la tarjeta SD. Guarde los puntos de assembly de cada archivo en dos ArrayList s separados.

Luego, comparé una lista con la otra y descarté los elementos que no estaban en ambas listas. Eso me dio una lista de rutas de acceso a cada tarjeta SD.

A partir de ahí, probé las rutas con File.exists() , File.isDirectory() y File.canWrite() . Si alguna de esas pruebas fuera falsa, descarté esa ruta de la lista.

Lo que quedaba en la lista, lo convertí en una matriz String[] para que pudiera ser utilizado por el ListPreference valores ListPreference .

Puede ver el código aquí: http://sapienmobile.com/?p=204

Para recuperar todos los almacenes externos (ya sean tarjetas SD o almacenes internos no extraíbles ), puede usar el siguiente código:

 final String state = Environment.getExternalStorageState(); if ( Environment.MEDIA_MOUNTED.equals(state) || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state) ) { // we can read the External Storage... //Retrieve the primary External Storage: final File primaryExternalStorage = Environment.getExternalStorageDirectory(); //Retrieve the External Storages root directory: final String externalStorageRootDir; if ( (externalStorageRootDir = primaryExternalStorage.getParent()) == null ) { // no parent... Log.d(TAG, "External Storage: " + primaryExternalStorage + "\n"); } else { final File externalStorageRoot = new File( externalStorageRootDir ); final File[] files = externalStorageRoot.listFiles(); for ( final File file : files ) { if ( file.isDirectory() && file.canRead() && (file.listFiles().length > 0) ) { // it is a real directory (not a USB drive)... Log.d(TAG, "External Storage: " + file.getAbsolutePath() + "\n"); } } } } 

Alternativamente, puede usar System.getenv (“EXTERNAL_STORAGE”) para recuperar el directorio primario de almacenamiento externo (por ejemplo, “/ storage / sdcard0” ) y System.getenv (“SECONDARY_STORAGE”) para recuperar la lista de todos los directorios secundarios (por ejemplo, ” / storage / extSdCard: / storage / UsbDriveA: / storage / UsbDriveB “ ). Recuerde que, también en este caso, es posible que desee filtrar la lista de directorios secundarios para excluir las unidades USB.

En cualquier caso, tenga en cuenta que el uso de rutas codificadas es siempre un mal enfoque (especialmente cuando cada fabricante puede cambiarlo como corresponde).

Puede intentar utilizar la función de biblioteca de soporte llamada ContextCompat.getExternalFilesDirs () :

  final File[] appsDir=ContextCompat.getExternalFilesDirs(getActivity(),null); final ArrayList extRootPaths=new ArrayList<>(); for(final File file : appsDir) extRootPaths.add(file.getParentFile().getParentFile().getParentFile().getParentFile()); 

El primero es el almacenamiento externo primario, y el rest se supone que son rutas reales de tarjetas SD.

La razón para el múltiple “.getParentFile ()” es ir a otra carpeta, ya que la ruta original es

 .../Android/data/YOUR_APP_PACKAGE_NAME/files/ 

EDITAR: esta es una forma más completa que he creado, para obtener las rutas de tarjetas SD:

  /** * returns a list of all available sd cards paths, or null if not found. * * @param includePrimaryExternalStorage set to true if you wish to also include the path of the primary external storage */ @TargetApi(Build.VERSION_CODES.HONEYCOMB) public static List getSdCardPaths(final Context context, final boolean includePrimaryExternalStorage) { final File[] externalCacheDirs=ContextCompat.getExternalCacheDirs(context); if(externalCacheDirs==null||externalCacheDirs.length==0) return null; if(externalCacheDirs.length==1) { if(externalCacheDirs[0]==null) return null; final String storageState=EnvironmentCompat.getStorageState(externalCacheDirs[0]); if(!Environment.MEDIA_MOUNTED.equals(storageState)) return null; if(!includePrimaryExternalStorage&&VERSION.SDK_INT>=VERSION_CODES.HONEYCOMB&&Environment.isExternalStorageEmulated()) return null; } final List result=new ArrayList<>(); if(includePrimaryExternalStorage||externalCacheDirs.length==1) result.add(getRootOfInnerSdCardFolder(externalCacheDirs[0])); for(int i=1;i 

Al igual que Richard, también uso el archivo / proc / mounts para obtener la lista de opciones de almacenamiento disponibles

 public class StorageUtils { private static final String TAG = "StorageUtils"; public static class StorageInfo { public final String path; public final boolean internal; public final boolean readonly; public final int display_number; StorageInfo(String path, boolean internal, boolean readonly, int display_number) { this.path = path; this.internal = internal; this.readonly = readonly; this.display_number = display_number; } public String getDisplayName() { StringBuilder res = new StringBuilder(); if (internal) { res.append("Internal SD card"); } else if (display_number > 1) { res.append("SD card " + display_number); } else { res.append("SD card"); } if (readonly) { res.append(" (Read only)"); } return res.toString(); } } public static List getStorageList() { List list = new ArrayList(); String def_path = Environment.getExternalStorageDirectory().getPath(); boolean def_path_internal = !Environment.isExternalStorageRemovable(); String def_path_state = Environment.getExternalStorageState(); boolean def_path_available = def_path_state.equals(Environment.MEDIA_MOUNTED) || def_path_state.equals(Environment.MEDIA_MOUNTED_READ_ONLY); boolean def_path_readonly = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED_READ_ONLY); BufferedReader buf_reader = null; try { HashSet paths = new HashSet(); buf_reader = new BufferedReader(new FileReader("/proc/mounts")); String line; int cur_display_number = 1; Log.d(TAG, "/proc/mounts"); while ((line = buf_reader.readLine()) != null) { Log.d(TAG, line); if (line.contains("vfat") || line.contains("/mnt")) { StringTokenizer tokens = new StringTokenizer(line, " "); String unused = tokens.nextToken(); //device String mount_point = tokens.nextToken(); //mount point if (paths.contains(mount_point)) { continue; } unused = tokens.nextToken(); //file system List flags = Arrays.asList(tokens.nextToken().split(",")); //flags boolean readonly = flags.contains("ro"); if (mount_point.equals(def_path)) { paths.add(def_path); list.add(0, new StorageInfo(def_path, def_path_internal, readonly, -1)); } else if (line.contains("/dev/block/vold")) { if (!line.contains("/mnt/secure") && !line.contains("/mnt/asec") && !line.contains("/mnt/obb") && !line.contains("/dev/mapper") && !line.contains("tmpfs")) { paths.add(mount_point); list.add(new StorageInfo(mount_point, false, readonly, cur_display_number++)); } } } } if (!paths.contains(def_path) && def_path_available) { list.add(0, new StorageInfo(def_path, def_path_internal, def_path_readonly, -1)); } } catch (FileNotFoundException ex) { ex.printStackTrace(); } catch (IOException ex) { ex.printStackTrace(); } finally { if (buf_reader != null) { try { buf_reader.close(); } catch (IOException ex) {} } } return list; } } 

Es posible encontrar dónde se montan las tarjetas SD adicionales leyendo /proc/mounts (archivo estándar de Linux) y comprobando de forma cruzada los datos /system/etc/vold.conf ( /system/etc/vold.conf ). Y tenga en cuenta que la ubicación devuelta por Environment.getExternalStorageDirectory() puede no aparecer en la configuración vold (en algunos dispositivos es un almacenamiento interno que no se puede desmontar), pero aún debe incluirse en la lista. Sin embargo, no encontramos una buena manera de describirlos al usuario .

Intento todas las soluciones dentro de este tema en este momento. Pero ninguno de ellos funcionó correctamente en dispositivos con una tarjeta externa (extraíble) y una interna (no extraíble). La ruta de la tarjeta externa no es posible desde el comando ‘mount’, desde el archivo ‘proc / mounts’, etc.

Y creo mi propia solución (en la de Paulo Luan):

 String sSDpath = null; File fileCur = null; for( String sPathCur : Arrays.asList( "ext_card", "external_sd", "ext_sd", "external", "extSdCard", "externalSdCard")) // external sdcard { fileCur = new File( "/mnt/", sPathCur); if( fileCur.isDirectory() && fileCur.canWrite()) { sSDpath = fileCur.getAbsolutePath(); break; } } fileCur = null; if( sSDpath == null) sSDpath = Environment.getExternalStorageDirectory().getAbsolutePath(); 

Simplemente usa esto:

 String primary_sd = System.getenv("EXTERNAL_STORAGE"); if(primary_sd != null) Log.i("EXTERNAL_STORAGE", primary_sd); String secondary_sd = System.getenv("SECONDARY_STORAGE"); if(secondary_sd != null) Log.i("SECONDARY_STORAGE", secondary_sd) 

Si observas el código fuente de android.os.Environment , verás que Android depende en gran medida de las variables de entorno para las rutas. Puede usar la variable de entorno “SECONDARY_STORAGE” para encontrar la ruta a la tarjeta sd extraíble.

 /** * Get a file using an environmental variable. * * @param variableName * The Environment variable name. * @param paths * Any paths to the file if the Environment variable was not found. * @return the File or {@code null} if the File could not be located. */ private static File getDirectory(String variableName, String... paths) { String path = System.getenv(variableName); if (!TextUtils.isEmpty(path)) { if (path.contains(":")) { for (String _path : path.split(":")) { File file = new File(_path); if (file.exists()) { return file; } } } else { File file = new File(path); if (file.exists()) { return file; } } } if (paths != null && paths.length > 0) { for (String _path : paths) { File file = new File(_path); if (file.exists()) { return file; } } } return null; } 

Ejemplo de uso:

 public static final File REMOVABLE_STORAGE = getDirectory("SECONDARY_STORAGE"); 

Esta es la forma en que uso para encontrar la tarjeta externa. Utilice mount cmd return y luego analice la parte vfat.

 String s = ""; try { Process process = new ProcessBuilder().command("mount") .redirectErrorStream(true).start(); process.waitFor(); InputStream is = process.getInputStream(); byte[] buffer = new byte[1024]; while (is.read(buffer) != -1) { s = s + new String(buffer); } is.close(); } catch (Exception e) { e.printStackTrace(); } //用行分隔mount列表String[] lines = s.split("\n"); for(int i=0; i 

¿Hay una forma universal de encontrar la ubicación de una tarjeta SD externa?

De forma universal , si te refieres a la forma oficial; sí hay una.

En el nivel API 19, es decir, en la versión 4.4 de Android Kitkat, han agregado File[] getExternalFilesDirs (String type) en la clase Context que permite que las aplicaciones almacenen datos / archivos en tarjetas micro SD.

Android 4.4 es el primer lanzamiento de la plataforma que ha permitido que las aplicaciones usen tarjetas SD para almacenamiento. Cualquier acceso a tarjetas SD antes del nivel 19 de la API se realizó a través de API privadas y no compatibles.

getExternalFilesDirs (tipo de cadena) devuelve rutas absolutas a directorios específicos de la aplicación en todos los dispositivos de almacenamiento compartidos / externos. Significa que devolverá rutas a la memoria interna y externa. Generalmente, la segunda ruta devuelta sería la ruta de almacenamiento para la tarjeta microSD (si corresponde).

Pero ten en cuenta que

El almacenamiento compartido puede no estar siempre disponible, ya que el usuario puede expulsar el medio extraíble. El estado del medio se puede verificar usando getExternalStorageState(File) .

No se aplica seguridad con estos archivos. Por ejemplo, cualquier aplicación que tenga WRITE_EXTERNAL_STORAGE puede escribir en estos archivos.

La terminología de almacenamiento interno y externo según Google / documentos oficiales de Android es bastante diferente de lo que pensamos.

Esta solución maneja el hecho de que System.getenv("SECONDARY_STORAGE") no sirve para Marshmallow.

Probado y trabajando en:

  • Samsung Galaxy Tab 2 (Android 4.1.1 – archivo)
  • Samsung Galaxy Note 8.0 (Android 4.2.2 – archivo)
  • Samsung Galaxy S4 (Android 4.4 – Stock)
  • Samsung Galaxy S4 (Android 5.1.1 – Cyanogenmod)
  • Samsung Galaxy Tab A (Android 6.0.1 – archivo)

     /** * Returns all available external SD-Card roots in the system. * * @return paths to all available external SD-Card roots in the system. */ public static String[] getStorageDirectories() { String [] storageDirectories; String rawSecondaryStoragesStr = System.getenv("SECONDARY_STORAGE"); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { List results = new ArrayList(); File[] externalDirs = applicationContext.getExternalFilesDirs(null); for (File file : externalDirs) { String path = file.getPath().split("/Android")[0]; if((Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && Environment.isExternalStorageRemovable(file)) || rawSecondaryStoragesStr != null && rawSecondaryStoragesStr.contains(path)){ results.add(path); } } storageDirectories = results.toArray(new String[0]); }else{ final Set rv = new HashSet(); if (!TextUtils.isEmpty(rawSecondaryStoragesStr)) { final String[] rawSecondaryStorages = rawSecondaryStoragesStr.split(File.pathSeparator); Collections.addAll(rv, rawSecondaryStorages); } storageDirectories = rv.toArray(new String[rv.size()]); } return storageDirectories; } 

Desde mi respuesta original anterior, escanear vold ya no es viable en los distintos fabricantes.

Desarrollé un método más confiable y directo.

 File mnt = new File("/storage"); if (!mnt.exists()) mnt = new File("/mnt"); File[] roots = mnt.listFiles(new FileFilter() { @Override public boolean accept(File pathname) { return pathname.isDirectory() && pathname.exists() && pathname.canWrite() && !pathname.isHidden() && !isSymlink(pathname); } }); 

roots contendrá todos los directorios raíz grabables en el sistema, incluyendo cualquier dispositivo usb conectado.

NOTA: El método canWrite necesita el permiso android.permission.WRITE_EXTERNAL_STORAGE.

Ha sido tan tarde, pero finalmente obtuve algo que he probado la mayoría de los dispositivos (por fabricante y las versiones de Android) funciona en Android 2.2+. Si encuentra que no funciona, coméntelo con el nombre de su dispositivo. yo lo arreglare. si alguien está interesado, explicaré cómo funciona.

 import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStreamReader; import android.util.Log; /** * @author ajeet *05-Dec-2014 2014 * */ public class StorageUtil { public boolean isRemovebleSDCardMounted() { File file = new File("/sys/class/block/"); File[] files = file.listFiles(new MmcblkFilter("mmcblk\\d$")); boolean flag = false; for (File mmcfile : files) { File scrfile = new File(mmcfile, "device/scr"); if (scrfile.exists()) { flag = true; break; } } return flag; } public String getRemovebleSDCardPath() throws IOException { String sdpath = null; File file = new File("/sys/class/block/"); File[] files = file.listFiles(new MmcblkFilter("mmcblk\\d$")); String sdcardDevfile = null; for (File mmcfile : files) { Log.d("SDCARD", mmcfile.getAbsolutePath()); File scrfile = new File(mmcfile, "device/scr"); if (scrfile.exists()) { sdcardDevfile = mmcfile.getName(); Log.d("SDCARD", mmcfile.getName()); break; } } if (sdcardDevfile == null) { return null; } FileInputStream is; BufferedReader reader; files = file.listFiles(new MmcblkFilter(sdcardDevfile + "p\\d+")); String deviceName = null; if (files.length > 0) { Log.d("SDCARD", files[0].getAbsolutePath()); File devfile = new File(files[0], "dev"); if (devfile.exists()) { FileInputStream fis = new FileInputStream(devfile); reader = new BufferedReader(new InputStreamReader(fis)); String line = reader.readLine(); deviceName = line; } Log.d("SDCARD", "" + deviceName); if (deviceName == null) { return null; } Log.d("SDCARD", deviceName); final File mountFile = new File("/proc/self/mountinfo"); if (mountFile.exists()) { is = new FileInputStream(mountFile); reader = new BufferedReader(new InputStreamReader(is)); String line = null; while ((line = reader.readLine()) != null) { // Log.d("SDCARD", line); // line = reader.readLine(); // Log.d("SDCARD", line); String[] mPonts = line.split("\\s+"); if (mPonts.length > 6) { if (mPonts[2].trim().equalsIgnoreCase(deviceName)) { if (mPonts[4].contains(".android_secure") || mPonts[4].contains("asec")) { continue; } sdpath = mPonts[4]; Log.d("SDCARD", mPonts[4]); } } } } } return sdpath; } static class MmcblkFilter implements FilenameFilter { private String pattern; public MmcblkFilter(String pattern) { this.pattern = pattern; } @Override public boolean accept(File dir, String filename) { if (filename.matches(pattern)) { return true; } return false; } } } 

By writing below code you will get the location:

/storage/663D-554E/Android/data/app_package_name/files/

which stores your app data at /android/data location inside the sd_card.

 File[] list = ContextCompat.getExternalFilesDirs(MainActivity.this, null); list[1]+"/fol" 

for getting location pass 0 for internal and 1 for sdcard to file array.

I have tested this code on a moto g4 plus and Samsung device (all works fine).

hope this might helpful.

I don’t know why but I need to call .createNewFile() on a File created in the public storage directories before using it. In the framework the comments for that method say it isn’t useful. Here’s a sample…

 String myPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PODCASTS) + File.separator + "My Directory"; final File myDir = new File(myPath); try { myDir.mkdirs(); } catch (Exception ex) { Toast.makeText(this, "error: " + ex.getMessage(), Toast.LENGTH_LONG).show(); } 

String myPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PODCASTS) + File.separator + "My Directory"; final File myDir = new File(myPath); try { myDir.mkdirs(); } catch (Exception ex) { Toast.makeText(this, "error: " + ex.getMessage(), Toast.LENGTH_LONG).show(); }

  String fname = "whatever"; File newFile = new File(myDir, fname); Log.i(TAG, "File exists --> " + newFile.exists()) //will be false try { if (newFile.createNewFile()) { //continue } else { Log.e(TAG, "error creating file"); } } catch (Exception e) { Log.e(TAG, e.toString()); } 

I have created a utils method to check a SD card is available on device or not, and get SD card path on device if it available.

You can copy 2 methods bellow into your project’s class that you need. Eso es todo.

 public String isRemovableSDCardAvailable() { final String FLAG = "mnt"; final String SECONDARY_STORAGE = System.getenv("SECONDARY_STORAGE"); final String EXTERNAL_STORAGE_DOCOMO = System.getenv("EXTERNAL_STORAGE_DOCOMO"); final String EXTERNAL_SDCARD_STORAGE = System.getenv("EXTERNAL_SDCARD_STORAGE"); final String EXTERNAL_SD_STORAGE = System.getenv("EXTERNAL_SD_STORAGE"); final String EXTERNAL_STORAGE = System.getenv("EXTERNAL_STORAGE"); Map listEnvironmentVariableStoreSDCardRootDirectory = new HashMap(); listEnvironmentVariableStoreSDCardRootDirectory.put(0, SECONDARY_STORAGE); listEnvironmentVariableStoreSDCardRootDirectory.put(1, EXTERNAL_STORAGE_DOCOMO); listEnvironmentVariableStoreSDCardRootDirectory.put(2, EXTERNAL_SDCARD_STORAGE); listEnvironmentVariableStoreSDCardRootDirectory.put(3, EXTERNAL_SD_STORAGE); listEnvironmentVariableStoreSDCardRootDirectory.put(4, EXTERNAL_STORAGE); File externalStorageList[] = null; if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) { externalStorageList = getContext().getExternalFilesDirs(null); } String directory = null; int size = listEnvironmentVariableStoreSDCardRootDirectory.size(); for (int i = 0; i < size; i++) { if (externalStorageList != null && externalStorageList.length > 1 && externalStorageList[1] != null) directory = externalStorageList[1].getAbsolutePath(); else directory = listEnvironmentVariableStoreSDCardRootDirectory.get(i); directory = canCreateFile(directory); if (directory != null && directory.length() != 0) { if (i == size - 1) { if (directory.contains(FLAG)) { Log.e(getClass().getSimpleName(), "SD Card's directory: " + directory); return directory; } else { return null; } } Log.e(getClass().getSimpleName(), "SD Card's directory: " + directory); return directory; } } return null; } /** * Check if can create file on given directory. Use this enclose with method * {@link BeginScreenFragement#isRemovableSDCardAvailable()} to check sd * card is available on device or not. * * @param directory * @return */ public String canCreateFile(String directory) { final String FILE_DIR = directory + File.separator + "hoang.txt"; File tempFlie = null; try { tempFlie = new File(FILE_DIR); FileOutputStream fos = new FileOutputStream(tempFlie); fos.write(new byte[1024]); fos.flush(); fos.close(); Log.e(getClass().getSimpleName(), "Can write file on this directory: " + FILE_DIR); } catch (Exception e) { Log.e(getClass().getSimpleName(), "Write file error: " + e.getMessage()); return null; } finally { if (tempFlie != null && tempFlie.exists() && tempFlie.isFile()) { // tempFlie.delete(); tempFlie = null; } } return directory; } 

Its work for all external devices, But make sure only get external device folder name and then you need to get file from given location using File class.

 public static List getExternalMounts() { final List out = new ArrayList<>(); String reg = "(?i).*vold.*(vfat|ntfs|exfat|fat32|ext3|ext4).*rw.*"; String s = ""; try { final Process process = new ProcessBuilder().command("mount") .redirectErrorStream(true).start(); process.waitFor(); final InputStream is = process.getInputStream(); final byte[] buffer = new byte[1024]; while (is.read(buffer) != -1) { s = s + new String(buffer); } is.close(); } catch (final Exception e) { e.printStackTrace(); } // parse output final String[] lines = s.split("\n"); for (String line : lines) { if (!line.toLowerCase(Locale.US).contains("asec")) { if (line.matches(reg)) { String[] parts = line.split(" "); for (String part : parts) { if (part.startsWith("/")) if (!part.toLowerCase(Locale.US).contains("vold")) out.add(part); } } } } return out; } 

Calling:

 List list=getExternalMounts(); if(list.size()>0) { String[] arr=list.get(0).split("/"); int size=0; if(arr!=null && arr.length>0) { size= arr.length - 1; } File parentDir=new File("/storage/"+arr[size]); if(parentDir.listFiles()!=null){ File parent[] = parentDir.listFiles(); for (int i = 0; i < parent.length; i++) { // get file path as parent[i].getAbsolutePath()); } } } 

Getting access to external storage

In order to read or write files on the external storage, your app must acquire the READ_EXTERNAL_STORAGE or WRITE_EXTERNAL_STORAGE system permissions. Por ejemplo:

   ...  

/sdcard => Internal Storage (It’s a symlink but should work)

/mnt/extSdCard => External Sdcard

This is for Samsung Galaxy S3

You can probably bank on this being true for most…double check however!