Getting "permission denied" even with WRITE_EXTERNAL_STORAGE declared and granted - android

I have an app that needs to write files to external storage.
In manifest I've added
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
In the activity I am calling
ActivityCompat.requestPermissions(this, STORAGE_PERMISSIONS, PERMISSION_REQUEST_RW_EXTERNAL_STORAGE);
Where:
private static final int PERMISSION_REQUEST_RW_EXTERNAL_STORAGE = 783;
private static final String[] STORAGE_PERMISSIONS = new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE};
Of course I'm granting everything and I can see in "onRequestPermissionsResult" the grants received by the app.
After all of that, when trying to create a file in external storage I am getting permissions denied.
java.io.IOException: Permission denied
Running on:
Android 8 (Oreo)
compileSdkVersion 27
minSdkVersion 23
targetSdkVersion 27
EDIT:
I am trying to write this directory: /storage/emulated/0/6666-6433/DCIM/Camera/. In previous state I'm listing video files on local storage and getting files in this directory. reading the files using this path is working as expected.

Related

getExternalStorageState().equals(Environment.MEDIA_MOUNTED) Passes without WRITE_EXTERNAL_STORAGE

I'm returning the external files directory for API 23 and below.
I want to check that the media is mounted, however this test is always passed, although the WRITE_EXTERNAL_STORAGE permission is not yet declared in the manifest.
I'm not sure, but I thought the test should fail for API 18 and below if the WRITE_EXTERNAL_STORAGE is not declared/enabled?
A permission denied exception is then thrown when trying to access this directory.
if(Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()))
{
return getExternalFilesDir(null).getAbsolutePath() + "/update_files";
}

Getting a Permission denied error when creating a file with Android, even when permission is given

I have this in my manifest:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
This is where I am trying to create and write to a file (it is in a file called EnterUserInfo.java:
// Storage Permissions
private static final int REQUEST_EXTERNAL_STORAGE = 1;
private static String[] PERMISSIONS_STORAGE = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
};
/**
* Checks if the app has permission to write to device storage
*
* If the app does not has permission then the user will be prompted to grant permissions
*
* #param activity
*/
public static void verifyStoragePermissions(Activity activity) {
// Check if we have write permission
int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (permission != PackageManager.PERMISSION_GRANTED) {
System.out.println("INSIDEEEEEE");
// We don't have permission so prompt the user
ActivityCompat.requestPermissions(
activity,
PERMISSIONS_STORAGE,
REQUEST_EXTERNAL_STORAGE
);
} else {
System.out.println("HEREEEEEEEEE");
}
}
private void writeToFile(String data, Context context) {
verifyStoragePermissions(this);
String FILENAME = "new_clients.txt";
String string = "hello world!";
try {
FileOutputStream fos = context.openFileOutput(FILENAME, Context.MODE_PRIVATE);
fos.write(string.getBytes());
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
FileOutputStream fos = context.openFileOutput("new_clients.txt", Context.MODE_PRIVATE);
fos.write(data.getBytes());
fos.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
When I try to create a file, this is what appears:
I/System.out: HEREEEEEEEEE
W/ContextImpl: Failed to ensure /data/user/0/c.b.project/files: mkdir failed: EACCES (Permission denied)
W/FileUtils: Failed to chmod(/data/user/0/cs.b07.cscb07courseproject/files): android.system.ErrnoException: chmod failed: EACCES (Permission denied)
W/System.err: java.io.FileNotFoundException: /data/user/0/c.b.project/files/new_clients.txt (Permission denied)
W/System.err: at java.io.FileOutputStream.open(Native Method)
W/System.err: at java.io.FileOutputStream.<init>(FileOutputStream.java:221)
W/System.err: at android.app.ContextImpl.openFileOutput(ContextImpl.java:506)
W/System.err: at android.content.ContextWrapper.openFileOutput(ContextWrapper.java:192)
W/System.err: at EnterUserInfo.writeToFile(EnterUserInfo.java:69)
As you can see, it prints here meaning the permission is granted, but right after it gives a Permission Denied error. Any idea how to solve this?
Edit: On a side note, when it says that it tries to save to /data/user/0/cs.b07.cscb07courseproject/files, is that within the project or is that saved on my computer? Because when I go to my terminal and do cd /data/ or cd /data neither is found.
Edit: writeToFile() is called in the same class and file posted above, and this is the code (the function below is called when a user hits the "register" button in the UI:
public void createNewUser(View view) {
// a data string is created here:
// String data = "asd";
writeToFile(data, this);
}
Edit 2: Please note that I did ask for permission at runtime in my verifyStoragePermissions() method. Unless something is wrong with that way of asking for permission (which I don't think it is because a prompt does appear which asks the user for permission), then I think the issue is with something else.
You do not need any permissions to call openFileOutput(). This writes a file to the private application-specific data area, which is owned by your application.
Judging by these errors:
W/ContextImpl: Failed to ensure /data/user/0/c.b.project/files: mkdir failed: EACCES (Permission denied)
W/FileUtils: Failed to chmod(/data/user/0/cs.b07.cscb07courseproject/files): android.system.ErrnoException: chmod failed: EACCES (Permission denied)
It looks like someone has changed the file ownership (or access rights) on your application's private data directory /data/user/0/c.b.project/. This directory should be owned by your application's user ID and therefore your application should have the necessary rights to write to it.
Uninstall your app (which should delete that directory) and then reinstall your app (which should recreate the directory with the correct permissions).
Requesting Permissions at Run Time
Beginning in Android 6.0 (API level 23), users grant permissions to apps while the app is running, not when they install the app. This approach streamlines the app install process, since the user does not need to grant permissions when they install or update the app.
More about runtime permission
Refer Answer
Hi firstly you have to check which android SDK version you are using
if it is less than 23 than you just have to put your permission in manifest file it work
if android version greater than 23 you should put all permission in manifest file as well as you should ask user permission for run time ( only first attempt )
for this you should follow this link https://stackoverflow.com/a/33162451/4741746
One more thing you can don is to change compileSdkVersion and buildToolsVersion to below 23 like 22 (but i will not suggest you for this because new features above 23 you can not be use )
android {
compileSdkVersion 22
buildToolsVersion "22.0.1"
defaultConfig {
minSdkVersion 16
targetSdkVersion 23
}
}
if not working let me know

Android Cannot create new folder

I cannot create new folder any way, it always return false when use mkdirs. I am using Android 6.0.1 in android studio debug mode.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="18" />`
String folder_main = "NewFolder";
Boolean success = false;
File f = new File(Environment.getExternalStorageDirectory(),folder_main
);
if (!f.exists()) {
Log.d("path","not exist");
success=f.mkdirs();
}
else
{
Log.d("path","exist");
}
Log.d("path",success.toString());
I didn't use write permission since in this docs
Starting in API level 19, this permission is not required to
read/write files in your application-specific directories returned by
getExternalFilesDir(String) and getExternalCacheDir().
The doc says you can read/write files only in the directories returned by getExternalFilesDir(String) and getExternalCacheDir() without write permission. But you get directory path by Environment.getExternalStorageDirectory().
Javadoc of Environment.getExternalStorageDirectory() says.
Writing to this path requires the WRITE_EXTERNAL_STORAGE permission, and starting in KITKAT, read access requires the READ_EXTERNAL_STORAGE permission, which is automatically granted if you hold the write permission.
Starting in KITKAT, if your application only needs to store internal data, consider using getExternalFilesDir(String), getExternalCacheDir(), or getExternalMediaDirs(), which require no permissions to read or write.

make external directory android

In case of making directory in external storage in android app I use this code:
File mDirectory = new File(Environment.getExternalStorageDirectory() + "/myDir");
if (!mDirectory.exists()) {
mDirectory.mkdirs();
if (!mDirectory.mkdirs()) {
Log.e("App", "failed to create directory");
}
}
but the directory didn't created and all the time the error message shown up in logcat:
App: failed to create directory
I also use both mkdir() and mkdirs(), but the result is same. where is the mistake?
updated:
AndroidManifest.xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
What Android Version are you running this app on ? This quote from the Android Developer Website says
If the device is running Android 6.0 (API level 23) or higher, and the app's targetSdkVersion is 23 or higher, the app requests permissions from the user at run-time. The user can revoke the permissions at any time, so the app needs to check whether it has the permissions every time it runs.
If the device is running Android 5.1 (API level 22) or lower, or the app's targetSdkVersion is 22 or lower, the system asks the user to grant the permissions when the user installs the app.
Now there is a notion of Dangerous permissions. That are permissions the user needs to grant at runtime and WRITE_EXTERNAL_STORAGE is one of those
This tutorial on the Android Dev website will teach you how to request permission at runtime
You are calling mkdirs twice. The first call creates the directory. The second call returns false, because the directory already exists.

open failed: EACCES (Permission denied)

I am having a very weird problem with storage accessing on some devices. The app works on my testing devices (Nexus 4 & 7, Samsung GS5). All my devices running Android 4.4.2. But I received many emails from users saying that the app can not write to the storage (neither the internal storage nor the sd card). From the log file received from user feedback, I can see the problem is the following code:
try {
if (fStream == null) {
fStream = new FileOutputStream(filename, true);
}
fStream.write(data, 0, bytes);
return;
} catch (IOException ex) {
ex.printStackTrace();
}
It throws exception at the line fStream = new FileOutputStream(filename, true); when creating FileOutputStream.
The stack log is:
W/System.err( 8147): Caused by: java.io.FileNotFoundException: /storage/emulated/0/my_folder/test_file_name.png: open failed: EACCES (Permission denied)
w/System.err( 8147): at libcore.io.IoBridge.open(IoBridge.java:409)
W/System.err( 8147): at java.io.FileOutputStream.<init>(FileOutputStream.java:88)
W/System.err( 8147): at java.io.FileOutputStream.<init>(FileOutputStream.java:128)
W/System.err( 8147): at myapp.save(SourceFile:515)
W/System.err( 8147): ... 8 more
W/System.err( 8147): Caused by: libcore.io.ErrnoException: open failed: EACCES (Permission denied)
W/System.err( 8147): at libcore.io.Posix.open(Native Method)
W/System.err( 8147): at libcore.io.BlockGuardOs.open(BlockGuardOs.java:110)
W/System.err( 8147): at libcore.io.IoBridge.open(IoBridge.java:393)
W/System.err( 8147): ... 11 more
In the AndroidManifest.xml I have the following permissions declared:
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="19"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
I've confirmed that the users are using the correct app's private on the SD card. And what's more weird is that it fails to write to internal storage as well. How can this happen if I have both read & write permissions? The users say they are not connecting their devices to the PC at that time.
Update
It turns out I am calling open and close FileOutputStream too frequently, which throws the FileNotFoundException at some point. Sounds more like a threading issue.
Apps targeting Android Q - API 29 by default are given a filtered view into external storage. A quick fix for that is to add this code in the AndroidManifest.xml:
<manifest ... >
<!-- This attribute is "false" by default on apps targeting Android Q. -->
<application android:requestLegacyExternalStorage="true" ... >
...
</application>
</manifest>
Read more about it here:
https://developer.android.com/training/data-storage/compatibility
For API 23+ you need to request the read/write permissions even if they are already in your manifest.
// Storage Permissions
private static final int REQUEST_EXTERNAL_STORAGE = 1;
private static String[] PERMISSIONS_STORAGE = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
};
/**
* Checks if the app has permission to write to device storage
*
* If the app does not has permission then the user will be prompted to grant permissions
*
* #param activity
*/
public static void verifyStoragePermissions(Activity activity) {
// Check if we have write permission
int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (permission != PackageManager.PERMISSION_GRANTED) {
// We don't have permission so prompt the user
ActivityCompat.requestPermissions(
activity,
PERMISSIONS_STORAGE,
REQUEST_EXTERNAL_STORAGE
);
}
}
AndroidManifest.xml
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
I ran into a similar issue a while back.
Your problem could be in two different areas. It's either how you're creating the file to write to, or your method of writing could be flawed in that it is phone dependent.
If you're writing the file to a specific location on the SD card, try using Environment variables. They should always point to a valid location. Here's an example to write to the downloads folder:
java.io.File xmlFile = new java.io.File(Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
+ "/Filename.xml");
If you're writing the file to the application's internal storage. Try this example:
java.io.File xmlFile = new java.io.File((getActivity()
.getApplicationContext().getFileStreamPath("FileName.xml")
.getPath()));
Personally I rely on external libraries to handle the streaming to file. This one hasn't failed me yet.
org.apache.commons.io.FileUtils.copyInputStreamToFile(is, file);
I've lost data one too many times on a failed write command, so I rely on well-known and tested libraries for my IO heavy lifting.
If the files are large, you may also want to look into running the IO in the background, or use callbacks.
If you're already using environment variables, it could be a permissions issue. Check out Justin Fiedler's answer below.
Add these both permission of read and write, to solve this issue
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Add this below line in Application tag
android:requestLegacyExternalStorage="true"
In my case I had the wrong case in
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
android.permission must be lowercase, and somehow the entire string was uppercase in our source.
I also faced the same issue.
After lot of hard work, I found what was wrong in my case.
My device was connected to computer via USB cable.
There are types for USB connections like Mass Storage, Media Device(MTP), Camera(PTP) etc.
My connection type was - 'Mass Storage', and this was causing the problems.
When I changed the connection type, the issue was solved.
Always remember while accessing filesystem on android device :-
DON'T CONNECT AS MASS STORAGE to the computer/pc.
In my case it was permissions issue.
The catch is that on device with Android 4.0.4 I got access to file without any error or exception. And on device with Android 5.1 it failed with ACCESS exception (open failed: EACCES (Permission denied)).
Handled it with adding follow permission to manifest file:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
So I guess that it's the difference between permissions management in OS versions that causes to failures.
First give or check permissions like
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
If these two permissions are OK, then check your output streams are in correct format.
Example:
FileOutputStream fos=new FileOutputStream(Environment.getExternalStorageDirectory()+"/rahul1.jpg");
I ran into the same problem and found that I have to request the permissions at run time, even if I have declared it in the manifest. Just as stated as Justin Fiedler's answer.
The official documentation about this are here: https://developer.android.com/training/permissions/requesting.html
My implementation is slightly different from Justin Fiedler's answer that it also implement v4 fragment's onRequestPermissionsResult method to handle the permissions request response.
public static final int REQUEST_EXTERNAL_PERMISSION_CODE = 666;
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
public static final String[] PERMISSIONS_EXTERNAL_STORAGE = {
READ_EXTERNAL_STORAGE,
WRITE_EXTERNAL_STORAGE
};
public boolean checkExternalStoragePermission(Activity activity) {
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.JELLY_BEAN) {
return true;
}
int readStoragePermissionState = ContextCompat.checkSelfPermission(activity, READ_EXTERNAL_STORAGE);
int writeStoragePermissionState = ContextCompat.checkSelfPermission(activity, WRITE_EXTERNAL_STORAGE);
boolean externalStoragePermissionGranted = readStoragePermissionState == PackageManager.PERMISSION_GRANTED &&
writeStoragePermissionState == PackageManager.PERMISSION_GRANTED;
if (!externalStoragePermissionGranted) {
requestPermissions(PERMISSIONS_EXTERNAL_STORAGE, REQUEST_EXTERNAL_PERMISSION_CODE);
}
return externalStoragePermissionGranted;
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (requestCode == REQUEST_EXTERNAL_PERMISSION_CODE) {
if (checkExternalStoragePermission(getActivity())) {
// Continue with your action after permission request succeed
}
}
}
}
In my case I used the option android:isolatedProcess="true" for a service in the AndroidManifest.xml.
As soon as I removed it, the error disappeared...
Also I found solving for my way.
Before launch app i granted root to file-explorer and did not disable permission on write/read when exit from app.
My app can not use external memory while i did restrat device for resetting all permissions.
I got the same issue but
Sometimes, the most dificult issue get simple answer.
I recheck the manifest permisions and there WAS_NOT write permision
shame of me!!!
#Uriel Frankel is correct that the Android 10 storage access has changed. But the right way is not to use legacy storage flag but to request the storage of your app like so:
val screenShotDirPath = getApplication<Application>().getExternalFilesDir(Environment.DIRECTORY_PICTURES)?.path
getExternalFilesDir is what you need.
I had the same problem. My app worked on Android 11, but the error showed up in Android 10. Upgrading to Android 11 solved the problem.
If the clients are using Android 6.0, Android added new permission model for (Marshmallow).
Trick: If you are targeting version 22 or below, your application will request all permissions at install time just as it would on any device running an OS below Marshmallow
In my case the issue was the WIFI Configuration that was static had a conflict with another device using the same IP Address.
This error was thrown by another app that I'm sharing my app's file to (using Intent.FLAG_GRANT_READ_URI_PERMISSION)
Turns out, the File Uri has to be provided via FileProvider class as shown here.
I was able to solve this problem by removing
tools:ignore="ScopedStorage" />
this line from
uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28" tools:ignore="ScopedStorage"
and also you don't need read permission anymore
Using Android 12 (API 31), I read in OS docs that we must use Manifest main property :
example:
uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
The issue has been solved.
I solved this by using another path:
data/data/[packagename]/cache/...
For those of you who tried all the above solutions and still doesn't solve your error on API 30.
Change targetSdkVersion 30 to 29 in defaultConfig in your build.gradle(app)
Code will look like:-
defaultConfig {
applicationId "com.example.company"
minSdkVersion 16
targetSdkVersion 29
.
.
.
}
in my case i forgot to add / in front of file name after i added i got rid of from it
bitmap.compress(Bitmap.CompressFormat.PNG,100,new FileOutputStream(Environment.getExternalStorageDirectory()+"/arjunreddy.png"));

Categories

Resources