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)
может возвращать ноль, если место хранения недоступно, поэтому обязательно проверяйте это всякий раз, когда проверяете, есть ли у вас внешние разрешения.
Подробнее здесь.