在 /sdcard 中创建目录失败

Posted

技术标签:

【中文标题】在 /sdcard 中创建目录失败【英文标题】:Creating a directory in /sdcard fails 【发布时间】:2011-04-20 16:31:55 【问题描述】:

我一直在尝试以编程方式在/sdcard 中创建一个目录,但它不起作用。下面的代码总是输出directory not created.

boolean success = (new File("/sdcard/map")).mkdir(); 
if (!success) 
    Log.i("directory not created", "directory not created");
 else 
    Log.i("directory created", "directory created");

【问题讨论】:

【参考方案1】:

这里需要考虑三件事:

    不要假设 sd 卡安装在/sdcard (默认情况下可能是这样,但最好不要硬编码。)。可以通过查询系统获取sdcard的位置:

    Environment.getExternalStorageDirectory();
    

    您必须通过在 AndroidManifest.xml 文件中添加使用权限条目来通知 android 您的应用程序需要写入外部存储:

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

    如果这个目录已经存在,那么 mkdir 将返回 false。因此检查目录是否存在,如果不存在则尝试创建它。 在您的组件中,使用类似:

    File folder = new File(Environment.getExternalStorageDirectory() + "/map");
    boolean success = true;
    if (!folder.exists()) 
        success = folder.mkdir();
    
    if (success) 
        // Do something on success
     else 
        // Do something else on failure 
    
    

【讨论】:

在 Froyo 之前,SD 卡安装在 /sdcard。从 Froyo 开始,sd 卡被挂载在 /mnt/sdcard 并创建了一个到 /sdcard 的软链接,这样即使挂载点发生变化,应用程序仍然可以正常运行。 由于某种原因,这段代码在我的 myTouch 手机上对我不起作用……嗯,.mkdir() 总是返回 false。 我认为您应该检查权限,并且该磁盘未安装在PC文件系统上。 我应该在 XML 文件的哪个位置放置使用权限块? 我有类似的问题,发现如果我的手机通过USB连接到我的电脑,它无法创建目录。当我断开手机并再次运行应用程序时,它会正确创建文件夹和文件。【参考方案2】:

在我将 Android 手机更新到 6.0(API 级别 23)后,我遇到了同样的问题。以下解决方案适用于我。希望它也能帮助你。

请检查您的安卓版本。如果是 >= 6.0(API 级别 23),则不仅需要包含

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

在您的 AndroidManifest.xml 中,还在调用 mkdir() 之前请求权限。 代码快照。

public static final int MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE = 1;
public int mkFolder(String folderName) // make a folder under Environment.DIRECTORY_DCIM
    String state = Environment.getExternalStorageState();
    if (!Environment.MEDIA_MOUNTED.equals(state))
        Log.d("myAppName", "Error: external storage is unavailable");
        return 0;
    
    if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) 
        Log.d("myAppName", "Error: external storage is read only.");
        return 0;
    
    Log.d("myAppName", "External storage is not read only or unavailable");

    if (ContextCompat.checkSelfPermission(this, // request permission when it is not granted. 
            Manifest.permission.WRITE_EXTERNAL_STORAGE)
            != PackageManager.PERMISSION_GRANTED) 
        Log.d("myAppName", "permission:WRITE_EXTERNAL_STORAGE: NOT granted!");
        // Should we show an explanation?
        if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                Manifest.permission.WRITE_EXTERNAL_STORAGE)) 

            // Show an expanation to the user *asynchronously* -- don't block
            // this thread waiting for the user's response! After the user
            // sees the explanation, try again to request the permission.

         else 

            // No explanation needed, we can request the permission.

            ActivityCompat.requestPermissions(this,
                    new String[]Manifest.permission.WRITE_EXTERNAL_STORAGE,
                    MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE);

            // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
            // app-defined int constant. The callback method gets the
            // result of the request.
        
    
    File folder = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM),folderName);
    int result = 0;
    if (folder.exists()) 
        Log.d("myAppName","folder exist:"+folder.toString());
        result = 2; // folder exist
    else
        try 
            if (folder.mkdir()) 
                Log.d("myAppName", "folder created:" + folder.toString());
                result = 1; // folder created
             else 
                Log.d("myAppName", "creat folder fails:" + folder.toString());
                result = 0; // creat folder fails
            
        catch (Exception ecp)
            ecp.printStackTrace();
        
    
    return result;


@Override
public void onRequestPermissionsResult(int requestCode,
                                       String permissions[], int[] grantResults) 
    switch (requestCode) 
        case MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE: 
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) 

                // permission was granted, yay! Do the
                // contacts-related task you need to do.

             else 

                // permission denied, boo! Disable the
                // functionality that depends on this permission.
            
            return;
        

        // other 'case' lines to check for other
        // permissions this app might request
    

更多信息请阅读“Requesting Permissions at Run Time”

【讨论】:

只有在面向 SDK 23 及更高版本时才需要运行时权限请求。当应用程序以较低的 SDK 为目标时,不需要运行时请求,并且 ContextCompat.checkSelfPermission 在这种特殊情况下将始终返回 true。 谢谢!是否必须像这样提供所有权限?还是只有与存储相关的权限才需要? @BalajiSrinivasan,不!仅适用于所谓的“危险权限”。检查我的答案底部的链接,看看他们是谁。 终于!!我整天都在搜索这些信息,试图弄清楚为什么在我的清单中指定权限后会收到“fail readDirectory() errno=13”消息。谢谢!! 我很密集,所以这篇文章对我来说还不够。这是我最终找到的视频,它演示了如何非常清楚地请求权限 - youtube.com/watch?v=C8lUdPVSzDk【参考方案3】:

SD卡的正确路径是

/mnt/sdcard/

但是,如前所述,您不应该对其进行硬编码。如果您使用的是 Android 2.1 或更高版本,请使用

getExternalFilesDir(String type) 

否则:

Environment.getExternalStorageDirectory()

仔细阅读https://developer.android.com/guide/topics/data/data-storage.html#filesExternal

另外,您需要使用此方法或类似方法

boolean mExternalStorageAvailable = false;
boolean mExternalStorageWriteable = false;
String state = Environment.getExternalStorageState();

if (Environment.MEDIA_MOUNTED.equals(state)) 
    // We can read and write the media
    mExternalStorageAvailable = mExternalStorageWriteable = true;
 else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) 
    // We can only read the media
    mExternalStorageAvailable = true;
    mExternalStorageWriteable = false;
 else 
    // Something else is wrong. It may be one of many other states, but all we need
    //  to know is we can neither read nor write
    mExternalStorageAvailable = mExternalStorageWriteable = false;

然后检查您是否可以访问 sdcard。如前所述,请阅读官方文档。

另一种选择,也许你需要使用mkdirs而不是mkdir

file.mkdirs()

创建由该文件的结尾文件名命名的目录,包括创建该目录所需的完整目录路径。

【讨论】:

在任何版本的 Android 中,Environment 上都没有 getExternalFilesDir()。您可能会想到Context 上的getExternalFilesDir(),它是在2.2 中添加的。但是,该方法有些损坏 - 它为您提供的目录将在应用程序升级期间删除其内容。我希望这将在 Gingerbread 中得到解决。 谢谢,已修复。我快速浏览了数据存储部分,并假设它的访问方式与我使用的 getExternalStorageDirectory() 一样。 如前所述,我已经测试了状态。状态显示我已安装,但我无法创建文件夹【参考方案4】:

重新启动您的 Android 设备。重新启动设备后,一切都开始为我工作了。

【讨论】:

我认为我调试了我的应用程序并且其中一个写入锁被锁定了,并且从未释放。 使用 mediaScan 或 sendbroadcast 到 Media_mount 以使用新目录刷新媒体存储 ***.com/questions/3300137/…【参考方案5】:

如果您在使用 Android 6 并且编译目标 >= 23 时遇到这种情况,请不要忘记我们现在使用的是 runtime permissions。因此,在清单中授予权限是不够的。

【讨论】:

【参考方案6】:

使用 mkdirs() 而不是 mkdir()..它对我有用 :)

File folder = new File(Environment.getExternalStorageDirectory()+"/Saved CGPA");
if(!folder.exists())
    if(folder.mkdirs())
    Toast.makeText(this, "New Folder Created", Toast.LENGTH_SHORT).show();


File sdCardFile = new File(Environment.getExternalStorageDirectory()+"/Saved CGPA/cgpa.html");

【讨论】:

【参考方案7】:

在安卓 API >= 23

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

而不是

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

【讨论】:

【参考方案8】:

您是否有权在清单中写入 SD 卡? 在 http://developer.android.com/reference/android/Manifest.permission.html 查找 WRITE_EXTERNAL_STORAGE

【讨论】:

是的,我已经在应用程序标签的清单文件中添加了这一行,但它仍然没有创建目录。 如果您使用 api 23 运行您的应用程序,您必须首先向用户 developer.android.com/training/permissions/requesting.html 请求权限 Bishoy - 这不完全正确。仅当您面向 API 23 及更高版本时,您才必须在运行时请求权限。如果您的目标是较低的 SDK,即使在 SDK 23+ 上运行,您也不必请求运行时权限【参考方案9】:

它不是已经创建了吗?如果文件夹已经存在,Mkdir 返回 false mkdir

【讨论】:

【参考方案10】:

有很多事情你需要担心 1.如果您使用的是Android Bellow Marshmallow,那么您必须在Manifest File 中设置permesions。 2.如果您使用的是更高版本的Android意味着现在从棉花糖到奥利奥 您必须转到应用信息并手动设置应用存储权限。 如果你想在运行时设置它,你可以通过下面的代码来做到这一点

public  boolean isStoragePermissionGranted() 
if (Build.VERSION.SDK_INT >= 23) 
    if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
            == PackageManager.PERMISSION_GRANTED) 
        Log.v(TAG,"Permission is granted");
        return true;
     else 

        Log.v(TAG,"Permission is revoked");
        ActivityCompat.requestPermissions(this, new String[]Manifest.permission.WRITE_EXTERNAL_STORAGE, 1);
        return false;
    

else  //permission is automatically granted on sdk<23 upon installation
    Log.v(TAG,"Permission is granted");
    return true;

【讨论】:

【参考方案11】:
File f = new File(Environment.getExternalStorageDirectory().getAbsolutePath()
        + "/FoderName");
if (!f.exists()) 
    f.mkdirs();

【讨论】:

【参考方案12】:

我犯了一个错误,将两者都包括在内:

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

和:

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

按上述顺序。因此,当我取出第二个权限 (READ) 时,问题就消失了。

【讨论】:

我同时包含了 WRITE_EXTERNAL_STORAGE 和 READ_EXTERNAL_STORAGE 权限。你只需要第一个。【参考方案13】:

如果错误发生在 Android 6.0 和 API >=23 ;在 AndroidManifest.xml 中授予权限还不够。

你必须给运行时权限,你可以在这里参考更多 Runtime Permission

                       (or)

Google 在 Android Q 上有一个新功能:用于外部存储的过滤视图。对此的快速解决方法是在 AndroidManifest.xml 文件中添加以下代码:

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

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

您可以在此处阅读更多信息:https://developer.android.com/training/data-storage/compatibility


内部存储与二级存储

内部存储在 API 中称为“外部存储”;不是“二级存储”

Environment.getExternalStorageDirectory();

如Environment 文档中所述

【讨论】:

以上是关于在 /sdcard 中创建目录失败的主要内容,如果未能解决你的问题,请参考以下文章

在文档目录的子文件夹中创建 sqlite 数据库失败

ANDROID - 在 sdcard 中创建文件夹和文本文件并将其写入

在 Swift 的应用程序支持中创建嵌套目录

防止pytest在Pycharm中创建.cache目录

如何在主目录中创建文件夹?

如何使用在服务器中创建目录的 curl 上传文件