Ошибка открытия: EACCES (в доступе отказано) api23?

Я знаю о разрешениях времени выполнения и принял это во внимание, но это все еще не работает. Я добавил эти строки в манифест:

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

это мой метод onCreate:

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

это для запроса и предоставления разрешения

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);
    }
}

это методы записи и чтения

 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());
    }

ИЗМЕНИТЬ Это моя трассировка стека:

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)

person future engineer    schedule 20.02.2017    source источник
comment
requestPermissions() асинхронный. Когда он возвращается, у пользователя еще даже не спрашивали разрешение, не говоря уже о его предоставлении.   -  person CommonsWare    schedule 21.02.2017
comment
@CommonsWare Я понимаю вашу точку зрения, но не понимаю, как изменить код. Я новичок с андроидом   -  person future engineer    schedule 21.02.2017
comment
Этот материал рассматривается в любой современной книге или курсе по разработке приложений для Android и, в меньшей степени, в документация. В этом примере проекта я использую an AbstractPermissionActivity, который изолирует код, необходимый для запроса разрешений времени выполнения при запуске действия.   -  person CommonsWare    schedule 21.02.2017


Ответы (1)


Если разрешения еще не предоставлены, не следует немедленно вызывать методы, которым они нужны. Вместо этого вызовите их в onRequestPermissionsResult. Это гарантирует, что они будут выполнены только после того, как пользователь предоставит разрешения.

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);
            } 
        }
    }
}

Изменить: Кроме того, включите ContextCompat.checkSelfPermission в вашем методе shouldAskPermissions ().

Изменить 2: вот реализация для 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);
}
person Damian Jäger    schedule 20.02.2017
comment
Боюсь, это не решило проблему, я все еще получаю W / System.err: Причина: android.system.ErrnoException: open failed: EACCES (Permission denied) - person future engineer; 21.02.2017
comment
@futureengineer, пожалуйста, опубликуйте полную трассировку стека и свой новый метод shouldAskPermissions () - person Damian Jäger; 21.02.2017
comment
Просто чтобы убедиться в чем-то, прежде чем публиковать трассировку стека, чтобы не тратить время зря. Как мне изменить метод shouldAskPermissions ()? он просто проверяет версию, чтобы проверить, нужны ли ей разрешения времени выполнения. А если вы имеете в виду метод askPermissions (), я должен его изменить? он просто запрашивает разрешения, которые запускают метод onRequestPermissionsResult, который вы опубликовали в своем ответе, я что-то не понимаю? - person future engineer; 21.02.2017
comment
он по-прежнему дает ту же ошибку даже после попытки кода в отредактированном вами сообщении, я добавлю трассировку стека в свой исходный пост - person future engineer; 21.02.2017
comment
@futureengineer Я скопировал код, и он работал нормально. Убедитесь, что вы внесли все изменения правильно. - person Damian Jäger; 21.02.2017
comment
хорошо, спасибо за вашу помощь. Это работает сейчас, хотя я понятия не имею, что было не так раньше. Я только что создал новый проект и сделал все с самого начала, и теперь он отлично работает. - person future engineer; 22.02.2017