Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Howto avoid the "EACCES permission denied" ON SDCARD with KITKAT 4.4.2 Version. New policy from google

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 ?

like image 553
mcfly soft Avatar asked Mar 14 '14 13:03

mcfly soft


3 Answers

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.

like image 170
nikis Avatar answered Nov 18 '22 17:11

nikis


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);
}
like image 24
WiFi Avatar answered Nov 18 '22 15:11

WiFi


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);
                }
            }
        }
    }
like image 2
lucasddaniel Avatar answered Nov 18 '22 17:11

lucasddaniel