我尽量做到用词准确,不写错别字,不造成阅读障碍。
文件存储这块涉猎的比较少,所以一直没有形成一个系统的知识网络,这次写自己的项目的时候感觉写起来不太顺手,就想着系统的学习一下,但发现网上的资料理解起来不太容易,所以多找了一些资料,结合自己的手机(华为荣耀6pPlus)作了个较为详细的梳理。
在学习时不要忘记设置应用“存储空间”权限,也不要忘记Manifest里面申请权限。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
一.内部存储和外部存储
在4.4系统之后,Andrioid就只有外部存储和内部存储之分,只是外部存储包含两个部分——外置SD卡和手机自身存储,而真正的内部存储一般是无法在文件管理器(Root过的除外)里面看到的(如果想查看可以打开QQ–我的文件–本机文件–全部(手机内存/SD卡)查看),日常开发中我们在打开手机文件管理器能看到的只是外部存储。
有些手机会把机身自身存储(外部存储一部分)叫做“内部存储设备”,外置SD卡叫做”SDCARD“,这里请不要与本文中的内部存储概念混淆。
结合图片一目了然:
内部存储
正常Android会给每一个应用分配一个存储空间,这个存储空间就是内部存储,它的特点就是会随着应用的卸载而删除,日常开发中使用的数据库存储、SharedPreferences等数据就是在内部存储中的,这部分的存储数据默认是只能在应用内部被访问的,技术上讲,除非在创建时设置为可读的,而且其他应用还要知道你的包名才可以访问。此外,内部存储十分可贵,尽量避免浪费使用。内部存储一般用Context来操作。
访问内部存储的方法一般有以下几种:
- Environment.getDataDirectory().getAbsolutePath()); //获取内部存储的根路径 /data
- Environment.getDownloadCacheDirectory().getAbsolutePath()); //获取内部存储的cache路径 /cache
- Environment.getRootDirectory().getAbsolutePath()); //获取内部存储的system路径 /system
- getFilesDir()); //获取内部存储中包名下files路径——/data/user/0/包名/files,内部存储多了一个files文件夹
- getCacheDir()); //获取内部存储中包名下cache路径——/data/user/0/包名/cache
- getDir(“test1”, MODE_PRIVATE)); //获取内部存储中包名下app_test路径——/data/user/0/包名/app_test,内部存储多了一个app_test1文件夹
外部存储
4.4之前的系统手机的外部存储只是单指外置SD卡,4.4之后,外部存储包含手机自身存储和外置SD卡,只要不是系统为应用分配的空间都是外部存储,例:某菊花手机配置为4GB+64GB,支持扩展卡槽,最大支持扩展128GB,4GB为运行内存,不属于外部存储也不属于某个应用的内部存储,而64GB和128GB都属于外部存储,4.4系统之前64GB属于内部存储,128GB属于外部存储。现在市面上绝大部分手机都是4.4之后的了,所以日常开发中我们使用外部存储的概念就OK了。
现在有两个问题,1.如何区分手机自带存储和外置SD卡存储。2.如何获取外部存储路径。
如何区分手机自带存储和外置SD卡存储
有一个方法可以获取所有外部存储的路径,然后筛选操作就好了,注:我使用的是华为荣耀6pPlus。
- getExternalFilesDirs(Environment.MEDIA_MOUNTED); //此方法会返回一个File数组——File[];
结果:
/storage/emulated/0/Android/data/com.clone.surpassli.filemanagerdemo/files/mounted //手机自身存储
/storage/2051-EE22/Android/data/com.clone.surpassli.filemanagerdemo/files/mounted //外置SD卡
这样如果你想指定存储路径可以直接使用“storage/emulated/0”或“storage/2051-EE22”的路径来操作了。
如何获取外部存储路径
带有外置SD卡的手机是可以设置默认存储位置的,一旦设置了默认存储位置,那么获取外部存储的结果就是默认的存储位置,如果想要指定位置,参考上一条。
对默认外部存储的操作主要有以下几个(默认为手机自身存储):
- Environment.getExternalStoragePublicDirectory(“”); //获取默认外部存储根路径——/storage/emulated/0
- Environment.getExternalStorageDirectory(); //获取默认外部存储根路径——/storage/emulated/0
- getExternalFilesDir(“”); //获取默认外部存储在本应用中的files路径——/storage/emulated/0/Android/data/包名/files,外部存储中包名下会创建files文件夹
- getExternalCacheDir(); //获取默认外部存储在本应用中的cache路径——/storage/emulated/0/Android/data/包名/cache,外部存储中包名下会创建cache文件夹
当然还有其它方法,如getExternalMediaDirs(); getExternalCacheDirs(); 但是一般用不到,所以没怎么研究。
文件管理器里面不管是机身自带存储还是外置SD卡,都会有一个Android文件夹,里面有data文件夹,里面是各包名文件,然而一般开发都是在根路径自建一个新的文件夹,命名自定义,往里面放一些数据,所以我们最常用的就是获取外部存储根路径的方法:Environment.getExternalStorageDirectory();
带有External的都是外部存储的相关操作方法,不带有Environment的都是获取本应用内文件路径的方法,所以结果里都有包名;
二.开发注意事项
日常开发中最常用的就是获取外部存储根路径的方法:
Environment.getExternalStorageDirectory();
但是在特殊情况下(现在一般没有),为防止意外发生,我们都会去检查一下外置存储可是否可用,否则就使用内部存储:
//检查外部存储是否可用
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
File file = new File(Environment.getExternalStorageDirectory(), path);
if (!file.exists()) {
return file.mkdirs();
}
}else{
//使用内部存储
}
如果你有幸看到了”/mnt/sdcard“这个路径,不要慌,其实这跟”/storage/emulated/0”是一样的,这是问题是历史原因造成的,正常使用即可。
如有理解错误的地方欢迎指正;
参考文章(感谢):
http://blog.csdn.net/u010937230/article/details/73303034