Exception 'open failed: EACCES (Permission denied)' на Android

Я получаю

open failed: EACCES (Permission denied)

на линии OutputStream myOutput = new FileOutputStream(outFileName);

Я проверил корень, и я попробовал android.permission.WRITE_EXTERNAL_STORAGE.

Как я могу исправить эту проблему?

try {
    InputStream myInput;

    myInput = getAssets().open("XXX.db");

    // Path to the just created empty db
    String outFileName = "/data/data/XX/databases/"
            + "XXX.db";

    // Open the empty db as the output stream
    OutputStream myOutput = new FileOutputStream(outFileName);

    // Transfer bytes from the inputfile to the outputfile
    byte[] buffer = new byte[1024];
    int length;
    while ((length = myInput.read(buffer)) > 0) {
        myOutput.write(buffer, 0, length);
    }

    // Close the streams
    myOutput.flush();
    myOutput.close();
    myInput.close();
    buffer = null;
    outFileName = null;
}
catch (IOException e1) {
    // TODO Auto-generated catch block
    e1.printStackTrace();
}

Ответы

Ответ 1

У меня была та же проблема... <uses-permission оказался не в том месте. Это правильно:

 <manifest>
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
        ...
        <application>
            ...
            <activity> 
                ...
            </activity>
        </application>
    </manifest> 

Тег uses-permission должен находиться вне тега application.

Ответ 2

Для API 23+ вам необходимо запросить разрешения на чтение и запись, даже если они уже находятся в вашем манифесте.

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

/**
 * Checks if the app has permission to write to device storage
 *
 * If the app does not has permission then the user will be prompted to grant permissions
 *
 * @param activity
 */
public static void verifyStoragePermissions(Activity activity) {
    // Check if we have write permission
    int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);

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

AndroidManifest.xml

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

Для официальной документации о запросе разрешений для API 23+, проверьте https://developer.android.com/training/permissions/requesting.html

Ответ 3

Я наблюдал это один раз при запуске приложения внутри эмулятора. В настройках эмулятора вам необходимо правильно указать размер внешней памяти ( "SD-карта" ). По умолчанию поле "внешнее хранилище" пустое, и это, вероятно, означает, что такого устройства нет, а EACCES выбрасывается, даже если разрешения выдаются в манифесте.

Ответ 4

В дополнение ко всем ответам убедитесь, что вы не используете свой телефон в качестве USB-накопителя.

У меня была та же проблема, что и в HTC Sensation на USB-накопителе. Я все еще могу отлаживать/запускать приложение, но не могу сохранить его на внешнем хранилище.

Ответ 5

Моя проблема была с "TargetApi (23)", которая необходима, если ваша minSdkVersion приведена ниже.

Итак, у меня есть разрешение на запрос со следующим фрагментом

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

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
// ...
    if (shouldAskPermissions()) {
        askPermissions();
    }
}

Ответ 6

Я испытываю то же самое. Я обнаружил, что если вы идете в Настройки → Диспетчер приложений → Ваше приложение → Разрешения → Включить хранилище, это решает проблему.

Ответ 7

Оказалось, это была глупая ошибка, так как у меня был телефон, который все еще подключен к настольному ПК и не понимал этого.

Поэтому мне пришлось отключить USB-соединение, и все сработало нормально.

Ответ 8

У меня была та же проблема на Samsung Galaxy Note 3, на которой запущен CM 12.1. Проблема для меня заключалась в том, что у меня был

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

и ему пришлось использовать его для хранения и хранения фотографий пользователей. Когда я попытался загрузить те же фотографии в ImageLoader, я получил ошибку (Permission denied). Решение заключалось в том, чтобы явно добавить

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

поскольку указанное выше разрешение ограничивает только разрешение на запись до версии API версии 18 и с ним разрешено чтение.

Ответ 9

В Google есть новая функция Android Q: фильтрованное представление для внешнего хранилища. Быстрое решение проблемы - добавить этот код в файл AndroidManifest.xml:

<manifest ... >
    <!-- This attribute is "false" by default on apps targeting Android Q. -->
    <application android:requestLegacyExternalStorage="true" ... >
     ...
    </application>
</manifest>

Вы можете узнать больше об этом здесь: https://developer.android.com/preview/privacy/scoped-storage

Ответ 10

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

Уловка: если вы ориентируетесь на версию 22 или ниже, ваше приложение будет запрашивать все разрешения во время установки так же, как и на любом устройстве, работающем под ОС ниже Marshmallow. Если вы пытаетесь использовать эмулятор, то начиная с Android 6.0 и далее вам нужно явно перейти к разрешениям settings-> apps-> YOURAPP → и изменить разрешение, если вы его предоставили.

Ответ 11

У меня была та же проблема, и ни одна из предложений не помогла. Но я нашел интересную причину этого, на физическом устройстве, Galaxy Tab.

Когда USB-накопитель включен, разрешения на чтение и запись на внешние хранилища не оказывают никакого эффекта. Просто отключите USB-накопитель, и с правильными разрешениями проблема будет решена.

Ответ 12

Я ожидал бы, что все ниже /data принадлежит к "внутреннему хранилищу". Однако вы должны написать /sdcard.

Ответ 13

Измените свойство разрешения в /system/etc/permission/platform.xml
и группа должна указывать, как показано ниже.

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE">
    <group android:gid="sdcard_rw" />
    <group android:gid="media_rw" />    
</uses-permission>

Ответ 14

У меня была такая же ошибка при попытке записать изображение в папке DCIM/камеры на Galaxy S5 (android 6.0.1), и я понял, что только эта папка ограничена. Я просто мог писать в DCIM/любую папку, но не в камеру. Это должно быть ограничение/настройка на основе бренда.

Ответ 15

Странно после того, как поместил черту "/" перед моей newFile, моя проблема была решена. Я изменил это:

File myFile= new File(Environment.getExternalStorageDirectory() + "newFile");

:

File myFile= new File(Environment.getExternalStorageDirectory() + "/newFile");

Ответ 16

Когда ваше приложение принадлежит системному приложению, оно не может получить доступ к SD-карте.

Ответ 17

имейте в виду, что даже если вы установили все правильные разрешения в манифесте: единственное место, в которое сторонним приложениям разрешено писать на вашу внешнюю карту, это "их собственные каталоги" (т.е./sdcard/Android/data/), пытающиеся записать в в другом месте: вы получите исключение: EACCES (В доступе отказано)

Ответ 18

Возможно, ответ таков:

на API >= 23 устройства, если вы устанавливаете приложение (приложение не является системным приложением), вы должны проверить разрешение на хранение в "Настройках - приложениях", есть список разрешений для каждого приложения, вы должны его проверить! попробуйте

Ответ 19

В моем случае я использовал сборщик файлов, который вернул путь к внешнему хранилищу, но начался с /root/. И даже с разрешения WRITE_EXTERNAL_STORAGE, предоставленного во время выполнения, я все еще получил ошибку EACCES (Permission denied).
Поэтому используйте Environment.getExternalStorageDirectory(), чтобы получить правильный путь к внешнему хранилищу.

Пример:
Невозможно написать: /root/storage/emulated/0/newfile.txt
Может написать: /storage/emulated/0/newfile.txt

boolean externalStorageWritable = isExternalStorageWritable();
File file = new File(filePath);
boolean canWrite = file.canWrite();
boolean isFile = file.isFile();
long usableSpace = file.getUsableSpace();

Log.d(TAG, "externalStorageWritable: " + externalStorageWritable);
Log.d(TAG, "filePath: " + filePath);
Log.d(TAG, "canWrite: " + canWrite);
Log.d(TAG, "isFile: " + isFile);
Log.d(TAG, "usableSpace: " + usableSpace);

/* Checks if external storage is available for read and write */
public boolean isExternalStorageWritable() {
    String state = Environment.getExternalStorageState();
    if (Environment.MEDIA_MOUNTED.equals(state)) {
        return true;
    }
    return false;
}

Выход 1:

externalStorageWritable: true
filePath: /root/storage/emulated/0/newfile.txt
isFile: false
usableSpace: 0

Выход 2:

externalStorageWritable: true
filePath: /storage/emulated/0/newfile.txt
isFile: true
usableSpace: 1331007488

Ответ 20

Environment.getExternalStoragePublicDirectory();

При использовании этого устаревшего метода с Android 29 и далее вы получите ту же ошибку:

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

Разрешение здесь:

getExternalStoragePublicDirectory устарела в Android Q

Ответ 21

Я создаю папку под/data/в моем init.rc(сбрасывая с помощью aosp на Nexus 7) и имел именно эту проблему.

Оказалось, что предоставление разрешения rw (666) для папки было недостаточным, и это должно было быть rwx (777), тогда все это сработало!

Ответ 22

Применять разрешения хранилища post 6.0 можно обойти, если у вас есть корневое устройство через эти команды adb:

[email protected]:/ # getenforce
getenforce
Enforcing
[email protected]:/ # setenforce 0
setenforce 0
[email protected]:/ # getenforce
getenforce
Permissive

Ответ 23

Решение для Android Q:

<application ...
    android:requestLegacyExternalStorage="true" ... >

Ответ 24

Добавить разрешение в манифест.

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

Ответ 25

после добавления разрешения решил мою проблему

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

Ответ 26

У меня была та же проблема (API >= 23).

Решение fooobar.com/questions/34167/... работало для меня, но было нецелесообразно отключать приложение для отладки.

Моим решением было установить правильный драйвер устройства adb в Windows. Драйвер USB Google не работал для моего устройства.

ШАГ 1: Загрузите драйверы adb для вашего устройства.

ШАГ 2. Перейдите в диспетчер устройств → другие устройства → найдите записи со словом "adb" → выберите "Обновить драйвер" → укажите местоположение на шаге 1

Ответ 27

Добавить зависимости gradle

implementation 'com.karumi:dexter:4.2.0'

Добавьте ниже код в вашей основной деятельности.

import com.karumi.dexter.Dexter;
import com.karumi.dexter.MultiplePermissionsReport;
import com.karumi.dexter.PermissionToken;
import com.karumi.dexter.listener.PermissionRequest;
import com.karumi.dexter.listener.multi.MultiplePermissionsListener;
    @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_splash);

    new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {


                checkMermission();
            }
        }, 4000);
    }

    private void checkMermission(){
        Dexter.withActivity(this)
                .withPermissions(
                        android.Manifest.permission.READ_EXTERNAL_STORAGE,
                        android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
                        android.Manifest.permission.ACCESS_NETWORK_STATE,
                        Manifest.permission.INTERNET
                ).withListener(new MultiplePermissionsListener() {
            @Override
            public void onPermissionsChecked(MultiplePermissionsReport report) {
                if (report.isAnyPermissionPermanentlyDenied()){
                    checkMermission();
                } else if (report.areAllPermissionsGranted()){
                    // copy some things
                } else {
                    checkMermission();
                }

            }
            @Override
            public void onPermissionRationaleShouldBeShown(List<PermissionRequest> permissions, PermissionToken token) {
                token.continuePermissionRequest();
            }
        }).check();
    }

Ответ 28

Опираясь на ответ пользователя 462990

Чтобы получать уведомления, когда пользователь отвечает на диалог запроса разрешения, используйте это: (код в kotlin)

override fun onRequestPermissionsResult(requestCode: Int,
                           permissions: Array<String>, grantResults: IntArray) {
when (requestCode) {
    MY_PERMISSIONS_REQUEST_READ_CONTACTS -> {
        // If request is cancelled, the result arrays are empty.
        if ((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)) {

            // permission was granted, yay! Do the
            // contacts-related task you need to do.

        } else {

            // permission denied, boo! Disable the
            // functionality that depends on this permission.

        }
        return
    }

    // Add other 'when' lines to check for other
    // permissions this app might request.

    else -> {
        // Ignore all other requests.
    }
}

}

Ответ 29

В моем случае ошибка появлялась на линии

      target.createNewFile();

так как я не мог создать новый файл на SD-карте, поэтому мне пришлось использовать подход DocumentFile.

      documentFile.createFile(mime, target.getName());

Для вышеуказанного вопроса проблема может быть решена с помощью этого подхода,

    fos=context.getContentResolver().openOutputStream(documentFile.getUri());

См. Также эту ветку. Как использовать новый API доступа к SD-карте, представленный для Android 5.0 (Lollipop)?

Ответ 30

Android 10 (API 29) изменяет некоторые разрешения, связанные с хранением.

Я исправил эту проблему, когда заменил мои предыдущие экземпляры Environment.getExternalStorageDirectory() (который устарел в API 29) на context.getExternalFilesDir(null).

Обратите внимание, что context.getExternalFilesDir(type) может возвращать ноль, если место хранения недоступно, поэтому обязательно проверяйте это всякий раз, когда проверяете, есть ли у вас внешние разрешения.

Подробнее здесь.