Не удалось открыть Android 6.0: EACCES (Permission denied)

Я добавил uses-permission включая WRITE_EXTERNAL_STORAGE, MOUNT_UNMOUNT_FILESYSTEMS, READ_EXTERNAL_STORAGE в AndroidManifest.xml.

Когда я попытался запустить мое приложение в Nexus5 (Android 6.0), он сделал исключение, как показано ниже:

java.io.IOException: open failed: EACCES (Permission denied)

И я попробовал другой Android-телефон (Android 5.1), все было в порядке. Вот код:

private File createImageFile() throws IOException {
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    String imageFileName = "JPEG_" + timeStamp + "_";
    File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
    File image = File.createTempFile(imageFileName, ".jpg", storageDir);
    currentPhotoPath = image.getAbsolutePath();
    return image;
}

Есть ли у Android 6.0 разница в разрешении?

Ответ 1

Android добавила новую модель разрешения для Android 6.0 (Marshmallow).

http://www.captechconsulting.com/blogs/runtime-permissions-best-practices-and-how-to-gracefully-handle-permission-removal

Итак, вы должны проверить Runtime Permission:

Что такое разрешения времени выполнения?

В Android 6.0 Marshmallow Google представила новую модель разрешений, которая позволяет пользователям лучше понять, почему приложение может запрашивать определенные разрешения. Вместо того, чтобы пользователь слепо принимал все разрешения во время установки, пользователю теперь предлагается принимать разрешения, поскольку они становятся необходимыми во время использования приложения.

Когда использовать новую модель?

он не требует полной поддержки, пока вы не решите настроить таргетинг версии 23 в своем приложении. Если вы настроили таргетинг на версию 22 или ниже, ваше приложение будет запрашивать все разрешения во время установки так же, как и на любом устройстве, работающем под ОС под Marshmallow.

Эта информация взята здесь:

Пожалуйста, проверьте, как реализовать по этой ссылке:

http://www.captechconsulting.com/blogs/runtime-permissions-best-practices-and-how-to-gracefully-handle-permission-removal

Ответ 2

В Android 6 (Marshmallow), несмотря на то, что пользователь принял все ваши разрешения во время установки, они могут позже решить взять некоторые из этих разрешений от вас.

Быстрое решение, но не рекомендуется:, возможно, если вы измените свой targetSdkVersion в gradle на 22, проблема будет решена.

Как реализовать? (Best Practices)

  • Сначала определите, является ли устройство пользователя устройством Marshmallow или нет:

    private boolean shouldAskPermission(){
    
    return(Build.VERSION.SDK_INT>Build.VERSION_CODES.LOLLIPOP_MR1);
    
    }
    
  • Если shouldAskPermission() вернуть true, запросите требуемое разрешение:

    String[] perms = {"android.permission.WRITE_EXTERNAL_STORAGE"};
    
    int permsRequestCode = 200;
    
    requestPermissions(perms, permsRequestCode);
    

Метод requestPermissions(String[] permissions, int requestCode); является общедоступным методом, найденным внутри класса Android Activity.

  1. Вы получите результаты вашего запроса в методе onRequestPermissionResult, как показано ниже:

    @Override
    public void onRequestPermissionsResult(int permsRequestCode, String[] permissions, int[] grantResults){
    
    switch(permsRequestCode){
    
        case 200:
    
            boolean writeAccepted = grantResults[0]==PackageManager.PERMISSION_GRANTED;
    
            break;
    
    }
    
    }
    

После получения результатов вам необходимо будет обработать их соответствующим образом.

Предлагаемый поток разрешений:

введите описание изображения здесь

Дополнительная информация:

Пользователь с устройством Marshmallow теперь сможет отменить опасные разрешения с помощью настроек приложения

Android определяет некоторые разрешения как " опасные", а некоторые разрешения - " обычный". Оба они требуются в манифесте приложений, но только для опасных разрешений требуется запрос времени выполнения.

Если вы решили не применять новую модель разрешений (запрос времени выполнения), то аннулирование разрешений может привести к нежелательным пользователям и в некоторых случаях сбой приложений.

В приведенной ниже таблице перечислены все текущие опасные разрешения и их соответствующие группы:

введите описание изображения здесь

Если пользователь принимает одно разрешение в группе/категории, он принимает всю группу!

Источник: http://www.captechconsulting.com

Использование библиотеки Dexter:

Вы можете использовать Dexter. Android-библиотека, которая упрощает процесс запроса разрешений во время выполнения.

Ответ 3

Вы также можете использовать ActivityCompat.requestPermissions для обратной совместимости.

Пример:

private static final int REQUEST_CODE = 0x11;

String[] permissions = {"android.permission.WRITE_EXTERNAL_STORAGE"};
ActivityCompat.requestPermissions(this, permissions, REQUEST_CODE); // without sdk version check

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);

    if (requestCode == REQUEST_CODE) {
        if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // save file
        } else {
            Toast.makeText(getApplicationContext(), "PERMISSION_DENIED", Toast.LENGTH_SHORT).show();
        }
    }
}

Ответ 4

Из API-23 вам нужно объявить разрешение в действии, даже если вы уже объявили в манифесте.

// Storage Permissions variables
private static final int REQUEST_EXTERNAL_STORAGE = 1;
private static String[] PERMISSIONS_STORAGE = {
        Manifest.permission.READ_EXTERNAL_STORAGE,
        Manifest.permission.WRITE_EXTERNAL_STORAGE
};

//persmission method.
 public static void verifyStoragePermissions(Activity activity) {
    // Check if we have read or write permission
    int writePermission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
    int readPermission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.READ_EXTERNAL_STORAGE);

    if (writePermission != PackageManager.PERMISSION_GRANTED || readPermission != PackageManager.PERMISSION_GRANTED) {
        // We don't have permission so prompt the user
        ActivityCompat.requestPermissions(
                activity,
                PERMISSIONS_STORAGE,
                REQUEST_EXTERNAL_STORAGE
        );
    }
}

Использовать просто вызов verifyStoragePermissions(this); в onCreate. Это должно сделать это надежно.

Ответ 5

Если вы ленивы, просто понизите targetSdkVersion до 22 (до леденца)

Ответ 6

Это сработало для меня.

Перейдите в Настройки → Приложения → YourApp → Предоставьте разрешения для хранения, контактов и т.д.

Ответ 7

Для меня мой телефон, подключенный как USB, как MTP, был проблемой даже после того, как все было сказано здесь. Для меня это переключилось на "Только зарядка".

Ответ 8

Я встретил ту же проблему.

Возможно, это вызвано механизмом безопасности вашего телефона. Вы можете перейти к настройкам, чтобы разрешить права на запись/чтение.