I'm using BeagleBuddy mp3 tag editor to make changes to mp3 files on the internal / external storage... Works fine on some phones... but on certain phones, I get this error... (Samsung S4, Note 3) etc...
open failed: EACCES (Permission denied)
I have in my manifest...
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Still no luck... Any suggestions?
I've read a lot about how Android is protecting the external card from edits on some phones... is there a way to get around this?
I've used several different methods to get the external drive... Some work on some phone, some don't work...
This is what I am currently using:
public static File getRemovableStorage()
{
String value = System.getenv("SECONDARY_STORAGE");
if (!TextUtils.isEmpty(value))
{
String[] paths = value.split(":");
for (String path : paths)
{
File file = new File(path);
if (file.isDirectory())
{
return file;
}
}
}
return null; // Most likely, a removable micro sdcard doesn't exist
}
It finds all of the files on the external drive great... I just get that error when I try to update an mp3 tag on the external drive.
Related
Trying to download file in cache directory like context.getExternalCacheDir() or context.getCacheDir() on some devices i'm getting a Permission Denied error;
Referring to this guys (https://www.youtube.com/watch?v=5xVh-7ywKpE&t=1580s) i don't need to request permission to access cache directory of my application
Error message I've got from Huawei 4x:
java.io.FileNotFoundException: /storage/3C11-1816/Android/data/{my app package}/cache/194751d974025fd4109902d9600b6a09.mp3: open failed: EACCES (Permission denied)
How can i solve that problem?
Here is my directory provider where i download files
public File provide() {
File external = mContext.getExternalCacheDir();
File cacheDir = external != null ? external : mContext.getCacheDir();
if (!cacheDir.exists()) {
cacheDir.mkdirs();
}
return cacheDir;
}
I have an application that correctly works with files in "external storage".
Recently I upgrade Android Studio from 2.2 to 2.3. And after this upgrade an application fails when creating files in external storage with EACCESS (Permission denied).
Affected versions
I have error in Android 4.0.3, 4.1, 4.2
I do not have error in Android 4.3, 4.4 and higher.
Code example
It is part of code, that fails
File tempFile = new File(Environment.getExternalStorageDirectory().toString() + "/.tmpfile");
if (!tempFile.exists() && !tempFile.createNewFile()) {
throw new IOException("Cannot create temp file");
}
And in method createNewFile() throws exception with EACCES:
java.io.IOException: open failed: EACCES (Permission denied)
at java.io.File.createNewFile(File.java:948)
...
Caused by: libcore.io.ErrnoException: open failed: EACCES (Permission denied)
at libcore.io.Posix.open(Native Method)
at libcore.io.BlockGuardOs.open(BlockGuardOs.java:110)
at java.io.File.createNewFile(File.java:941)
...
java.io.IOException: open failed: EACCES (Permission denied)
at java.io.File.createNewFile(File.java:948)
...
Caused by: libcore.io.ErrnoException: open failed: EACCES (Permission denied)
at libcore.io.Posix.open(Native Method)
at libcore.io.BlockGuardOs.open(BlockGuardOs.java:110)
at java.io.File.createNewFile(File.java:941)
... 15 more
Of course, I have <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> in AndroidManifest.xml.
Application have granted permissions. I check it in main activity via:
if (checkCallingOrSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, WRITE_EXTERNAL_STORAGE_CODE);
}
and have requestCode == PackageManager.PERMISSION_GRANTED is true.
The most strange: when I try to rollback my code to previous stable production releases (when files was succesfully created in 2.2) and create build, I get the same error! :( I get this error in emulator, in real devices.
Why? What was changed in Android Studio 2.3, that I cant create any file in old Android?
UPD
Thanks for Nick, he helps me to find difference in behaviour. I test below lines on Android 4.2 and 4.3, and get:
Environment.getExternalStorageDirectory()
4.2: '/mnt/sdcard'
4.3: '/storage/sdcard'
ContextCompat.getExternalFilesDirs(this, null)
4.2: {null} (array with one null-element)
4.3: '/storage/sdcard/Android/data/com.example/files'
Environment.getExternalStorageState()
4.2: 'removed'
4.3: 'mounted'
Your problem concerns changes made in Android 4.4. To quote documentation:
Sometimes, a device [...] may also offer an SD card slot. When such a device is running Android 4.3 and lower, the getExternalFilesDir() method provides access to only the internal partition and your app cannot read or write to the SD card
The documentation also offers a solution:
If you'd like to access both possible locations while also supporting Android 4.3 and lower, use the support library's static method
This refers to using ContextCompat rather than the core Android method
File[] dirs = ContextCompat.getExternalFilesDirs(ctx, null); //null, no specific sub directory
if (dirs.length > 0) {
File ext = dirs[dirs.length -1]; //Just presuming SD card will be the last one offered
//use ext here like you used tempFile before
}
You should also make sure that the media is available, as lower Android versions are more likely to be using low performance devices. Do that with the Environment class
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
//safe
}
EDIT
So a complete solution might be to replace
File tempFile = new File(Environment.getExternalStorageDirectory().toString() + "/.tmpfile");
With
File tempFile = null;
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
//compatible for ALL the versions
File[] dirs = ContextCompat.getExternalFilesDirs(ctx, null); //null, no specific sub directory
if (dirs.length > 0) {
tempFile = dirs[dirs.length -1];
}
}
if (tempFile != null) {
//here continue exactly as you did before
if (!tempFile.exists() && !tempFile.createNewFile()) {
throw new IOException("Cannot create temp file");
}
} else {
//handle case where sd card isnt reachable (notification etc)
}
I'm using Samsung J7 Unrooted for Testing,
My AndroidManifest.xml contains the necessary permissions to write to external storage
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
I don't encounter any error when I used the code:
File myFile = new File("sdcard/Billing/mysdfile.txt");
It save the file on the Device Storage.
But when I specify the removable SDCard using the code:
File myFile = new File("/storage/extSdCard/mysdfile.txt");
I encounter the error :
open failed: EACCES (Permission denied)
I've tried different ways to point to the removable SDCard but encountered the same "open failed: EACCES (Permission denied)" error.
I've checked if I have the necessary permissions to write to external storages and it always say "Granted"
public void verifyStoragePermissions() {
if (ContextCompat.checkSelfPermission(InitActivity.this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
Toast.makeText(getBaseContext(), "Denied", Toast.LENGTH_SHORT).show();
if (ActivityCompat.shouldShowRequestPermissionRationale(InitActivity.this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
} else {
}
}else{
Toast.makeText(getBaseContext(), "Granted",Toast.LENGTH_SHORT).show();
}
}
I've tried almost everything suggested listed in the google search but to no avail. There are a Few who advises to "Root" the phone but that is unfortunately not an option for me...
Hope someone can help me gain the needed permission rights to save files in my removable external storage without resorting to "Rooting" the phone.
On Samsung T230 (Android 4.4.2) It works in both of the following
File firstFile = new File("mnt/extSdCard/Android/data/com.example.storagetest", "test.txt");
RandomAccessFile fileLittle = new RandomAccessFile(firstFile, "rw");
File scndFile = new File("mnt/extSdCard/Android/data/com.example.storagetest", "test2.txt");
scndFile.createNewFile();
I've tried a lot of these devices are working in this way. T230 is an example
On Hometech Tablet (Android 5.1.1) does not work.
File firstFile = new File("mnt/external_sd/Android/data/com.example.storagetest", "test.txt");
RandomAccessFile fileLittle = new RandomAccessFile(firstFile, "rw");
File scndFile = new File("mnt/external_sd/Android/data/com.example.storagetest", "test2.txt");
scndFile.createNewFile();
I get an error as follows:
open failed: EACCES (Permission denied)
Current AndroidManifest.xml
<application>
...
</application>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
I tried many different ways... requestPermissions() and android:maxSdkVersion does not change anything
Too much search but I could not reach a conclusion.
How can i create a file on SD Card.
Important: I can read files directly, but cant change or create new file.
How can i create a file on SD Card.
You don't. Devices that ship with Android 4.4+ do not allow arbitrary access to removable storage.
You can indirectly work with removable storage via the Storage Access Framework. There, you do not worry about exactly where the user is putting the data (external storage, removable storage, Google Drive, Dropbox, etc.).
I am having a problem copying files (.so binaries) from my assets directory to the app installation "/data/data/name.ofmy.app/lib" directory.
When I try to I get the following error:
07-09 11:00:48.902: W/System.err(25122): java.io.FileNotFoundException: /data/data/name.ofmy.app/lib/libOlsrdPudWireFormat.so: open failed: EACCES (Permission denied)
This happens when the following code is being ececuted:
if ((so = new File(dir, fileName)).exists()) {
/*
* Check to see if this timestamp pre-dates the current package
*/
if ((pkg = new File(ctx.getPackageResourcePath())).exists()) {
if (pkg.lastModified() < so.lastModified()) {
Log.v(TAG, "extractFile: File up to date");
return;
}
}
Log.v(TAG, "extractFile: library present but out of date");
so.delete();
}
Log.v(TAG, "extractFile: copying library");
InputStream in = ctx.getAssets().open(name);
FileOutputStream out = new FileOutputStream(so);
It breaks right at InputStream in = ctx.getAssets().open(name); when there is not an already existing file with that name...
I have been reading similar questions here on Stack Overflow, but unfortunately that did not help. Most are copying to the SD card, but I am not.
Also the strange part is that a previous directory (/bin instead of /lib), which is also supplied within my assets, does get copied without any problem in the same /dat/data... directory!
I tried adding the <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> permission to no avail.
I even tried adding Runtime.getRuntime().exec("su"); just before I try to copy anything, also to no avail.
It's a rooted phone BTW!
I also double checked if the file is really there in the assets, and it is!
Just for the sake of trying I changed the directory name from lib to libs (because as mentioned in my question, I also copied another directory named /bin without any issues) and guess what: now it works!
It seems you cannot use the /lib directoryname whilst copying. I have no idea why, though.
Definitely you forgot to put in the manifest:
<manifest
.
.
</application>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
</manifest>