Исключение «Открыть неудачу: eacces (разрешение отказано)» на Android
-
28-10-2019 - |
Вопрос
я получаю
Открыто не удалось:
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)
Разрешение здесь:
Я создаю папку под / 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, если местоположение хранилища недоступно, поэтому обязательно убедитесь, что всякий раз, когда вы проверяете, если у вас есть внешние разрешения.
Читать далее здесь.