在 /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 中创建目录失败的主要内容,如果未能解决你的问题,请参考以下文章