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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22366217/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 15:16:55  来源:igfitidea点击:

Can't create folder on external storage on android

javaandroidstoragefile-permissions

提问by benallansmith

My development phone is a Nexus 5, running Android 4.4.2.

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

In my application, I am attempting to create a folder on external storage that will store debug information for my application. Basically it will contain all the commands executed by the application, so that when a user encounters a problem, I have the option of having them send me the information from the debug folder to analyse.

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

I started off by trying to write a file to the folder, but found there was an error creating the folder. At first I was using mkdir(), then I moved onto mkdirs()which also didn't work.

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

I have <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />in my manifest.

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

Here is the code for creating the folder:

下面是创建文件夹的代码:

    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");
        } 

Here is what I have also tried:

这是我也尝试过的:

    //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");
    }

This returns that the external storage is notread only or unavailable.

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

I have also tried different paths, such as File folder = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "Folder1");

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

This is where it became really confusing.

这就是它变得真正令人困惑的地方。

I tried development on different phones. Firstly, I grabbed a Galaxy S4 GT-i9505running Android 4.2.2and it worked. I was able to create the folders and write to them. This showed me that the code was working. Also the path returned by running the code on the S4 and Nexus 5 was the same.

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

Then I thought it may be android version specific. So I grabbed a Nexus 4with Android 4.4.2and the code worked on it as well. Created the folders and allowed me to write to them.

然后我认为它可能是特定于 android 版本的。所以我抓住了一个Nexus 4withAndroid 4.4.2并且代码也在它上面工作。创建文件夹并允许我写入它们。

None of the phones are rooted and are all stock standard. There's no special applications or anything I can think of settings wise on the Nexus 5 that would cause permissions problems. The connection is set to Media Device (MTP).

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

EDIT:

编辑:

I should add that I have tried the follow which also did not work:

我应该补充一点,我已经尝试了以下也不起作用:

  • Writing a file to the root directory of the external storage
  • Creating the file in the external storage root directory and writing to it
  • Creating a folder in a path outlined and writing a file to it
  • Creating the file in the path outlined and writing to it
  • 写文件到外存根目录
  • 在外部存储根目录中创建文件并写入
  • 在概述的路径中创建一个文件夹并将文件写入其中
  • 在概述的路径中创建文件并写入其中

I am confused as to what is causing this, is there anything else I can test or change to fix the issue?

我很困惑是什么导致了这个问题,还有什么我可以测试或更改来解决这个问题的吗?

EDIT 2:

编辑2:

Turns out the issue was due to, I think, indexing.

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

Basically all of the other devices I tested on, allowed me to reconnect the USB connection and view the created files and folders.

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

For some reason my Nexus 5 doesn't index the folders/files, even though they exist.

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

I downloaded a different 3rd party file explorer application and noticed all the folders and files were there.

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

So to view these folders and files via USB debugging, I have to restart the phone in order to re-index them, which seems quite annoying but it is better than it not working at all.

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

Thanks.

谢谢。

采纳答案by Liam George Betsworth

In terms of this being an indexing issue with the Nexus, this worked for me:

就 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);
            }
});

You should call it straight after creating and saving the file. By using the scanner, I was able to see newly created files and directories simply by replugging the device in.

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

According to the docs:

根据文档

MediaScannerConnection provides a way for applications to pass a newly created or downloaded media file to the media scanner service. The media scanner service will read metadata from the file and add the file to the media content provider.

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

Hope this helps someone else.

希望这对其他人有帮助。

回答by Amadas

First, new File()is just create object for file connect.
you want use this file, file is exists or createNewFile().
If you want use this file to create directory, check file is exists, isDirectory()after then mkDir().
Second, check Environment.getExternalStorageDirectoryis variable path.
You can use DDMSor ADBfor work.
Additionaly, I think you add permission for read external storage for something error.

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

回答by Edward Falk

Typically, I do this:

通常,我这样做:

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

Also, add this permission to your manifest:

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

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

If you want private storage (typically under /data/) for your app (not on sdcard), then look into getDir(), getFilesDir(), fileList(), openFileInput(), openFileOutput(), etc.

如果你想为你的应用程序专用存储(通常在/数据/)(不是SD卡),然后看看getDir()getFilesDir()fileList()openFileInput()openFileOutput(),等。

There are also helper functions to get private directories within the sdcard for API 8 and above: getExternalFilesDir(), getExternalCacheDir(), etc.

还有一些辅助函数来获取SD卡内的私有目录中的API 8及以上的getExternalFilesDir()getExternalCacheDir()等等。

回答by benallansmith

Turns out the issue was due to, I think, indexing.

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

Basically all of the other devices I tested on, allowed me to reconnect the USB connection and view the created files and folders.

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

For some reason my Nexus 5 doesn't index the folders/files, even though they exist.

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

I downloaded a different 3rd party file explorer application and noticed all the folders and files were there.

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

So to view these folders and files via USB debugging, I have to restart the phone in order to re-index them, which seems quite annoying but it is better than it not working at all.

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

回答by stoefln

Had the same problem. Turned out I was testing on Android 6 and did not check for runtime WRITE_EXTERNAL_STORAGE permission.

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

回答by Diiiiii

If you are running an Android device with api >= 23, you need to request permission from user before you call mkdir() function. My previous answer with example code can be found https://stackoverflow.com/a/38694026/5089713

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

回答by Bookan

For android sdk version 23 and above you should check if the user has granted permission of external storage.

对于 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;
    }
}

The code above worked for me and I hope it will work for you.

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