Android中的mkdirs无法工作

28

我需要在安卓设备上从摄像头保存一张图片。我在清单文件中使用了写外部存储的权限,同时使用如下代码:

File dir = new File(Environment.getExternalStorageDirectory(), "Test");
if (!dir.exists() || !dir.isDirectory())
    dir.mkdirs();

String path = dir.getAbsolutePath();
Log.d(TAG, path);                     //log show the path
File file = new File(dir.getAbsolutePath() + "/Pic.jpg");
Log.d(TAG, file.getAbsolutePath());   //again path is shown here

outStream = new FileOutputStream(file);
outStream.write(bytes);
outStream.close();
Log.d(TAG, "onPictureTaken - wrote bytes: " + bytes.length);   //fail here
} catch (FileNotFoundException e) {
Log.d(TAG, "not done");                       //error is here (this exception is thrown)
} catch (IOException e) {
Log.d(TAG, "not");
} finally {  }

我也尝试了使用mkdir()代替mkdirs(),但结果相同。

有什么想法是代码出了什么问题吗?

谢谢


5
也许你没有实现运行时权限。除此之外,千万不要捕获异常而不记录它。将e作为第三个参数添加到你的Log.d()调用中,然后使用LogCat来查看与崩溃相关的Java堆栈跟踪。 - CommonsWare
你能展示一下堆栈跟踪吗? - ToYonos
3
这是一个糟糕的代码示例:“if (!dir.exists() || !dir.isDirectory()) dir.mkdirs();”。首先,如果它确实不是一个目录,而是一个文件,则mkdirs无法将该文件转换为目录。其次,您应该检查mkdirs的返回值,因为它可能会失败。顺便说一下,它确实失败了。 - greenapps
1
尝试一下,这可能有效 stackoverflow.com/a/41221852/5488468 - Bipin Bharti
好问题!有帮助 - Androider
11个回答

62
对于像我这样没有经验的人来说,这个问题让我头发掉了一段时间。我正在针对API 21进行开发(为了兼容性),在棒棒糖上可以工作,但是在棉花糖上无法创建目录。虽然在清单文件中有“使用”权限,但仍无法正常工作。显然,在Marshmallow上,当您使用Android Studio安装时,它从未询问您是否应该授予权限,只是悄悄地失败,就像您拒绝了它一样。您必须进入“设置”,然后依次点击“应用程序”,选择您的应用程序,并切换权限开关。

3
试试这个,它可能有效 stackoverflow.com/a/41221852/5488468 - Bipin Bharti
@RobbyPatel 谢谢你的帮助,这个方法非常有效。但我有一个问题,如果我需要两个权限(比如存储和相机),并且我使用这段代码来检查权限,它只会检查第一个权限而不是检查另一个权限。有没有什么方法可以同时检查多个权限呢? - lallous34
可以将权限放在数组中吗? - Bipin Bharti
这解决了允许logback写出文件的问题。如何从运行6.0的设备中检索它?根据我所读的,你不能。或者,文件附加器的唯一用途是与设备模拟器一起使用(这很好地工作)。 - XMAN
我的应用程序是设备所有者,所以我认为它不会有任何权限问题。但我错了。这个解决了它。 - OoDeLally

45

像我这样正在尝试使用Android10的人,请在清单文件中使用以下API:

<application android:requestLegacyExternalStorage="true" ... >
    ...
  </application> 

来自Google的最新更新: 在您将应用程序更新以针对Android 11之后,系统将忽略requestLegacyExternalStorage标志。


1
谢谢!我正在将一个旧的 Android 7 项目移植到 Android 10。 - born loser
1
有用的答案!谢谢兄弟! - Androider

7

我真是个傻瓜!我使用了清单权限,但在手机上安装应用程序时没有授予存储权限!......我明白这个问题的否定性......但我希望如果其他人遇到相同的问题......请检查您的手机权限。对不起给大家带来不便。


7
你是否放置了 <\p>?
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

在你的AndroidManifest中是否声明了写入SD卡的权限?如果你正在使用Android M,那么你必须请求用户授权才能进行写入操作。这里提供一个示例


3
如果您正在测试Android M版本,则应该检查“设置”>“应用程序”>“权限”,以查看是否授予了访问存储的权限。这帮了我很多。

3
你创建了一个目录,而不是文件。使用以下代码创建新文件。
File file = new File(dir.getAbsolutePath() + "/Pic.jpg");
file.createNewFile()

谢谢回复,我按照你的代码创建了文件,现在我得到了IOException异常而不是文件未找到。 - lallous34
这意味着在写入文件时出现了一些错误。 - Ravi
当我在安卓上浏览我的文件时,目录没有被创建(我不知道这是否是问题的一部分)。 - lallous34

2

如果您已经允许了R/W权限(也包括运行时权限),但仍然无法工作,请在AndroidManifest.xml中添加下面提到的行:

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


2
API 30 开始,你只能写入你的 应用特定文件 中。
 File dir = new File(context.getFilesDir(), "YOUR_DIR");
 dir.mkdirs();

或者在您的应用程序的外部存储中 Android/data

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

更新

这个答案提供了另一种解决方案https://dev59.com/ZL_pa4cB1Zd3GeqP_g8c#65744517

更新

另一种方法是在清单文件(manifest)中授予此权限

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

像这样的答案 https://dev59.com/hlIG5IYBdhLWcg3wjhYh#66968986


1
不要使用“MANAGE_EXTERNAL_STORAGE”,否则Google Play商店将因为这个敏感权限而拒绝你的应用程序。 - Rahul Kamble

0
尝试这个。在棉花糖中提供运行时权限,它在我的应用程序代码中完美地工作:
 private String getFilename(String strFileName) {
        String filepath = Environment.getExternalStorageDirectory().getPath();
        File fileBase = new File(filepath, "Test");
        if (!fileBase.exists()) {
            fileBase.mkdirs();
        }
        return (file.getAbsolutePath() + "/" + strFileName + file_exts[currentFormat]);
    }

new File(getFilename(edt.getText().toString().trim()))

0

在编写适用于Android API 29及以上版本的代码时,请在应用程序清单文件(AndroidManifest.xml)中使用以下权限。

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

请调整您的代码,使其读起来像以下内容

    ActivityCompat.requestPermissions(this, new String[]
                    {
                            Manifest.permission.READ_EXTERNAL_STORAGE,
                            Manifest.permission.WRITE_EXTERNAL_STORAGE
                    },
            PackageManager.PERMISSION_GRANTED);

    StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
    StrictMode.setVmPolicy(builder.build());

    file = new File(Environment.getExternalStorageDirectory().getPath(), "TestDirectory/Document/");
    if (!file.exists()) {
        try {
            file.mkdirs();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

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