Android的外部存储
Android支持外部存储(case-insensitive filesystem with immutable POSIX permission classes and modes)。
外部存储可以通过物理介质提供(如SD卡),也可以通过将内部存储中的一部分封装而成,设备可以有多个外部存储实例。
访问外部存储的权限
从Android 1.0开始,写操作受权限WRITE_EXTERNAL_STORAGE
保护。
从Android 4.1开始,读操作受权限READ_EXTERNAL_STORAGE
保护。
从Android 4.4开始,应用可以管理在它外部存储上的特定包名目录,而不用获取WRITE_EXTERNAL_STORAGE权限。
比如,一个包名为com.example.foo的应用,可以自由访问外存上的Android/data/com.example.foo/目录。
外部存储对数据提供的保护较少,所以系统不应该存储敏感数据在外部存储上。
特别地,配置和log文件应该存储在内部存储中,这样它们可以被有效地保护。
Environment API的目录
getDataDirectory()
:用户数据目录。即/data
getDownloadCacheDirectory()
:下载缓存内容目录。即/cache
getExternalStorageDirectory()
:主要的外部存储目录。即/sd卡根目录
,不同手机得到的此路径可能不一样。
这个目录很可能当前不能访问,比如这个目录被用户的PC挂载,或者从设备中移除,或者其他问题发生,你可以通过getExternalStorageState()
来获取当前状态。但是当我们连接电脑发现SD卡根目录存在着很多不同应用创建的成千上百个文件夹,显得杂乱不堪,所以为了不污染用户的根命名空间,一般不会直接使用这个外部存储的根目录。
getExternalStoragePublicDirectory(String)
一些共享文件应该被放置在该目录中。写这个路径需要WRITE_EXTERNAL_STORAGE
权限,读需要READ_EXTERNAL_STORAGE
权限,当然写权限默认包含了读权限。这个方法接收一个参数,表明目录所放的文件的类型,传入的参数是Environment类中的DIRECTORY_XXX静态变量,比如DIRECTORY_DCIM等。即sd卡根目录/DCIM
DIRECTORY_ALARMS //警报的铃声
DIRECTORY_DCIM //相机拍摄的图片和视频保存的位置
DIRECTORY_DOWNLOADS //下载文件保存的位置
DIRECTORY_MUSIC //音乐保存的位置
DIRECTORY_MOVIES //电影保存的位置,比如通过google play下载的电影
DIRECTORY_PICTURES //下载的图片保存的位置
DIRECTORY_NOTIFICATIONS //通知音保存的位置
DIRECTORY_PODCASTS //用于保存podcast(博客)的音频文件
DIRECTORY_RINGTONES //保存铃声的位置
注意:传入的类型参数不能是null,返回的目录路径有可能不存在,所以必须在使用之前确认一下,比如使用File.mkdirs
创建该路径。
getRootDirectory()
得到Android的根目录。即/system
isExternalStorageEmulated()
设备的外存是否是用内存模拟的,是则返回true。(API Level 11)isExternalStorageRemovable()
设备的外存是否是可以拆卸的,比如SD卡,是则返回true。(API Level 9)
Context API中的目录
getExternalFilesDir(String type)
是应用在外部存储上的目录。
和Environment类的getExternalStoragePublicDirectory(String type)
方法类似,返回包含参数指定的特定类型文件的子目录,即sd卡根目录/Android/data/包名/files/XXXX
。getExternalCacheDir()
是应用的在外部存储上的缓存目录。即sd卡根目录/Android/data/包名/cache
从Android 4.4这两个方法不需要读写权限,是针对于本应用来说,存储一些本应用内部私有的数据,如果要访问其他应用的相关目录,还是需要声明读写权限。在应用被卸载的时候,系统会清理这个目录。
Android 4.4之前的版本要访问的话还是要声明读写权限的,如果没有在manifest中写权限,上面两个get方法都会返回null。
与上面两个方法形成对比的是下面两个方法:
getFilesDir()
getCacheDir()
这两个方法得到的是内存上的目录,即/data/data/包名/files
和/data/data/包名/cache
。
这些目录都是属于应用的,当应用被卸载的时候,里面的内容都会被移除,但是不要依赖于系统的操作。
测试代码
import android.content.Context;
import android.os.Environment;
public class DirectoryUtils {
private static final String LOG_TAG = "DirectoryUtils";
public static void getEnvironmentDirectories() {
LogUtils.i(LOG_TAG, "getRootDirectory(): "
+ Environment.getRootDirectory().toString());
LogUtils.i(LOG_TAG, "getDataDirectory(): "
+ Environment.getDataDirectory().toString());
LogUtils.i(LOG_TAG, "getDownloadCacheDirectory(): "
+ Environment.getDownloadCacheDirectory().toString());
LogUtils.i(LOG_TAG, "getExternalStorageDirectory(): "
+ Environment.getExternalStorageDirectory().toString());
LogUtils.i(LOG_TAG,"getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES): "+Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString());
/*LogUtils.i(LOG_TAG,"isExternalStorageEmulated(): "+Environment.isExternalStorageEmulated());
LogUtils.i(LOG_TAG,"isExternalStorageRemovable(): "+Environment.isExternalStorageRemovable());*/
}
public static void getApplicationDirectories(Context context) {
LogUtils.i(LOG_TAG, "context.getFilesDir(): "+context.getFilesDir().toString());
LogUtils.i(LOG_TAG, "context.getCacheDir(): "+context.getCacheDir().toString());
/*methods below will return null if the permissions denied*/
LogUtils.i(LOG_TAG, "context.getExternalFilesDir(Environment.DIRECTORY_MOVIES): "+ context.getExternalFilesDir(Environment.DIRECTORY_MOVIES));
LogUtils.i(LOG_TAG,"context.getExternalCacheDir():"+context.getExternalCacheDir());
}
}
在MI 2S上输出Log:
在三星S5660上(API Level 9,注释掉了两个方法):
声明:本文大部分内容来自:
http://www.cnblogs.com/mengdd/p/3742623.html