Search code examples
androidandroid-manifestandroid-permissionsandroid-fileruntime-permissions

open failed: EACCES (Permission denied) api23?


I know about the runtime permissions and I've taken that into consideration but it still doesn't work. I have added these lines to manifest:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

this is my onCreate method:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_new);
    if (shouldAskPermissions()) {
        askPermissions();
    }
    generateNoteOnSD(this,fileName,msg);
    readFile(fileName);
}

this is for asking and granting permission

protected static boolean shouldAskPermissions() {
    return (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1);
}

@TargetApi(23)
protected void askPermissions() {
    String[] permissions = {
            "android.permission.READ_EXTERNAL_STORAGE",
            "android.permission.WRITE_EXTERNAL_STORAGE"
    };
  /*  int requestCode = 200;
    requestPermissions(permissions, requestCode);*/
    // Check if we have write permission
    int permission = ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);

    if (permission != PackageManager.PERMISSION_GRANTED) {
        // We don't have permission so prompt the user
        ActivityCompat.requestPermissions(
                this, permissions, 1);
    }
}

and these are the writing and reading methods

 public static void generateNoteOnSD(Context context, String sFileName, String sBody) {
        try {
            File root = new File(String.valueOf(Environment.getExternalStorageDirectory()));
            Log.e("file path is ", String.valueOf(Environment.getExternalStorageDirectory()));
            if (!root.exists()) {
                root.mkdirs();
            }
            File gpxfile = new File(root, sFileName);
            String separator = System.getProperty("line.separator");

            FileWriter writer = new FileWriter(gpxfile.getAbsoluteFile(), true);
            writer.append(separator); // this will add new line ;

            //FileWriter writer = new FileWriter(gpxfile);
            writer.append(sBody);
            writer.flush();
            writer.close();
            Toast.makeText(context, "Saved", Toast.LENGTH_SHORT).show();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public void readFile(String file1){
        //Find the directory for the SD Card using the API
//*Don't* hardcode "/sdcard"
        File sdcard = Environment.getExternalStorageDirectory();

//Get the text file
        File file = new File(sdcard,file1);

//Read text from file
        StringBuilder text = new StringBuilder();

        try {
            BufferedReader br = new BufferedReader(new FileReader(file));
            String line;

            while ((line = br.readLine()) != null) {
                text.append(line);
                text.append('\n');
            }
            br.close();
        }
        catch (IOException e) {
            //You'll need to add proper error handling here
        }

//Find the view by its id
        Log.e("text",text.toString());
    }

EDIT This is my stacktrace:

W/System.err: java.io.FileNotFoundException: /storage/emulated/0/CrowdSensingData: open failed: EACCES (Permission denied)
W/System.err:     at libcore.io.IoBridge.open(IoBridge.java:487)
W/System.err:     at java.io.FileOutputStream.<init>(FileOutputStream.java:87)
W/System.err:     at java.io.FileWriter.<init>(FileWriter.java:58)
W/System.err:     at enis.example.com.alarmmanagertest.FileAndServerHandlingActivity.generateNoteOnSD(FileAndServerHandlingActivity.java:128)
W/System.err:     at enis.example.com.alarmmanagertest.ActivityRecognitionService.handleDetectedActivities(ActivityRecognitionService.java:107)
W/System.err:     at enis.example.com.alarmmanagertest.ActivityRecognitionService.onStart(ActivityRecognitionService.java:122)
W/System.err:     at android.app.Service.onStartCommand(Service.java:459)
W/System.err:     at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3209)
W/System.err:     at android.app.ActivityThread.-wrap17(ActivityThread.java)
W/System.err:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1586)
W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:111)
W/System.err:     at android.os.Looper.loop(Looper.java:207)
W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:5728)
W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
W/System.err:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:679)
W/System.err: Caused by: android.system.ErrnoException: open failed: EACCES (Permission denied)
W/System.err:     at libcore.io.Posix.open(Native Method)
W/System.err:     at libcore.io.BlockGuardOs.open(BlockGuardOs.java:186)
W/System.err:     at libcore.io.IoBridge.open(IoBridge.java:473)

Solution

  • If the permissions are not granted yet you should not call methods which need them immediately. Call them in onRequestPermissionsResult instead. This guarantees that they only get executed as soon as the permissions are granted by the user.

    if (shouldAskPermissions()) {
        askPermissions();
    } else {
        generateNoteOnSD(this,fileName,msg);
        readFile(fileName);
    }
    
    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
            case 1: {
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    generateNoteOnSD(this,fileName,msg);
                    readFile(fileName);
                } 
            }
        }
    }
    

    Edit: Furthermore, include ContextCompat.checkSelfPermission in your shouldAskPermissions() method.

    Edit 2: Here's an implementation for shouldAskPermissions()

    protected boolean shouldAskPermissions() {
        if(Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP_MR1) {
            return false;
        }
        int permission = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
        return  (permission != PackageManager.PERMISSION_GRANTED);
    }