Android 问:file.mkdirs() returns 错误

Android Q: file.mkdirs() returns false

我们有一个应用程序使用外部存储来存储一些临时文件:图像、二进制数据。直到最近,它的代码已经运行了几年,没有大的变化。在 Android Q 上它不起作用:

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

mkdirs现在returns只是false

清单中提供了所需的权限:

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

该代码在 Android 的早期版本上运行良好。这种访问类型是否有一些系统级别的更改?如果是这样,解决方法是什么?

通过引入 Scoped Storage,android Q 中的隐私发生了巨大变化。

自 Q beta 4 以来,可以通过以下方式 opt-out 该功能:

  • 目标 API 28(或更低)
  • 使用 requestLegacyExternalStorage 清单属性(目标 API 29):

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

edit: 如其他答案中所述,如果应用程序的目标是 API 30 - Android 11 设备,则此操作将忽略旧存储标志。

编辑 2: 任何计划在 Play 商店发布的人请注意 - 很快将限制使用此标志(不接受新的和更新的应用程序),除非它需要核心功能(例如文件管理器)

更新: 自 Android 11 scoped storage is enforced。以 Android 10(API 级别 29)为目标的应用程序仍然可以请求 requestLegacyExternalStorage 属性。此标志允许应用程序暂时选择退出与范围存储相关的更改,例如授予对不同目录和不同类型媒体文件的访问权限。将应用更新为目标 Android 11 后,系统会忽略 requestLegacyExternalStorage 标志。


在 API 级别 29 中直接访问 shared/external 存储设备已被弃用。当应用以 Build.VERSION_CODES.Q 为目标时,应用不再可以直接访问从 getExternalStorageDirectory() 方法返回的路径。 通过迁移到 Context#getExternalFilesDir(String), MediaStore, or Intent#ACTION_OPEN_DOCUMENT.

等替代方案,应用可以继续访问存储在 shared/external 存储上的内容

最佳做法是使用分区存储,除非您的应用需要访问不在应用特定目录中的文件。

那些在 Android-Q 中遇到文件管理问题的人可以阅读 this 文章以进一步了解。

在新的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");

更新

这个答案提供了另一种解决方案

更新

另一种方法是在 manifest

中授予此权限
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />

喜欢这个回答