无法在Android上的外部存储上创建文件夹

时间:2014-03-12 23:43:02

标签: java android storage file-permissions

我的开发手机是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");

这是令人困惑的地方。

我尝试在不同的手机上进行开发。首先,我抓住Galaxy S4 GT-i9505正在运行Android 4.2.2并且它有效。我能够创建文件夹并写入它们。这告诉我代码正在运行。通过在S4和Nexus 5上运行代码返回的路径也是相同的。

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

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

修改

我应该补充一点,我已经尝试了以下也没有用的:

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

我对导致这种情况的原因感到困惑,还有什么我可以测试或更改以解决问题吗?

编辑2:

事实证明,问题是由于我认为是索引。

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

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

我下载了另一个第三方文件资源管理器应用程序,并注意到所有文件夹和文件都在那里。

因此,要通过USB调试查看这些文件夹和文件,我必须重新启动手机才能重新编制索引,这看起来很烦人,但它比不工作更好。

感谢。

8 个答案:

答案 0 :(得分:7)

就这是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为应用程序提供了一种新传递方式   创建或下载媒体文件到媒体扫描仪服务。该   媒体扫描程序服务将从文件中读取元数据并添加   将文件发送给媒体内容提供商。

希望这有助于其他人。

答案 1 :(得分:4)

事实证明,问题是由于我认为是索引。

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

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

我下载了另一个第三方文件资源管理器应用程序,并注意到所有文件夹和文件都在那里。

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

答案 2 :(得分:3)

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

答案 3 :(得分:2)

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

答案 4 :(得分:1)

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

答案 5 :(得分:1)

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

<meta http-equiv="cache-control" content="no-cache" />

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

答案 6 :(得分:1)

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

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

仅仅要求Manifest.permission.WRITE_EXTERNAL_STORAGE还不够。

答案 7 :(得分:0)

通常,我这样做:

/**
 * 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" />

如果您想要为您的应用设置私有存储(通常位于/ data /下)(而不是在SD卡上),请查看getDir()getFilesDir()fileList()openFileInput()openFileOutput()等。

还有辅助函数来获取API 8及更高版本的SD卡中的私有目录:getExternalFilesDir()getExternalCacheDir()等。