Removable storage (external) sdcard path by manufacturers - android

I've been Googling around but it is sooooo hard to find what manufacturers/models use which path for sdcard/external storage.
I am NOT talking about the internal storage path which can be found by:
Environment.getExternalStorageDirectory()
I know that getExternalStorageDirectory() sometimes points to external sdcard on some devices.
Here's what I've found some common path for external path (Not sure which manufacturer uses which path):
/emmc
/mnt/sdcard/external_sd
/mnt/external_sd
/sdcard/sd
/mnt/sdcard/bpemmctest
/mnt/sdcard/_ExternalSD
/mnt/sdcard-ext
/mnt/Removable/MicroSD
/Removable/MicroSD
/mnt/external1
/mnt/extSdCard
/mnt/extsd
/mnt/usb_storage <-- usb flash mount
/mnt/extSdCard <-- usb flash mount
/mnt/UsbDriveA <-- usb flash mount
/mnt/UsbDriveB <-- usb flash mount
These are what I found by Googling around.
I need to scan entire internal + external storage + USB flash drive to look for a certain file. If I am missing any path, please add to the above list. If someone knows paths used by each manufacturers, please share with us.

Good news! In KitKat there's now a public API for interacting with these secondary shared storage devices.
The new Context.getExternalFilesDirs() and Context.getExternalCacheDirs() methods can return multiple paths, including both primary and secondary devices. You can then iterate over them and check Environment.getStorageState() and File.getFreeSpace() to determine the best place to store your files. These methods are also available on ContextCompat in the support-v4 library.
Also note that if you're only interested in using the directories returned by Context, you no longer need the READ_ or WRITE_EXTERNAL_STORAGE permissions. Going forward, you'll always have read/write access to these directories with no additional permissions required.
Apps can also continue working on older devices by end-of-lifing their permission request like this:
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18" />

I also started with a list like yours from somewhere (sorry couldn't find the original source) and continue to add some paths collected from user feedback. There are duplicate to the above list.
/storage/sdcard1 //!< Motorola Xoom
/storage/extsdcard //!< Samsung SGS3
/storage/sdcard0/external_sdcard // user request
/mnt/extsdcard
/mnt/sdcard/external_sd //!< Samsung galaxy family
/mnt/external_sd
/mnt/media_rw/sdcard1 //!< 4.4.2 on CyanogenMod S3
/removable/microsd //!< Asus transformer prime
/mnt/emmc
/storage/external_SD //!< LG
/storage/ext_sd //!< HTC One Max
/storage/removable/sdcard1 //!< Sony Xperia Z1
/data/sdext
/data/sdext2
/data/sdext3
/data/sdext4
/sdcard1 //Sony Xperia Z
/sdcard2 //HTC One M8s
/storage/microsd //ASUS ZenFone 2
For what you want to achieve (scanning all possible paths for certain files), I think it's quite impossible to do it this way (using a list of known paths). Some paths on same device even changed between android upgrade.

Based on the paths oceanuz provided, I wrote a method, which locates the external storage path (ignoring the case) and returns it as a String.
Note: I used StreamSupport library inside my method, so in order for it to work, you'll need to download the jar file and add that to libs folder in your project and that's it.
public static String getExternalSdPath(Context context) {
List<String> listOfFoldersToSearch = Arrays.asList("/storage/", "/mnt/", "/removable/", "/data/");
List<String> listOf2DepthFolders = Arrays.asList("sdcard0", "media_rw", "removable");
List<String> listOfExtFolders = Arrays.asList("sdcard1", "extsdcard", "external_sd", "microsd", "emmc", "ext_sd", "sdext",
"sdext1", "sdext2", "sdext3", "sdext4");
final String[] thePath = {""};
Optional<File> optional = StreamSupport.stream(listOfFoldersToSearch)
.filter(s -> {
File folder = new File(s);
return folder.exists() && folder.isDirectory();
}) //I got the ones that exist and are directories
.flatMap(s -> {
try {
List<File> files = Arrays.asList(new File(s).listFiles());
return StreamSupport.stream(files);
} catch (NullPointerException e) {
return StreamSupport.stream(Collections.emptyList());
}
}) //I got all sub-dirs of the main folders
.flatMap(file1 -> {
if (listOf2DepthFolders.contains(file1.getName().toLowerCase())) {
try {
List<File> files = Arrays.asList(file1.listFiles());
return StreamSupport.stream(files);
} catch (NullPointerException e) {
return StreamSupport.stream(Collections.singletonList(file1));
}
} else
return StreamSupport.stream(Collections.singletonList(file1));
}) //Here I got all the 2 depth and 3 depth folders
.filter(o -> listOfExtFolders.contains(o.getName().toLowerCase()))
.findFirst();
optional.ifPresent(file -> thePath[0] = file.getAbsolutePath());
Log.i("Path", thePath[0]);
return thePath[0];
}
This method will return an empty string if there is no Sd Card path found.

I was trying to find path to my external SD card on Sony Xperia XA. I then installed ES File explorer and that clearly showed path to any folder, internal or external, in it's characteristics window. I found the path to external SD as /storage/C4EE-F3A3. I was trying to save output file from Python3 to external SD but it did not have permission to save anywhere other than Qpython folder in the internal SD.

Related

How to manage external storage independently of the phone

I have phone (B15 CAT) with a sd card slot. When i insert a sdcard in this phone and asking for the external storage directory with :
Environment.getExternalStorageDirectory()
it always return an space on sdcard0 which is the internal memory. This memory is too small for my need.
By listing /mnt i found a mount point named /sdcard2 which is the "real" scard.
Unfortunately sdcard2 doesn't seems to be a standard and some other brand will use some other name...
Knowing that getExternalStorageDirectory() seems working as expected on phone with no sdcard slot , like nexus 4, how should i handle external storage to be sure to write on the sdcard (big space available) and not on internal memory ?
I have tried something like this :
File mnt = new File("/mnt");
File[] liste = mnt.listFiles();
boolean hassd2 = false;
for(File mount : liste) {
if(folder.getName().equals("sdcard2") {
hassd2 = true;
break;
}
}
String path = "";
if(hassd2) {
path = "/sdcard2/my/folder/"
} else {
File p = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/my/folder/");
path = p.toString();
}
It's working but only with this specific phone and others one with no sdcard slot ...
I also had the problem with the build in functions of Android in case of multiple 'external' storages mounted. I parsed the mounted directories directly from the f_stab file.
This link should give you the code you needed.
After having the mount points you could try to calculate the available space in order to decide if it is enough for your operation.

Android app can write data on Nexus S but not on samsung S2 on "/sdcard/filename" path?

i have given required permission :
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
hard-coded the path as "/sdcard/filename".
I guess Nexus don't have external SD support but S2 has, that I think might cause a problem in getting the path. How should I handle such a case gracefully?
On each Android Device you can get the path to the external storage like this
Environment.getExternalStorageDirectory()
I've a Nexus device and it works - also on my old milestone
Here is an example usage to create your own apps directory:
You should always check to see if the SDcard is available first because it could be mounted/teathered to a computer or be removed from the device.
private void SetDirectory() {
if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {
extStorageDirectory = Environment.getExternalStorageDirectory().toString();
File dbDirectory = new File(extStorageDirectory + "/yourAppName/whatever/");
myDirectory.mkdirs();// Have the object build the directory
} else if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED_READ_ONLY)) {
//TODO Make some kind of allert or Toast to warn/notify the user that the SDcard is needed.
}
}
You can use the android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED) method to check if the card is available anywhere within your application.

Samsung Nexus S android 4.0: can't create file in dir on sdcard

I have a Samsung Nexus S device with android 4.0 loaded on it. I am trying to create a file in an existing folder on sdcard and get a "permission denied". In the following code, exists() returns true but canWrite() returns false. Why?
File exst = Environment.getExternalStorageDirectory();
String exstPath = exst.getPath();
File d = new File(exstPath+"/TestDir/");
if (!d.exists())
{
int b = 1;
}
if (!d.canWrite())
{
int a = 1;
}
By the way, I've added <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> to the manifest but that did not help.
Is your phone plugged into your computer? If so, the computer will take control of the SD card and not allow it to be written to. Try changing the connection mode to 'Charge Only' if this is the case.
Append getAbsolutePath() to your first line, then it should work:
File exst = Environment.getExternalStorageDirectory().getAbsolutePath();
Update:
Reviewing my own code and other SO answers, I believe you do not use canWrite to check if a path is writable on a SD card. Instead you use Environment.MEDIA_MOUNTED:
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
Log.d("Test", "sdcard mounted and writable");
}
else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
Log.d("Test", "sdcard mounted readonly");
}
else {
Log.d("Test", "sdcard state: " + state);
}
Although all the answers give partial suggestions, the problem is very likely Samsungs non-standard implementation of the API
String myPath = Environment.getExternalStorageDirectory().getAbsolutePath ;
// or .getName() or .getPath() <-- these don't return everything you need.
// same is true for the file version you're trying.
// you have to append
"/external_sd/"
to the path before the file name.
Here's Samsungs explanation for their "breaking" of the API
http://developer.samsung.com/forum/board/thread/view.do?boardName=GeneralB&messageId=162934&messageNumber=1381&startId=zzzzz~&searchType=TITLE&searchText=sdcard
it's also mentioned in several SO posts, but I don't have the links handy...
H
[Edit Mid May, 2013] Here's the pathology of this problem: you can get the path() by the various normal methods mentioned. Then, just write a simple file and watch it show up in the DDMS file explorer. Try hardcoding that exact path and file name OR use the /external_sd/ thing - in both cases, you will not be able to read your own file back in ! (Or you might, but it will contain garbage.) We've verified this on three different S3 phones. Will test more on Samsungs "real" phones via their RemoteTestingLab site and report back.

Android ImageView SDCard

I am trying to read an image file from /mnt/sdcard/image.jpg into my ImageView. Here is my code:
Bitmap bmp = BitmapFactory.decodeFile("/mnt/sdcard/image.jpg");
webImage.setImageBitmap(bmp);
I have write external storage permission.
My code says bmp is null, even though the image resides in the root directory (I go to I Drive and image.jpg is there.)
What am I doing incorrectly?
There could be two cases:
1) If you image is in the root folder of sdcard then it is possible to to access it through
Environment.getExternalStorageDirectory().toString + File.separator + "yourimage.jpg"
2) But i guess in your case it is in the /mnt/sdcard/external_sd which your memory card of the device in that case try this:
Environment.getExternalStorageDirectory().toString + File.separator + "external_sd" + File.separator + "yourimage.jpg"
Replace the above two paths with yours in BitmapFactory.decodeFile("Replace Here...")
I suspect the card with the image isn't mounted under /mnt/sdcard/.
Since you are using a Motorola device, chances are that you have two mass storage devices (see this list, if your device is in there, this is the case). In this situation you have to use the Motorola "External" Storage API to get the path to your second mass storage.
Also in general: You can't rely on hardcoding paths to the SD-Card like this. The mountpoint differs across devices. Or might be named differently, some devices might have a flash storage instead of a card, and so on. In short: What works on your phone breaks on others. You can read a reliable path to the primary external storage by calling Environment.getExternalStorageDirectory() instead.
Thanks, I managed to resolve it. Here is what I found:
I went to project > clean
I disconnected the phone from the computer. When it is connected, the SD is mounted and you can't view data.
The image name can't start with numbers. I am using SDK 7.
I viewed LogCat and I didn't get any errors, however, saving to other system areas (like /Android/Data/) caused a FileNotFoundException - permissions error.
File destination = new File(Environment.getExternalStorageDirectory(), "image" +
DateHelper.getTodaysDate() + "_" + DateHelper.getCurrentTime() + ".jpg");
private View.OnClickListener listener = new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Add extra to save full-image somewhere
intent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(destination));
startActivityForResult(intent, REQUEST_IMAGE);
}
};
Please check you LogCat for more information.
My guess is you have a Samsung device. Samsung tends to have an external_sd folder, so you might have added it to the wrong sdcard because Samsung often has an internal and an external one.
Your code is perfectly okay. Just check whether you are writing proper sd card path or not. May be for that reason you are getting null bitmap.
And "write external storage permission" is for writing to your sd card not for reading from sd card. Make this concept clear.

Environment.getExternalStorageDirectory does not return the path to the removable storage

As of API level 8, it seems Android has redefined what "external" storage is. Reading through http://developer.android.com/reference/android/os/Environment.html, attached to the documentation for getExternalStorageDirectory I see the comment: "don't be confused by the word 'external' here. This directory can better be thought as media/shared storage... In devices with multiple 'external' storage directories... , this directory represents the 'primary' external storage that the user will interact with."
My app writes files to the path obtained by getExternalStorageDirectory, and I've had users ask for an option to write to their removable SD card instead. I had always assumed that getExternalStorageDirectory returned the path to the removable SD card, but this is no longer true. How do I access the path to this SD card?
According to the source, getExternalStorageDirectory is implemented to return whatever is set as "external storage" in the device environment:
public static File getExternalStorageDirectory() {
return EXTERNAL_STORAGE_DIRECTORY;
}
and EXTERNAL_STORAGE_DIRECTORY is:
private static final File EXTERNAL_STORAGE_DIRECTORY
= getDirectory("EXTERNAL_STORAGE", "/sdcard");
static File getDirectory(String variableName, String defaultPath) {
String path = System.getenv(variableName);
return path == null ? new File(defaultPath) : new File(path);
}
In contrast, getExternalStoragePublicDirectory(String type) requires one of these strings:
DIRECTORY_MUSIC, DIRECTORY_PODCASTS, DIRECTORY_RINGTONES, DIRECTORY_ALARMS, DIRECTORY_NOTIFICATIONS, DIRECTORY_PICTURES, DIRECTORY_MOVIES, DIRECTORY_DOWNLOADS, or DIRECTORY_DCIM. May not be null.
so it is not meant to return the sd-card root.
An alternative:
Finally, getExternalStorageState() will return the filesystem mounted in /mnt/sdcard/. According to CommonsWare in this answer: Find an external SD card location, there is no way to directly get the external sdcard (if it even exist).
An alternative would be to check isExternalStorageRemovable () and give a manual option if it is false.
For API 17 I get the following returns:
Environment.getExternalStoragePublicDirectory(Environment.MEDIA_MOUNTED)
returns:-------> /storage/sdcard0/mounted
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
returns:-------> /storage/sdcard0/DCIM
Environment.getExternalStoragePublicDirectory(Environment.MEDIA_SHARED)
returns:-------> /storage/sdcard0/shared
Environment.MEDIA_MOUNTED
returns:-------> mounted
Environment.getExternalStorageDirectory()
returned:-------> /storage/sdcard0
All return location of internal phone memory.
To be sure you are accessing the sd card you can use:
System.getenv("SECONDARY_STORAGE")
however - please keep in mind that even if you set all the correct permissions in the manifest -
The only place 3rd party apps are allowed to write on your external card are "their own directories"
(i.e. /sdcard/Android/data/)
Try to write to anywhere else and you will get exception:
EACCES (Permission denied)

Categories

Resources