I have looked over many posts on getting SD card locations, and most that mention using Environment.getExternalStorageState(), Environment.getExternalStorageDirectory() always returns internal storage for my on a Samsung Galaxy Tab A / Android 11 (/storage/emulated/0)
I did see a comment that said to use System.getenv("SECONDARY_STORAGE"), which returns /storage/sdcard:/storage/usb1:/storage/usb2, but trying to open a file (I have put there) just returns a not found error (ie java.io.FileNotFoundException: /sdcard/external_sd/Music/test/testfile.mp3: open failed: ENOENT (No such file or directory).
Also tried Environment.getExternalStoragePublicDirectory(Environment.MEDIA_MOUNTED).getPath() and this returns /storage/emulated/0/mounted and this does not work either
I have the following permissions..
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.PERMISSIONS_STORAGE" />
<uses-permission android:name="android.permission.REQUEST_EXTERNAL_STORAGE" />
and at startup I call
private fun verifyStoragePermissions(activity: Activity) {
// Check if we have write permission
val permission =
ActivityCompat.checkSelfPermission(activity, READ_EXTERNAL_STORAGE)
if (permission != PackageManager.PERMISSION_GRANTED) {
// We don't have permission so prompt the user
ActivityCompat.requestPermissions(
activity,
arrayOf(READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE),
)
}
}
Finally, as stated here, I hardwired /sdcard/external_sd and this did not work either (ie I try to open a file I know is there, and also using the following to list contents..
File(testFolder).walk().forEach {
println(it)
}
I have other application that writes to it, so there must be some way to do it (I only want to read existing files).
What might I be doing wrong?
You can try this:
File[] dirs = getExternalFilesDirs("");
for (File currD :
dirs) {
if (currD.getAbsolutePath().equals(getExternalFilesDir("").getAbsolutePath())) {
// Here is internal storage path
} else {
// Here is SD path
}
}
I'm working in a listActivity and I'm trying to show the children of a given directory. Here is what I've tried to get the children of a given directory :
File currentFile = new File(Environment.getExternalStorageDirectory(), "Pictures");
String[] children = currentFile.list();
In fact, "children" is null and I don't know why. When I ask the absolute path of "currentFile", the answer is "/storage/emulated/0/Pictures".
Thanks for your help!
Make sure the folder exists, and check if you have added the permission to your manifest.
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
and if you are running on Android M, you would need to request runtime permission
https://developer.android.com/preview/features/runtime-permissions.html#coding
Once again, I've come up against a question which has been asked and answered before but in my implementation it is still not working.
I'm calling getExternalFilesDir(null) right at the very start of my main activity's onCreate method. It returns null every time, whether I run it in an AVD or on my phone (Samsung Galaxy Plus).
Yes, I have the <uses-permission android:name="android.permissions.WRITE_EXTERNAL_STORAGE" /> line in my AndroidManifest.xml and yes, I am checking the external storage state before I make the call and it is mounted.
Here are the first three lines inside my onCreate() method. Actually, it's just after the super.onCreate() and setContentView() calls.
String state = Environment.getExternalStorageState();
File extFiles = getExternalFilesDir(null);
File locFiles = getFilesDir();
So, once these three lines have executed, these are the values for the variables:
state == "mounted"
extFiles == null
locFiles == "/data/data/com.mypackage.name/files"
Would anyone have any ideas as to why this might be?
-----EDIT-----
So I've tried another approach; Rather than using getExternalFilesDir(null), I tried using File basePath = new File(Environment.getExternalStorageDirectory(), "myAppName");
This is not ideal and I know that the Android documentation says, and I agree with it, that you should rather use getExternalFilesDir(). Seeing as that's not working for me though I had to try something else. This time the function does return a valid File object so, after the above line, the path of basePath is /mnt/sdcard/myAppName. So far, so good. When I check with DDMS I can see that /mnt/sdcard exists but not /mnt/sdcard/myAppName. This is to be expected. So I call boolean result = basePath.mkdirs();
But this returns false and when I check on the file system I can confirm that the myAppName subfolder has not been created. When I create the folder manually through DDMS and put files in it, I can read those files from my application but I can't write anything in that folder.
Please help! I'm at my wit's end.
If this wasn't a typo when you posted your question, you'll probably hate yourself for this:
<uses-permission android:name="android.permissions.WRITE_EXTERNAL_STORAGE" />
should be
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
This is from Android documentation:
Returns the path of the directory holding application files on external storage.
Returns null if external storage is not currently mounted so it could not ensure
the path exists; you will need to call this method again when it is available.
The other option is you can check if External storage is available:
String state = Environment.getExternalStorageState();
File filesDir;
// Make sure it's available
if (Environment.MEDIA_MOUNTED.equals(state)) {
// We can read and write the media
filesDir = getExternalFilesDir(null);
} else {
// Load another directory, probably local memory
filesDir = getFilesDir();
}
My issue was that I opened a FileOutputStream, then before I closed the FileOutputStream, I opened a FileInputStream to see what was already in the file.
I moved opening the FileInputStream to before the FileOutputStream is opened and that fixed my issue.
Delete a line
uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
in AndroidManifest.xml.
Switch a xml editor to "Android Manifest Permissions" with "Permission" tab in eclipse, and add a
uses-permission "android.permission.WRITE_EXTERNAL_STORAGE"
with some clicks.
Then try running your application.
It seems eclipse (may depends on a defference of version or state or settings) can ignore some words described by direct xml in AndroidManifest.xml.
Thanks for an advise. You are right, my answer looked like to agree in small talk.
I am writing a simple activity to record and save audio, preferably to a folder within my application, but, for simplicity, to the SD card. The line of code that's giving me trouble is
String path = Environment.getExternalStorageDirectory().toString() + "/" + "tempAppFiles/";
String filename = "test"+".mp4";
recorder.setOutputFile(path + filename);
where recorder is an instance of MediaRecorder.
When I run the application, I get a permissions error that states
07-31 15:51:51.810: W/System.err(13670): java.io.FileNotFoundException: /mnt/sdcard/tempAppFiles/test.mp4 (Permission denied)
I looked this problem up and found that I needed to add several permission tags to my manifest, and I added
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
to my manifest.
I am still getting the same permissions issue, and I can't find anyone with a similar problem.
Any ideas?
Hmm... The permissions seem to be correct, perhaps you've put them in the wrong place, they need to be children of the root note .
Next you can check, whether you can write the file by checking
boolean canIWrite = path.canWrite();
As you also get a FileNotFound exception you could try...
String path = Environment.getExternalStorageDirectory().getAbsolutePath();
...instead of...
String path = Environment.getExternalStorageDirectory().toString();
If that is no help at all, there is still an official example of capturing audio - you should compare your code to:
http://developer.android.com/guide/topics/media/audio-capture.html
tempAppFiles does not set well with me. Seems like you should be writing to a directory that is under the package name of the app you are writing ...
I'm driven crazy with this:
Log.d("STATE", Environment.getExternalStorageState());
File f = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), "work_data");
Log.d("PATH", f.getAbsolutePath());
if (!f.exists()) {
Log.d("MAKE DIR", f.mkdirs() + "");
}
The output log looks like this:
STATE mounted
PATH /mnt/sdcard/DCIM/work_data
MAKE DIR false
I made sure to add the correct permission:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
But I don't know why it could not create the folder. I also used mkdir() step by step but the result is the same. Please help me. I have googled so much and spent at least 2 days on this stupid thing. Thanks for your help!!
EDITING:
Sorry everyone! I had added <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> in <application> tag. this was my mistake! But thank you all for reply.
I got the same problem,and I am sure I had put the permission tag in the right place,but mkdirs didn't work yet, my system is Android 6.0, I resolve it now , you can check as below:
make sure your put the permission tag in .
open "setting/application" in your phone,check your application's permission(I found the permission in my manifest statement is not here),open the switch of the permission like this.(I found it is closed in default which make "mkdirs" failed)
I have had the same problem and I have searched everything for a week trying to find the answer. I think I found it and I think it's ridiculously easy, you have to put the uses-permission statement in the right place...
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.company.name"
android:versionCode="1"
android:versionName="0.2">
<uses-sdk android:minSdkVersion="8" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
When I had it inside the <application></application> section it did not work.
I know this is an old post but perhaps my answer can help somebody.
After several days dealing with this problem I have realized that while the phone is connected to the PC, which it turns to be always during development, the SD card is not available. Thus making to fail any attempt to create a directory or file over it.
To make it "easier" it seemed to behave differently depending of the telephone under test.
I know it can sound quite a silly problem, but it cost a lot of time that maybe some other can save.
Applicable only if your targetSdkVersion is 29 or above
Environment.getExternalStorageDirectory() is deprecated in API level 29.
To get the same functionality use this line
File mediaStorageDir = context.getExternalFilesDir(null);
If you have checked all the possible errors then try this fix.
Already answered here - https://stackoverflow.com/a/61480077/7764015
add this line of code in OnCreate()
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},1);
Might be it's too late for answer but if you already allowed R/W permission(Runtime Permission too) and still doesn't work add this below mentioned line in your AndroidManifest.xml
<application
........
........
android:requestLegacyExternalStorage="true">
Note: this must required if you'r targeting Android 10+
mkdirs() only returns true if the directory was created. If it is in place already, it should return false. So I would bet this directory already exists.
<application
.....
android:requestLegacyExternalStorage="true">
work well.
I had the same issue, and I just wanted to share my fix.
as per android
Beginning with Android 4.4, reading or writing files in your app's private directories does not require the READ_EXTERNAL_STORAGE or WRITE_EXTERNAL_STORAGE permissions.
So you can declare the permission should be requested only on the lower versions of Android by adding the maxSdkVersion attribute:
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18" />
but maxSdkVersion is the issue, I just removed it and now it works.
put this
Log.d("MAKE DIR", f.mkdir() + "");
instead of
Log.d("MAKE DIR", f.mkdirs() + "");
or try this
String s=Environment.getExternalStorageDirectory().toString()+"/";
File f = new File(s+"DCIM/work_data");
Your code is working fine for me.There is no any thing wrong in your code.
Just if you are making one directory use f.mkdir() instead of f.mkdirs()
You can see your folder in mnt => Sd card => DCIM => work_data
If you have android 6.0 and more, make sure your target sdk in gradle file less than 22:
targetSdkVersion 22
or you need to implement run time permissions.
This might help someone in the future.
the problem might also be that you write the address "/File/Address/" instead you should write
File.separator + "File" + File.separator + "Address" + File.separator
This is such a small and stupid thing but this worked for me after wasting hours of my time.
If you're targeting Android api 29 then add this in your AndroidManifest.xml
<application android:requestLegacyExternalStorage="true">
I tried to make a set of subfolders in external storage 'Test/Test1/Test2' when mkdirs() kept returning false. Turns out that 'Test' is either a reserved word for a folder in the external storage root. This was on a Motorola G (XT1541) and may apply to other devices as well.
For new devices, you have to ask user permission.
You can do that like this before create your file:
boolean hasPermission = (ContextCompat.checkSelfPermission(MainActivity.this,
Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED);
if (!hasPermission) {
//ask permission
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
REQUEST_WRITE_STORAGE);
}
else {
//you have permission, create your file
}
After user's action, you can handle result.
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode)
{
case 1: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
{
//you have permission, create your file
//reload my activity with permission granted or use the features what required the permission
} else
{
Toast.makeText(MainActivity.this, "The app was not allowed to write to your storage. Hence, it cannot function properly. Please consider granting it this permission", Toast.LENGTH_LONG).show();
}
}
}
}