Исключение «Открыть неудачу: eacces (разрешение отказано)» на Android

StackOverflow https://stackoverflow.com/questions/8854359

Вопрос

я получаю

Открыто не удалось: 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();
}
Это было полезно?

Решение

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

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

А uses-permission тег должен быть за пределами application ярлык.

Другие советы

Для 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

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

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

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

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

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

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

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

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

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

У меня была та же проблема на 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, а с ним разрешение на чтение.

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

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

Обманывать: Если вы нацелены на версию 22 или ниже, ваше приложение запросит все разрешения во время установки, как и на любом устройстве, работающем с ОС под зефиром. Если вы примеряете эмулятор, то с Android 6.0 вам необходимо явно перейти на настройки-> Приложения-> yourapp-> разрешения и изменить разрешение, если вы дали.

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

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

Я ожидаю все ниже /data принадлежать к «внутренней памяти». Вы должны, однако, иметь возможность написать /sdcard.

Изменить свойство разрешения в вашем /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>

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

Странно, положив склад "/" перед моим новый файл Моя проблема была решена. Я изменил это:

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

к этому:

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

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

Имейте в виду, что даже если вы устанавливаете все правильные разрешения в манифесте: единственным местам, которое сторонним приложениям разрешено писать на вашей внешней карте, являются «их собственные каталоги» (т.е./SDCARD/Android/Data/) Пытаться написать В любом месте: вы получите исключение: eacces (разрешение отказано)

Может быть, ответ:

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

В моем случае я использовал Библиотека сборщика файлов который вернул путь к внешнему хранилищу, но начался с /root/. Анкет И даже с Write_external_storage разрешение, предоставленное во время выполнения, я все еще получил ошибку Eacces (разрешение отказано).
Так используйте 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
Environment.getExternalStoragePublicDirectory();

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

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

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

GetExternalStoragePublicDirectory устарел в Android Q

Я создаю папку под / data / in in init.rc (мила с AOSP на Nexus 7) и имел именно эту проблему.

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

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

root@msm8996:/ # getenforce
getenforce
Enforcing
root@msm8996:/ # setenforce 0
setenforce 0
root@msm8996:/ # getenforce
getenforce
Permissive

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

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

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

<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"/>

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

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

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

Решение https://stackoverflow.com/a/13569364/1729501 Работал на меня, но это было не практично отключить приложение для отладки.

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

Шаг 1: Загрузите драйверы ADB для бренда вашего устройства.

Шаг 2: Перейдите к диспетчере устройств -> Другие устройства -> Ищите записи с Word "ADB" -> Выберите Драйвер обновления -> Дайте местоположение на шаге 1

Добавить зависимости Градл

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

Строительство ответа User462990

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

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.
    }
}

}

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

      target.createNewFile();

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

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

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

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

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

Для тех, кто приезжает сюда из результатов поиска и нацеливается на Android 10: Android 10 (API 29) изменяет некоторые разрешения, связанные с хранением.

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

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

Читать далее здесь.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top