【问题标题】:Creating a directory in /sdcard fails在 /sdcard 中创建目录失败
【发布时间】: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");
}

【问题讨论】:

    标签: android file directory io


    【解决方案1】:

    这里需要考虑三件事:

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

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

      <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
      
    3. 如果这个目录已经存在,那么 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 以使用新目录刷新媒体存储 stackoverflow.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 文档中所述

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2021-09-07
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2011-08-03
                  • 1970-01-01
                  • 2019-09-02
                  • 1970-01-01
                  相关资源
                  最近更新 更多