【问题标题】:Can't create folder on external storage on android无法在android的外部存储上创建文件夹
【发布时间】:2014-04-17 10:55:15
【问题描述】:

我的开发手机是Nexus 5,运行Android 4.4.2

在我的应用程序中,我试图在外部存储上创建一个文件夹,用于存储我的应用程序的调试信息。基本上它将包含应用程序执行的所有命令,因此当用户遇到问题时,我可以选择让他们将调试文件夹中的信息发送给我以进行分析。

我开始尝试将文件写入文件夹,但发现创建文件夹时出错。起初我使用mkdir(),然后我转到mkdirs(),这也不起作用。

我的清单中有<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

创建文件夹的代码如下:

    File folder = new File(Environment.getExternalStorageDirectory() + "/DebugData");

    String path = folder.getPath();

    if(!folder.mkdirs() || !folder.exists()){        
            Log.e(LOG_TAG, path + " failed");
        } else {
            Log.d(LOG_TAG, path + " succeeded");
        } 

这是我也尝试过的:

    //Check SD card state
    String state = Environment.getExternalStorageState();
    if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state) || !Environment.MEDIA_MOUNTED.equals(state)) {
        Log.e(LOG_TAG, "Error: external storage is read only or unavailable");
    } else {
        Log.d(LOG_TAG, "External storage is not read only or unavailable");
    }

这将返回外部存储只读或不可用。

我也试过不同的路径,比如File folder = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "Folder1");

这才是真正令人困惑的地方。

我尝试在不同的手机上进行开发。首先,我抓住了一个运行Android 4.2.2Galaxy S4 GT-i9505,它成功了。我能够创建文件夹并写入它们。这向我表明代码正在运行。在 S4 和 Nexus 5 上运行代码返回的路径也是相同的。

然后我认为它可能是特定于 android 版本的。所以我抓住了Nexus 4Android 4.4.2 并且代码也可以使用它。创建文件夹并允许我写信给他们。

没有一部手机是植根的,都是标准的。在 Nexus 5 上没有任何特殊的应用程序或任何我能想到的设置会导致权限问题。连接设置为媒体设备 (MTP)。

编辑:

我应该补充一点,我尝试了以下方法,但也没有用:

  • 将文件写入外部存储的根目录
  • 在外部存储根目录中创建文件并写入
  • 在概述的路径中创建文件夹并向其中写入文件
  • 在概述的路径中创建文件并写入文件

我不知道是什么原因造成的,还有什么我可以测试或更改来解决问题的吗?

编辑 2:

原来问题是由于,我认为,索引。

基本上我测试过的所有其他设备都允许我重新连接 USB 连接并查看创建的文件和文件夹。

出于某种原因,我的 Nexus 5 不索引文件夹/文件,即使它们存在。

我下载了一个不同的 3rd 方文件浏览器应用程序,发现所有文件夹和文件都在那里。

所以要通过USB调试查看这些文件夹和文件,我必须重新启动手机才能重新索引它们,这看起来很烦人,但总比完全不工作要好。

谢谢。

【问题讨论】:

  • 不要使用串联来创建File 对象。使用正确的File 构造函数,例如new File(Environment.getExternalStorageDirectory(), "SmartspeedPTdata")。这可能不是你的困难的根源,但它可能会有所帮助。
  • 您无法访问根目录。我遇到过您甚至无法访问外部存储根目录的设备。你的清单文件肯定需要适当的权限,特别是如果你想写的话。

标签: java android storage file-permissions


【解决方案1】:

就 Nexus 的索引问题而言,这对我有用:

MediaScannerConnection.scanFile(this, new String[] { file.toString() }, null,
        new MediaScannerConnection.OnScanCompletedListener() {
            public void onScanCompleted(String path, Uri uri) {
                Log.i("ExternalStorage", "Scanned " + path + ":");
                Log.i("ExternalStorage", "-> uri=" + uri);
            }
});

您应该在创建并保存文件后直接调用它。通过使用扫描仪,我只需重新插入设备即可查看新创建的文件和目录。

根据docs

MediaScannerConnection 为应用程序提供了一种方法来传递一个新的 创建或下载媒体文件到媒体扫描仪服务。这 媒体扫描仪服务将从文件中读取元数据并添加 文件到媒体内容提供商。

希望这对其他人有所帮助。

【讨论】:

  • 这才是真正的答案。谢谢@Liam。
  • 感谢@Liam 的回答。我有点困惑(我是新手):这是否意味着如果您想保证在将设备连接到 PC 时可以查看您的应用程序创建的文件,那么这就是您需要环绕您的代码“创建目录”还是“创建文件”代码?
【解决方案2】:

原来问题是由于,我认为,索引。

基本上我测试过的所有其他设备都允许我重新连接 USB 连接并查看创建的文件和文件夹。

出于某种原因,我的 Nexus 5 不索引文件夹/文件,即使它们存在。

我下载了一个不同的第 3 方文件资源管理器应用程序,发现所有文件夹和文件都在那里。

所以要通过USB调试查看这些文件夹和文件,我必须重新启动手机才能重新索引它们,这看起来很烦人,但总比完全不工作要好。

【讨论】:

  • 这个问题非常烦人。它也出现在我的 Nexus 5 上。
【解决方案3】:

对于android sdk 23及以上版本,您应该检查用户是否已授予外部存储权限。

private void createFolder() {
    if (isStoragePermissionGranted()) {
        File folder = new File(Environment.getExternalStorageDirectory()+ File.separator + "DebugData");

        if(!folder.exists()){
            folder.mkdir();
        }
    }

public  boolean isStoragePermissionGranted() {
    if (Build.VERSION.SDK_INT >= 23) {
        if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
                == PackageManager.PERMISSION_GRANTED) {
            return true;
        } else {
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
            return false;
        }
    }
    else { //permission is automatically granted on sdk<23 upon installation
        return true;
    }
}

上面的代码对我有用,我希望它对你有用。

【讨论】:

  • 鼓励链接到外部资源,但请在链接周围添加上下文,以便您的其他用户了解它是什么以及为什么存在。始终引用重要链接中最相关的部分,以防目标站点无法访问或永久离线。
  • 正是我想要的。谢谢!
【解决方案4】:

遇到了同样的问题。原来我在 Android 6 上进行测试,并没有检查运行时 WRITE_EXTERNAL_STORAGE 权限。

【讨论】:

  • 如果我们能在这里得到一个更具描述性的错误信息就更好了。
【解决方案5】:

首先,新的File() 只是为文件连接创建对象。
你想使用这个文件,文件存在或createNewFile().
如果要使用此文件创建目录,请检查文件是否存在,isDirectory() 然后mkDir()
二、检查Environment.getExternalStorageDirectory是变量路径。
您可以使用DDMSADB 工作。
另外,我认为您为某些错误添加了读取外部存储的权限。

【讨论】:

    【解决方案6】:

    如果您运行的是 api >= 23 的 Android 设备,您需要在调用 mkdir() 函数之前请求用户的许可。 可以找到我之前对示例代码的回答 https://stackoverflow.com/a/38694026/5089713

    【讨论】:

      【解决方案7】:

      对于 Android 10+,将以下内容添加到清单中:

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

      要求Manifest.permission.WRITE_EXTERNAL_STORAGE 是不够的。

      【讨论】:

        【解决方案8】:

        通常,我会这样做:

        /**
         * Return a dedicated directory named "MyApp" at the top of external storage
         */
        public static file getDataDir() {
            File sdcard = Environment.getExternalStorageDirectory();
            if( sdcard == null || !sdcard.isDirectory() ) {
                // TODO: warning popup
                Log.w(TAG, "Storage card not found " + sdcard);
                return null;
            }
            File dataDir = new File(sdcard, "MyApp");
            if( !confirmDir(dataDir) ) {
                // TODO: warning popup
                Log.e(TAG, "Unable to create " + dataDir);
                return null;
            }
            return dataDir;
        }   
        
        private static boolean confirmDir(File dir) {
            if (dir.isDirectory()) return true;  // already exists
            if (dir.exists()) return false;      // already exists, but is not a directory
            return dir.mkdirs();                 // create it
        }       
        

        另外,将此权限添加到您的清单中:

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

        如果您想为您的应用程序(而不是在 sdcard 上)提供私有存储空间(通常在 /data/ 下),请查看 getDir()getFilesDir()fileList()openFileInput()openFileOutput() 等。

        还有一些辅助函数可以在 API 8 及更高版本的 sdcard 中获取私有目录:getExternalFilesDir()getExternalCacheDir() 等。

        【讨论】:

        • 爱德华,你没有仔细阅读 benallansmith 给出的描述!他写道,他的版本是 4.4.x!你知道 4.4.x 的变化吗?你的描述说你不是。
        • 我不得不承认我不知道 4.4 中的任何新内容。您在考虑哪些新的 API?
        • Environment.getExternalStorageDirectory 不适用于现代设备
        • 这是文档:developer.android.com/reference/android/os/…。它似乎仍然是受支持的 API;它以什么方式不再起作用?
        猜你喜欢
        • 2016-07-21
        • 2020-11-17
        • 1970-01-01
        • 2012-01-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多