Android Q: file.mkdirs() возвращает false

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

File f = new File(Environment.getExternalStorageDirectory().toString() + File.separator + MainActivity.APP_DIR)
f.mkdirs();
// do sth with f

mkdirs теперь возвращает просто false.

Требуемое разрешение указано в манифесте:

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

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

См. следующий ответ ниже: stackoverflow.com/a/50571167/3736063

Malek Tubaisaht 15.08.2020 14:16
32
1
18 305
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

В Android Q были внесены огромные изменения в конфиденциальность, когда был введен Хранилище с заданным объемом.

Начиная с Q beta 4, можно сделать уклоняться этой функции следующим образом:

  • таргетинг на API 28 (или ниже)
  • используя атрибут манифеста requestLegacyExternalStorage (при нацеливании на API 29):

<manifest ... >
  <!-- This attribute is "false" by default on apps targeting Android Q. -->
  <application android:requestLegacyExternalStorage = "true" ... >
    ...
  </application>
</manifest>

редактировать:, как упоминалось в другом ответе, не работает, если приложение нацелено на API 30 — устройства Android 11 будут игнорировать устаревший флаг хранилища.

редактировать 2: предупреждает всех, кто планирует публиковать в магазине игр — скоро использование этого флага будет ограничено (новые и обновленные приложения не будут приниматься), если только это не требуется для основных функций (например, файлового менеджера).

Разве он не просит Android Pie? Но я думаю, что вы решаете проблемы, связанные с Android Q.

exploitr 30.06.2019 13:10

@Toaster, ты прав, я ответил поздно ночью. По какой-то странной причине я думал, что 9 уже Q.

Pawel 30.06.2019 13:34

Ха-ха, это нормально. Просто обновите ответ в свободное время.

exploitr 30.06.2019 13:37

@Pawel Похоже, не только ты был сонным, я не обратил внимания - изображение, которое я проверял, действительно было Q (эмулятор 9+). Проверил на 9 - все нормально, так что перефразируй вопрос и принимай

khusrav 30.06.2019 21:37

@khusrav вот что я думал, не видел причин, по которым этот код не работал бы на P, но знал, что в Q возникнут проблемы.

Pawel 30.06.2019 21:40

@khusrav Ну, это была катастрофа. :-D

exploitr 03.07.2019 20:20

Я обновил свою версию SDK до 29 и добавил этот атрибут, но все еще сталкиваюсь с той же проблемой. Есть ли что-то еще, что мне не хватает? моя версия андроида "10QP1A"

Zainab Rostami 07.03.2020 11:55

Да, у меня это работает, я только что добавил android:requestLegacyExternalStorage = "true" в API 29 или выше.

prototype86 20.09.2020 11:27

Обновлено: Начиная с Android 11 ограниченное хранилище принудительно. Приложения, предназначенные для Android 10 (уровень API 29), по-прежнему могут запрашивать атрибут requestLegacyExternalStorage. Этот флаг позволяет приложениям временно отказаться от изменений, связанных с хранилищем с заданной областью, таких как предоставление доступа к различным каталогам и различным типам медиафайлов. После того, как вы обновите свое приложение до Android 11, система игнорирует флаг requestLegacyExternalStorage.


В уровне API 29 прямой доступ к общим/внешним устройствам хранения не рекомендуется. Когда приложение нацелено на Build.VERSION_CODES.Q, путь, возвращаемый из метода getExternalStorageDirectory(), больше не доступен приложениям напрямую. Приложения могут продолжать получать доступ к содержимому, хранящемуся в общем/внешнем хранилище, путем перехода на такие альтернативы, как Контекст # getExternalFilesDir (строка), Медиасторе или Намерение#ACTION_OPEN_DOCUMENT.

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

Те, кто сталкивается с проблемой управления файлами в Android-Q, могут прочитать статью это, чтобы узнать больше.

@RonTLV Обновлен ответ с предварительным просмотром 3 изменений конфиденциальности для разработчиков Android11.

Anoop M Maddasseri 05.05.2020 09:55

В новом обновлении Android API 30 писать можно только в app-specific files

 File directory = new File(context.getFilesDir(), "YOUR_DIR");
 directory.mkdirs();

или во внешнем хранилище вашего приложения Android/data

File directory = new File(myContext.getExternalFilesDir("FolderName"),"YOUR_DIR");

ОБНОВИТЬ

этот ответ предоставил другое решение https://stackoverflow.com/a/65744517/8195076

ОБНОВИТЬ

другой способ - предоставить это разрешение в manifest

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

нравится этот ответ https://stackoverflow.com/a/66968986/8195076

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