getExternalFilesDir和getExternalStorageDirectory()之间的区别

108

我明白ExternalFiles适用于API 8及以上版本,而getExternalStorageDirectory适用于7及以下版本。然而我对它们的使用还有点困惑。例如,我想要检查一个已经存在的文件夹,之前可能会使用下面的代码:

File ChildFolder = new File(Environment.getExternalStorageDirectory() + "/ParentFolder/Child");

然而,我看到的所有示例都建议使用getExternalFilesDir(null)、File.ext等方法。由于我的API版本高于8,我想使用此方法,但我该如何检查文件夹是否存在?在另一点上,我将检查文件的存在性,但现在只想查看文件夹是否存在?

4个回答

153
getExternalFilesDir()

它返回SD卡上位于 Android/data/data/your_package/ 中的 files 文件夹路径。它用于存储应用程序所需的任何文件(例如从网络下载的图像或缓存文件)。一旦应用程序被卸载,存储在此文件夹中的所有数据也将消失。

getExternalStorageDirectory()

它返回你的SD卡根路径(例如 mnt/sdcard/)。如果你在这个路径上保存数据并卸载应用程序,那么这些数据不会丢失。


7
Google Android希望您在框架内使用他们提供的任何内容,因此这取决于您的选择和设计要求。如果您不希望应用程序卸载时留下文件,则建议您使用**getExternalFilesDir()getExternalCacheDir()**。 - waqaslam
5
因为在API 8中,他们引入了高级媒体扫描功能,可以扫描音乐、图片、铃声等文件夹中的数据。只有使用**getExternalFilesDir()才会自动创建这些目录。现在由于API 7中没有这个功能,所以建议使用getExternalStorageDirectory()**。简单明了... - waqaslam
2
没问题,给它一些时间,很快就会有一个"灵光乍现"的时刻 :) - waqaslam
8
重要的是要知道,getExternalStorageDirectory() 不一定会返回“SD卡路径”,甚至可能通常不会返回。而是它会返回“主外部存储目录”。文档(https://developer.android.com/reference/android/os/Environment.html#getExternalStorageDirectory())说明: - LarsH
2
注意:不要被这里的“外部”一词所困惑。这个目录最好被认为是媒体/共享存储。它是一个可以容纳相对大量数据并在所有应用程序之间共享(不强制执行权限)的文件系统。传统上,这是一个SD卡,但它也可以作为设备中内置存储的实现,并且可以在计算机上作为文件系统挂载。 - LarsH
显示剩余6条评论

100

首先,我们需要了解内部存储、外部存储(也称为主要外部存储)和次要外部存储之间的区别是什么?

内部存储:是用户无法访问的存储,除非通过安装的应用程序(或通过对其设备进行根操作)来访问。例如:data/data/app_packageName

主要外部存储:内置的共享存储,可以“通过插入USB电缆并将其作为驱动器挂载到主机计算机上”由用户访问。例如:当我们说Nexus 5 32 GB时。

次要外部存储:可移动存储。例如:SD卡。

getExternalFilesDir (String type)

它返回主要外部存储器中 Android/data/data/your_package/ 文件夹内的文件路径。该文件夹位于内置存储器中。

Environment.getExternalStorageDirectory()
它将返回第二外部存储目录的路径。

感谢您解释不同类型的存储方式。然而,也许可以编辑“内部存储”项目,提到获取该值的方法调用是getFilesDir()。好吧,我猜那个方法实际上返回data/data/app_packageName/files,但它仍然是内部存储。 - raddevus
3
@VicJordan 请写一下关于 File getExternalStoragePublicDirectory (String type)File getFilesDir () 的内容。 - AnV
2
谢谢 Vic。Environment.getExternalStorageDirectory() 输出 /storage/emulated/0。 - gimmegimme
我遇到过这样的手机,但我没有一个像Gingerbread那么旧的设备,所以我应该能够想出一个解决方案。如果可以的话,我会在这里发布,但测试需要一些时间。然而,即使我找不到这样的例子,将“据我所知,自Gingerbread以来,在所有手机上,X实际上等同于Y”表示为“X = Y”似乎非常危险。特别是如果没有文档支持这个想法。 - LarsH
1
这个答案是错误的。getExternalStorageDirectory返回的是/ storage / emulated / 0,它是主内部存储。 - MSeiz5
显示剩余5条评论

23

重要更新!对于任何看到这篇问题的人来说都非常重要。

由于这是一个有点老的问题,我想提供一些额外的信息。自从KitKat以来,即使拥有 WRITE_EXTERNAL_STORAGE 权限的应用程序也只能在外部存储器上写入 Android/data/data/your_package/,也就是getExternalFilesDir()

如果您尝试写入getExternalStorageDirectory() + "/somefolder/anotherfolder/",则大多数设备会抛出SecurityException异常。


13
根据文档,拥有WRITE_EXTERNAL_STORAGE权限的应用程序可以写入其他包的外部存储空间,而不仅仅是它们自己的。没有该权限的应用程序只能写入其自己的目录:https://developer.android.com/reference/android/content/Context.html#getExternalFilesDir(java.lang.String)“从KITKAT开始,读取或写入返回路径不需要任何权限;调用应用程序始终可以访问...要访问属于其他包的路径,需要WRITE_EXTERNAL_STORAGE和/或READ_EXTERNAL_STORAGE权限。” - Oded
8
你的回答没有解决其中错误的信息。"自KitKat以来,即使是具有WRITE_EXTERNAL_STORAGE权限的应用程序也只允许在外部存储器上写入Android/data/data/your_package/,也就是getExternalFilesDir()。"根据文档,这是错误的。使用WRITE_EXTERNAL_STORAGE权限,应用程序可以写入所有外部存储器。 - Oded
1
@Oded,你测试过这个吗?根据文档和我在KitKat及更高版本设备上的经验,我的理解与你不同。(但愿我现在有时间详细讨论所有细节。也许以后吧。)我的经验是SGal是正确的。还有一点就是Lollipop有些不同。 - LarsH
3
根据Android文档,这个答案是明显错误的。请参考https://developer.android.com/reference/android/Manifest.permission.html#WRITE_EXTERNAL_STORAGE ,从API级别19开始,在通过getExternalFilesDir(String)和getExternalCacheDir()返回的应用程序特定目录中读写文件不需要此权限。(请注意,API级别19=KitKat)。不知道它为什么会有那么多赞。 - Ajedi32
@Ajedi32,可能是因为一些手机的行为(例如我的经验中的Galaxy S2)与文档不符。 可能是一个错误,可能是一种配置(多个内部/外部分区),这种情况在Google撰写文档时没有考虑到。 我会阅读,我知道文档上说了什么。只是想分享一下我的个人经验。 - SGal
显示剩余2条评论

16

!! 重要提示 !!

Environment.getExternalStorageDirectory()已经被弃用,应该使用Context#getExternalFilesDir(String)、MediaStore或Intent#ACTION_OPEN_DOCUMENT代替。

此方法已在API级别29中弃用。 为了提高用户隐私保护,直接访问共享/外部存储设备已被弃用。当应用程序针对Build.VERSION_CODES.Q时,从此方法返回的路径不再直接对应用程序可访问。应用程序可以通过迁移到替代方案(例如Context#getExternalFilesDir(String)、MediaStore或Intent#ACTION_OPEN_DOCUMENT)来继续访问存储在共享/外部存储上的内容。

https://developer.android.com/reference/android/os/Environment.html#getExternalStorageDirectory()

自Android.M版本开始,开发者需要在运行时请求权限。

更多详细信息,请参阅此文档这个问题

Environment.getExternalStorageDirectory()在API级别29中已被弃用Java


如果有人正在寻找 Stack Overflow 的链接而不是从 Google 文档中复制粘贴的内容,请看这里: https://dev59.com/LFMI5IYBdhLWcg3wFXWg - Rowan Berry
6
自 Android 11 开始,应用程序无法在外部存储器上创建自己特定于应用的目录。 - Darksymphony
应用程序*技术上*不能这样做,但系统可以为它们完成此操作:https://dev59.com/dFIG5IYBdhLWcg3wkh4y - mirh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接