With the android kitkat 4.4.2 version is a new google policy implemented for writeaccess, which I do not understand so far.
I read a lot about this issue with other apps. They get a "EACCES permission denied". My app needs to write/unzip a zipfile, also write to a sqlite-database.
How can this EACCES permission denied issue be solved with Android version 4.4.2 KITKAT ?
From the docs:
Starting in Android 4.4, multiple external storage devices are surfaced to developers through Context.getExternalFilesDirs(), Context.getExternalCacheDirs(), and Context.getObbDirs().
External storage devices surfaced through these APIs must be a semi-permanent part of the device (such as an SD card slot in a battery compartment). Developers expect data stored in these locations to be available over long periods of time. For this reason, transient storage devices (such as USB mass storage drives) should not be surfaced through these APIs.
The WRITE_EXTERNAL_STORAGE permission must only grant write access to the primary external storage on a device. Apps must not be allowed to write to secondary external storage devices, except in their package-specific directories as allowed by synthesized permissions. Restricting writes in this way ensures the system can clean up files when applications are uninstalled.
I found a working solution to this issue in xda forum; there is no need for rooting.
Here's an example :
/**
* Returns an OutputStream to write to the file. The file will be truncated immediately.
*/
public OutputStream write()
throws IOException {
if (file.exists() && file.isDirectory()) {
throw new IOException("File exists and is a directory.");
}
// Delete any existing entry from the media database.
// This may also delete the file (for media types), but that is irrelevant as it will be truncated momentarily in any case.
String where = MediaStore.MediaColumns.DATA + "=?";
String[] selectionArgs = new String[] { file.getAbsolutePath() };
contentResolver.delete(filesUri, where, selectionArgs);
ContentValues values = new ContentValues();
values.put(MediaStore.Files.FileColumns.DATA, file.getAbsolutePath());
Uri uri = contentResolver.insert(filesUri, values);
if (uri == null) {
// Should not occur.
throw new IOException("Internal error.");
}
return contentResolver.openOutputStream(uri);
}
You need to ask the android about the permission on real time like this:
private static final int MY_PERMISSIONS_REQUEST_STORAGE = 123456;
if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(getActivity(), new String[]{android.Manifest.permission.READ_EXTERNAL_STORAGE}, MY_PERMISSIONS_REQUEST_STORAGE);
}
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_STORAGE: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Intent chooserIntent = cameraHelper.openImageIntent();
startActivityForResult(chooserIntent, MY_PERMISSIONS_REQUEST_STORAGE);
}
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With