mkdirs возвращает false для каталога на SD-карте, в то время как родительский каталог доступен для записи

При запуске моего приложения для Android мне нужно создать каталог на SD-карте, у небольшого количества пользователей это не удается, и я не могу понять причину этого...

(Я обнаружил аналогичные проблемы, вызванные отсутствием разрешения WRITE_EXTERNAL_STORAGE, оно есть и работает почти для всех пользователей, поэтому я не думаю, что это причина)

Я упростил предыдущую ситуацию, чтобы упростить объяснение: если создание каталога не удается, я запускаю тестовый пример, в котором пытаюсь создать каталог .test на SD-карте:

new File(Environment.getExternalStorageDirectory(), ".test").mkdir() -> false
new File(Environment.getExternalStorageDirectory(), ".test").mkdirs() -> false

Свойства файлов соответствующих каталогов:

/sdcard/.test (exists=false canWrite=false canRead=false canExecute=err isDirectory=false isFile=false)

/sdcard (существует=true canWrite=true canRead=true canExecute=err isDirectory=true isFile=false)

/ (exists=true canWrite=false canRead=true canExecute=err isDirectory=true isFile=false)

getExternalStorageState=установлен

(canExecute возвращает ошибку, потому что тест выполняется на SDK ‹ 9)

Предложения и идеи очень приветствуются...


person Danny    schedule 31.10.2010    source источник
comment
Не могли бы вы показать код, в котором вы пытаетесь создать каталог? Например, если у вас жестко подключен /sdcard, это может быть вашей проблемой.   -  person CommonsWare    schedule 31.10.2010
comment
@CommonsWare: я использую Environment.getExternalStorageDirectory() и думаю о переходе на Context.getExternalFilesDir(null), как только решу эту проблему... Я отредактирую исходный пост с кодом.. Спасибо за быстрый ответ!   -  person Danny    schedule 31.10.2010
comment
Имейте в виду, что getExternalFilesDir() существует только для Android 2.2 и не работает в этом выпуске. Я бы придерживался вашей текущей стратегии в обозримом будущем.   -  person CommonsWare    schedule 31.10.2010
comment
Вы нашли решение?   -  person xmen    schedule 11.06.2014


Ответы (14)


Это распространено, когда у вас нет разрешения в вашем манифесте.

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

Что касается меня, это была единственная ошибка.

person Vladimir Ivanov    schedule 31.10.2010
comment
У меня есть эта проблема только для очень небольшого числа пользователей, и мой AndroidManifest.xml имеет разрешение WRITE_EXTERNAL_STORAGE внутри тега манифеста, поэтому мне жаль говорить, что это не причина. - person Danny; 31.10.2010

У меня была аналогичная проблема, и я потратил несколько часов, чтобы понять, что не так. На Sumsung Mega это не работало, но на других телефонах работало нормально. У меня действительно было разрешение WRITE_EXTERNAL_STORAGE, а getExternalStorageDirectory смонтирован и доступен. Но все же каталог не был создан. Что помогло? Я только что перезагрузил устройство! И это помогло! Жаль, что никто не посоветовал это раньше. Надеюсь, это поможет!

person Andrey_yog    schedule 29.05.2015

Прежде всего, технически mkdirs(), возвращающая false, не означает, что она не удалась, это просто означает, что она не создала каталоги. Если каталоги уже существуют, то mkdirs() продолжит возвращать false.

Во-вторых, в Android 6 нужно не только:

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

Вам также понадобится некоторый эквивалент:

ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED

Дополнительную информацию о проверке разрешений см. на странице:
https://github.com/googlesamples/android-RuntimePermissions

person swooby    schedule 17.02.2016
comment
И что делать, если разрешение не дано? Как правильно запросить? - person Robert Navado; 24.03.2017

У меня также были проблемы с созданием каталогов на SDCard. Я обнаружил, что мой код будет нормально работать на некоторых телефонах, а также на эмуляторе. Однако другие телефоны будут сообщать об ошибках.

Я считаю, что есть проблема с некоторыми телефонами, например, Atrix и Bionic.

Эти телефоны при использовании кода Environment.getExternalStorageDirectory() фактически возвращают /mnt/sdcard.

Однако на этих телефонах SD-карта на самом деле /mnt/sdcard-ext.

Так что где-то по ходу дела похоже, что некоторые производители взломали код getExternalStorageDirectory и каким-то образом возвращают ложное местоположение.

У меня было чертовски много времени, чтобы понять это, потому что мой код работал на многих разных устройствах, и все же некоторые пользователи сообщали, что он не работал.

person BJGApps    schedule 11.10.2011

Моя проблема заключалась в том, что я использовал mkdir для создания пути к нескольким каталогам, и каждый раз получал false. Как только я использовал mkdirs, моя проблема была решена

person Mohsen Afshin    schedule 25.07.2013

У меня такая же проблема. Разрешение было установлено, а также путь был по умолчанию (/mnt/sdcard), но мой андроид был смонтирован как внешнее запоминающее устройство для быстрого просмотра SD-карты. Однако это мешает другим приложениям.

Я понял это, погрузившись в оболочку adb:

$ cd /mnt   
$ cd sdcard
cd: can't cd to sdcard
$ ls -l
d--------- system   system            2011-12-07 01:59 sdcard

после размонтирования образа у меня получилось:

$ ls -l                   
drwxrwxr-x system   sdcard_rw          2011-12-07 11:46 sdcard

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

person nuala    schedule 07.12.2011

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

person Phil    schedule 03.01.2012

Я думал, что у меня возникла эта проблема при отладке приложения. Это не удалось, потому что SD-карта была смонтирована хост-компьютером во время отладки. После отключения от компьютера приложение снова заработало.

person Jason    schedule 10.09.2012
comment
Может быть, я ошибаюсь, но технически это тот же ответ, что и мой, только с меньшим количеством слов… :| - person nuala; 14.08.2014

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

person hackbod    schedule 31.10.2010
comment
Я не думаю, что это все, я использую developer.android .com/reference/android/os/, чтобы проверить это, и он дает установленный, он должен дать Mounted_ro в вашей ситуации, я думаю... Спасибо, хотя.. - person Danny; 12.12.2010

Я столкнулся с этой проблемой, когда символическая ссылка /storage/emulated/0 почему-то отсутствовала. Что я сделал, так это использовал приложение камеры, чтобы сделать снимок. Я заметил, что в деталях изображений указано, что он находится в /storage/emulated/0, хотя этот каталог не существует в проводнике. Потом я перезагрузил телефон. После перезагрузки каталог появился в проводнике.

person Frank Schwieterman    schedule 09.09.2014

У меня была аналогичная проблема. Мое приложение камеры работало нормально во всех версиях Android, кроме Q (10).

Проблема заключалась в том, что я использовал Environment.getExternalStorageDirectory();, и он устарел в Android Q (и далее). Решение было простым, используя то, что поддерживалось в последней версии, которая будет context.getExternalFilesDir()

Вот как я заставляю его работать на всех устройствах: -

public static boolean createDirectory(Context context, String directoryPath) {
    File folder;

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
        folder = new File(context.getExternalFilesDir(null), directoryPath);
    else
        folder = new File(Environment.getExternalStorageState(), directoryPath);

    if (!folder.exists()) {
        return folder.mkdirs();
    }

    return true;
}
person Utsav Barnwal    schedule 11.04.2020

Это также может произойти, если вы ориентируетесь на SDK 29 или выше (targetSdkVersion в build.gradle) из-за введения хранилища с заданной областью. Если это так, либо измените целевой SDK на 28 или ниже, либо добавьте: android:requestLegacyExternalStorage="true" в свой манифест в разделе Ключ приложения.

person MelOS    schedule 09.09.2020

У меня возникла аналогичная проблема при использовании mkdirs(), однако из-за выполнения команды:

мкдир один/два

не работает в Linux, то API (http://download.oracle.com/javase/1.4.2/docs/api/java/io/File.html#mkdirs()) также не работает. Я предполагаю, что это означает, что нет возможности использовать mkdirs на Android? Мой (вероятно, довольно хакерский) обходной путь заключался в том, чтобы создать каждый необходимый каталог отдельно:

String extStorageDirectory = Environment.getExternalStorageDirectory().toString();
new File(extStorageDirectory + "/one/").mkdirs();
new File(extStorageDirectory + "/one/two/).mkdirs();
person Fofx    schedule 08.04.2011

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

person treatheat    schedule 18.09.2014