22

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 ?

mcfly soft
  • 11,289
  • 26
  • 98
  • 202

4 Answers4

9

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.

nikis
  • 11,166
  • 2
  • 35
  • 45
  • 10
    This change in SD card security/permission is breaking apps left and right. It might help apps clean up files on uninstall moving forward but devices are receiving Android updates with this new rule and it is orphaning files on the user's SD Cards because existing apps no longer have permissions to delete or move files from previously-writable folders. It's immensely frustrating. – Robert Nekic Mar 14 '14 at 20:57
  • 1
    This is really a bad change for both users and developers. for an extra bit of history : http://www.androidpolice.com/2014/02/17/external-blues-google-has-brought-big-changes-to-sd-cards-in-kitkat-and-even-samsung-may-be-implementing-them/ . – Mohamed El-Nakeep Mar 20 '14 at 23:58
  • Ironically, it breaks their own examples from [their tutorial](http://developer.android.com/training/camera/photobasics.html) – G_V Nov 12 '14 at 08:45
  • For me there should be a simple rule, if something worked in the old version of Android, it should work in all new versions. Otherwise we are risking that user install app and thinks "what a bad developer". Moreover it's not possible to test app on all versions of Android (especially if you are not a big company but just someone developing for pleasure). With every day Google is making me more irritated because of their approach. – user2707175 Sep 13 '15 at 19:32
7

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);
}
Pokechu22
  • 4,984
  • 9
  • 37
  • 62
WiFi
  • 133
  • 1
  • 8
2

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);
                }
            }
        }
    }
lucasddaniel
  • 1,779
  • 22
  • 22
  • I think this is not the only change. The change also happened in path returned by most usual classes, now it is no more direct clean path but it includes ID of a resource, hard or impossible to get path out of it. – Ahmad Ebrahimi Dec 15 '16 at 16:02
0

The only solution as of now is this problem can only be solved by rooting your phone and changing permissions of the ext sdcard from the root directory using file explorers,which is not recommended as it voids yours phone's warranty and also triggers some security apps like KNOX in phones like samsung galaxy S5 S4 Note3 and also Note2.

Sorry for posting this bitter fact.

lets hope an update from the google itself who can put us out of this situation.

But also think before updating jellybean to kitkat as the JB is most convenient OS of Android. and the difference b/w JB & Kitkat is not so high.

Hope I Helped U......