Android中mkdir()返回false,未创建文件夹

6
这让我很疯狂。我已经尝试了各种语法,但是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的错误提示。日志部分显示没有创建目录:

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之后我们不允许在外部存储器中写入,但是我还没有找到解决方案。


我正在6.0.1上进行测试。谢谢,我会看一下! - user3484582
你能看一下我的回答吗?对我来说它运行良好:http://stackoverflow.com/questions/36916703/how-to-create-a-directory-and-save-a-picture-to-it-in-android/36917734#36917734 - Yasin Kaçmaz
在进行写入操作之前,您是否已经接受了RuntimePermission? - Vincent D.
我正在研究这个。在我的应用程序中实现requestPermission()。将会回复结果。 - user3484582
我刚刚实现了requestPermission(),但是情况依旧如此。当我启动应用程序并按下接受时,会出现请求权限的对话框,我正在使用checkSelfPermissions()和logcat,它返回0,表示已授予权限。还有更多想法吗? - user3484582
显示剩余4条评论
8个回答

9

仅适用于 targetSdkVersion 29

在 API 级别 29 中,Environment.getExternalStorageDirectory() 已被弃用。

要获得相同的功能,请使用此行代码。

File mediaStorageDir = context.getExternalFilesDir(null);

如果您已经检查了所有可能的错误,请尝试此修复方法。


1
对于targetSdkVersion 29,可能会有一些不同。getExternalFilesDir(null)是应用程序的目录,它位于.../Android/data/与应用程序包名称一起创建。 如果某人的旧应用程序在其他地方创建了一些目录,例如在根目录中。这个答案无法涵盖这个问题,因为它们是两个不同的目录。一个临时解决方案应该是这样的: https://developer.android.com/training/data-storage/use-cases#opt-out-scoped-storage<application android:requestLegacyExternalStorage="true" ... > - Fisher

5
创建外部存储目录需要WRITE_EXTERNAL_STORAGE权限;没有此权限,尝试写入外部存储将会失败。此外,并非所有目录都可写入;使用getExternalStoragePublicDirectory()获取具有共享写入访问权限的目录(其他外部目录可能为只读)。然而,如果将文件写入外部存储的目的是与其他应用程序共享文件,则应强烈考虑使用FileProvider API(请参见设置文件共享);通过此策略,您的应用程序将文件存储在其自己的内部应用程序特定目录中,但随后通过内容提供程序选择性地共享这些文件以供其他应用程序使用。此策略可为文件提供更高的安全性,并使您能够对文件的读/写访问进行更好的访问控制。

既然您说您已经拥有所需的权限*,那么您可能在调用toString()时出错了。无法保证文件的toString()方法返回其完整路径。连接这些时请使用getPath()getAbsolutePath()。选择写入外部存储器时,建议您首先检查其状态;外部存储器在某些情况下可能会被弹出/卸载并且不可用。

*您应该使用ContextCompat.checkSelfPermission()进行验证。如果没有权限,请添加对requestPermissions()的调用。


1
我已经使用了写外部存储权限,并且我已经仔细检查过它是否放置在正确的位置。不过,我会看看你推荐的内容。 - user3484582
我也尝试过那些方法。然而,如果你看一下logcat,文件路径看起来是正确的,对吧? - user3484582
@user3484582 是的。你的应用程序可能没有权限访问该目录。使用 getExternalStoragePublicDirectory() 方法(它需要一个指示文件类型的参数),很可能会为你提供一个实际具有写入权限的目录 [假设你打算使用共享存储而不是内部写入]。 - Michael Aaron Safyan
如果您查看我的原始帖子,我会使用logcat检查其状态并进行挂载。我刚刚实现了requestPermission(),结果相同。当我启动应用程序时,我收到请求权限的对话框,按下接受,并使用checkSelfPermissions()和logcat一起使用,返回0,表示已授予权限。还有更多想法吗? - user3484582
@user3484582 除了打印 folder.isDirectory(),你能否打印 folder.exists()?我想知道你是否试图创建一个与现有文件同名的目录。 - Michael Aaron Safyan
最终我使用了getExternalStoragePublicDirectory(),因为我不想让我的文件是私有的,并且它运行得很好。问题不在于文件夹不存在,否则它会工作,就像使用getExternalStoragePublicDirectory()一样。不过我有一个问题。通过手机文件管理器浏览目录时,我实际上找不到那些文件夹。编辑:它在我的下载文件夹中。感谢您的帮助! - user3484582

2

试试这个:

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,则权限发生了变化。您必须在运行时请求其中一些权限,而清单声明则会被忽略。

这段代码与我的有什么区别?除了更改文件夹名称之外?我已经在清单文件中设置了权限。 - user3484582
1
如果您正在测试 Android 6.0+,从 API 23 开始,一些权限只能在运行时请求。 - Stepan Maksymov
我刚刚实现了 requestPermission(),但情况并没有改变。当我启动应用程序并按下接受时,我得到了请求权限的对话框,并且我正在使用 checkSelfPermissions() 和 logcat 进行检查,它返回 0,表示已经授予了权限。还有其他想法吗? - user3484582
你修好了吗? - 68060
你所说的“fix”是什么意思?我之前已经写过了,在尝试创建目录之前,你必须请求权限来写入外部存储。请搜索如何检查权限,并根据权限请求结果执行操作。 - Stepan Maksymov

1

还有一个可能的原因:Environment.getExternalStorageDirectory()在API级别29中已被弃用。


1

如果您已经允许了读写权限(包括运行时权限),但仍然无法正常工作,请在AndroidManifest.xml文件中添加以下内容:

<application ........ ........ android:requestLegacyExternalStorage="true"> 注意:如果您的目标是Android 10+,则必须需要此设置。


0

如果你的目标是Android api 29,在AndroidManifest中添加这一行:<application android:requestLegacyExternalStorage="true">

此外,Environment.getExternalStorageDirectory() 在api 29中已被弃用,请改用以下代码:

File mediaStorageDir = context.getExternalFilesDir(null);

0
我曾经遇到过同样的问题,尝试了很多方法,但最终通过以下方式解决了: 在你的 Manifest 文件中的 Application 标签内添加 android:requestLegacyExternalStorage="true"
 <application
    .
    .
    .
    android:requestLegacyExternalStorage="true">

-1

只需删除 .toString(),如下所示:

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

变为

String extStorageDirectory = Environment.getExternalStorageDirectory();


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接