I'm learning Android development so am relatively new to some of the technical Android concepts, but I do have a strong developer background.
I am writing an app that I want to be able to directly access files on the user's SD card. The test device is a Samsung Galaxy Tab 4.
Samsung appears to use a custom method of mounting the SD card, placing it at /storage/extSdCard
rather than the more traditional /sdcard
.
In my app, I used the method Environment.getExternalStoragePublicDirectory
method to request the path for storage, and was given a path which points to the internal storage rather than the SD card. (/storage/sdcard0/...
)
When I try to directly access the SD card storage (/storage/extSdCard/...
), I get the error open failed: EACCES (Permission denied)
.
This device - and potentially any user's device - has very limited storage available on the internal memory. (This device has only 8GB of storage internally, most of which is taken up by apps.) Additionally, I want a potential app user to be able to put files onto their MicroSD card directly and not have to use an Android file transfer tool to load content into the app...
Any way I can access the external SD card directly from an app running on a Samsung device?
Test code:
public void doTest()
{
FileWriter fw;
File f = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS), "test.txt");
Log.i("file","Trying to write a file at: "+f.getPath());
try {
fw = new FileWriter(f);
fw.write("You got a file.");
fw.flush();
fw.close();
Log.i("file", "Successfully wrote the file.");
}
catch (IOException e)
{
Log.i("file_error", "Could not write the file.");
Log.i("file_error",e.getMessage());
}
f = new File("/storage/extSdCard/Documents", "test.txt");
Log.i("file","Trying to write a file at: "+f.getPath());
try {
fw = new FileWriter(f);
fw.write("You got a file.");
fw.flush();
fw.close();
Log.i("file", "Successfully wrote the file.");
}
catch (IOException e)
{
Log.i("file_error", "Could not write the file.");
Log.i("file_error",e.getMessage());
}
}
That is not possible on Android 4.4+, as most of the direct access to removable storage has been curtailed. Exceptions include pre-installed apps and apps that run on rooted devices and use superuser privileges.
/sdcard
has not been used for removable media since Android 2.x, on most devices.No,
getExternalStoragePublicDirectory()
points to external storage. External storage is not removable storage. Internal storage is something else entirely.You are welcome to use the
getExternalFilesDirs()
,getExternalCacheDirs()
, andgetExternalMediaDirs()
methods onContext
. Note the plural method names. If those methods return 2+ entries, the second and subsequent ones are locations on removable storage that you can read from and write to, no permissions required. However, you cannot access all of removable storage this way, just a location specific for your app.You are also welcome to use the Storage Access Framework, allowing the user to pick where the content goes, including placing it on removable storage. However, you are no longer working with files and paths, but with content and
Uri
values.The N Developer Preview offers another option for "Scoped Directory Access", which supports removable storage. However, this is still part of a developer preview at the present time (March 2016).