Android mkdir() возвращает false, не создает папку

Это сводит меня с ума. Я пробовал все виды синтаксисов, но и mkdir(), и mkdirs() возвращают false.

Мой код:

String extStorageDirectory = Environment.getExternalStorageDirectory().toString();

File folder = new File(extStorageDirectory, "myportal");
boolean bool = folder.mkdir();

File pdfFile = new File(folder, fileName);

try{
    pdfFile.createNewFile();
}catch (IOException e){
    e.printStackTrace();
}
FileDownloader.downloadFile(fileUrl, pdfFile);

Я получал и IOException: No such file or directory при попытке создать файл. Часть logcat показала мне, что каталог не создан:

Log.d("BG", "URL: " + fileUrl);
Log.d("BG", "pdfFile: " + pdfFile);
Log.d("BG", "Ext Storage: " + extStorageDirectory);
Log.d("BG", "Ext storage state: " + Environment.getExternalStorageState().toString());
Log.d("BG", "Mkdir return: " + bool);
Log.d("BG", "IsDirectory: " + folder.isDirectory());

И что напечатано:

05-26 22:43:03.797 19364-30646/com.kristmiha.myportal2 D/BG: URL: http://192.168.100.65:80/myportal/upload/orari.pdf
05-26 22:43:03.798 19364-30646/com.kristmiha.myportal2 D/BG: pdfFile: /storage/emulated/0/myportal/orari.pdf
05-26 22:43:03.798 19364-30646/com.kristmiha.myportal2 D/BG: Ext Storage: /storage/emulated/0
05-26 22:43:03.804 19364-30646/com.kristmiha.myportal2 D/BG: Ext storage state: mounted
05-26 22:43:03.805 19364-30646/com.kristmiha.myportal2 D/BG: Mkdir return: false
05-26 22:43:03.805 19364-30646/com.kristmiha.myportal2 D/BG: IsDirectory: false

Я дважды проверил разрешения и поместил их в нужное место. Кажется, я где-то читал, что после KitKat нам не разрешено писать во внешнее хранилище, но пока не нашел решения.


person user3484582    schedule 26.05.2016    source источник
comment
Почему вы пытаетесь создать каталоги?   -  person Michael Aaron Safyan    schedule 27.05.2016
comment
Пытаюсь скачать файл, а потом открыть.   -  person user3484582    schedule 27.05.2016
comment
На какой версии Android вы тестируете? См. также stackoverflow.com/questions/32635704/ и commonsware.com/blog/2015/08/31/   -  person CommonsWare    schedule 27.05.2016
comment
Тестирую на 6.0.1. Спасибо, посмотрю!   -  person user3484582    schedule 27.05.2016
comment
Можете ли вы посмотреть мой ответ, он хорошо работает для меня: stackoverflow.com/questions/36916703/   -  person Yasin Kaçmaz    schedule 27.05.2016
comment
Приняли ли вы RuntimePermission перед выполнением процесса записи?   -  person Vincent D.    schedule 27.05.2016
comment
Я изучаю это сейчас. Реализация requestPermission() в моем приложении. Вернусь с результатом   -  person user3484582    schedule 27.05.2016
comment
Ну, я только что реализовал requestPermission(), и происходит то же самое. У меня появилось диалоговое окно с запросом разрешений, когда я запустил приложение, нажал «Принять», и я использую logcat с checkSelfPermissions(), который возвращает 0, что означает, что разрешения предоставлены. Есть еще идеи?   -  person user3484582    schedule 27.05.2016
comment
Я решил это следующим образом. Откройте этот ответ, он поможет вам:   -  person Chirag Prajapati    schedule 16.08.2020


Ответы (5)


Для создания каталогов внешнего хранилища требуется разрешение WRITE_EXTERNAL_STORAGE; без этого разрешения попытки записи во внешнее хранилище будут неудачными. Кроме того, не все каталоги обязательно доступны для записи; используйте getExternalStoragePublicDirectory(), чтобы получить каталог с общим доступом для записи (другие внешние каталоги могут быть доступны только для чтения). Однако, если целью записи во внешнее хранилище является совместное использование файла с другими приложениями, настоятельно рекомендуется использовать FileProvider API (см. также Настройка общего доступа к файлам); с этой стратегией ваше приложение хранит файлы в своих собственных внутренних каталогах для конкретных приложений, но затем разрешает выборочный обмен этими файлами с другими приложениями через поставщика контента. Эта стратегия обеспечивает большую безопасность файлов, а также позволяет вам обеспечить больший контроль доступа при чтении/записи файлов.

Поскольку вы говорите, что у вас уже есть необходимое разрешение *, скорее всего, вы ошибаетесь в вызове toString(). Нет гарантии, что метод toString() для файла вернет его полный путь. Используйте getPath() или getAbsolutePath() при их объединении. Также рекомендуется при выборе записи во внешнее хранилище сначала проверить его состояние; внешнее хранилище в некоторых случаях может быть извлечено/размонтировано и недоступно.

*Вы должны проверить это с помощью ContextCompat.checkSelfPermission(). Вы должны добавить вызов requestPermissions(), если разрешения отсутствуют.

person Michael Aaron Safyan    schedule 26.05.2016
comment
Я использовал разрешение на запись во внешнее хранилище и дважды проверил, что оно находится в нужном месте. Хотя посмотрю что порекомендуете - person user3484582; 27.05.2016
comment
Я тоже их пробовал. Тем не менее, если вы видите логарифм, путь к файлу выглядит правильно, верно? - person user3484582; 27.05.2016
comment
@ user3484582 правда. Возможно, у вашего приложения просто нет прав доступа к этому каталогу. Метод getExternalStoragePublicDirectory() (который принимает параметр, указывающий тип файла), скорее всего, даст вам каталог, в который у вас действительно есть разрешение на запись [при условии, что вы намерены использовать общее хранилище, а не внутреннюю запись]. - person Michael Aaron Safyan; 27.05.2016
comment
Если вы видите мой оригинальный пост, я проверяю его состояние с помощью logcat, и он смонтирован. Я только что реализовал requestPermission(), и происходит то же самое. У меня появилось диалоговое окно с запросом разрешений, когда я запустил приложение, нажал «Принять», и я использую logcat с checkSelfPermissions(), который возвращает 0, что означает, что разрешения предоставлены. Есть еще идеи? - person user3484582; 27.05.2016
comment
@user3484582 user3484582 в дополнение к печати folder.isDirectory(), вы можете распечатать folder.exists()? Мне интересно, пытаетесь ли вы создать каталог с именем существующего файла. - person Michael Aaron Safyan; 27.05.2016
comment
В итоге я использовал getExternalStoragePublicDirectory(), так как не хочу, чтобы мой файл был приватным, и это работает как шарм. Проблема была не в том, что папки не существовало, иначе бы она работала, так как работает с getExternalStoragePublicDirectory(). Хотя есть один вопрос. Просматривая каталог в файловом менеджере моего телефона, я не могу найти эти папки. РЕДАКТИРОВАТЬ: это в моей папке загрузок. Спасибо за помощь! - person user3484582; 27.05.2016

Применимо, только если ваша targetSdkVersion 29

Environment.getExternalStorageDirectory() устарел на уровне API 29.

Чтобы получить ту же функциональность, используйте эту строку

File mediaStorageDir = context.getExternalFilesDir(null);

Если вы проверили все возможные ошибки, попробуйте это исправление.

person Priyankchoudhary    schedule 28.04.2020
comment
Для targetSdkVersion 29 могут быть некоторые отличия. getExternalFilesDir(null) — это каталог приложения, созданного в .../Android/data/ с именем пакета приложения. Если чье-то старое приложение создало какой-то каталог в другом месте, например, в корневом каталоге. Этот ответ не может охватить проблему, потому что это два разных каталога. Временное решение должно быть таким: developer.android .com/training/data-storage/ ‹application android:requestLegacyExternalStorage=true ... › - person Fisher; 19.09.2020

попробуй это:

String extStorageDirectory = Environment.getExternalStorageDirectory().toString();
File folder = new File(extStorageDirectory, "pdf");
folder.mkdir();

в манифесте:

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com....">
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

также, если вы тестируете на Android 6.0 + API 23, есть изменения в правах, вы должны запросить некоторые из них во время выполнения, объявление манифеста игнорируется)

person Stepan Maksymov    schedule 26.05.2016
comment
Чем этот код отличается от моего? Кроме изменения имени папки? Я уже поставил разрешения на файл манифеста. - person user3484582; 27.05.2016
comment
если тестируете на android 6.0+ начиная с api 23 некоторые права можно запросить ТОЛЬКО во время выполнения. - person Stepan Maksymov; 27.05.2016
comment
Ну, я только что реализовал requestPermission(), и происходит то же самое. У меня появилось диалоговое окно с запросом разрешений, когда я запустил приложение, нажал «Принять», и я использую logcat с checkSelfPermissions(), который возвращает 0, что означает, что разрешения предоставлены. Есть еще идеи? - person user3484582; 27.05.2016
comment
ты когда-нибудь исправлял это? - person 68060; 12.01.2018
comment
что вы имеете в виду под исправлением? - я писал выше, что вы должны запросить права на запись во внешнее хранилище вживую, прямо перед попыткой создания каталога ) поищите, пожалуйста, как проверить права, и выполните действия по результатам запроса прав. - person Stepan Maksymov; 17.01.2018

Еще одна возможная причина: Environment.getExternalStorageDirectory() устарела на уровне API 29.

person senior_russia    schedule 31.10.2019

если вы уже разрешили разрешение R/W (также разрешение на выполнение) и все еще не работает, добавьте эту строку ниже в свой AndroidManifest.xml

‹application ........ ........ android:requestLegacyExternalStorage=true› Примечание: это необходимо, если вы ориентируетесь на Android 10+

person AYUSH KUMAR SINGH    schedule 06.10.2020