APP中的存储路径
访问SD卡 所需权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
App专属文件 vs App独立文件
app专属文件就是那些只有该app才可以使用的文件,例如专属格式的电子书,app独立文件就是那些不依赖于某特定app的文件,例如照片。
App独立文件
这类文件当我们删除应用之后,还应该保留在手机上的,例如拍照的照片,不应该随着删除应用而被删除掉。对于这类文件,android给我们提供了特定的目录,这些目录都是以DIRECTORY开头的,例如:DIRECTORY_MUSIC , DIRECTORY_PICTURES.
访问这些文件夹有两种方式:
Environment.getExternalStorageDirectory()是获得外部存储的第一层的对象
第一种:File sdCard = Environment.getExternalStorageDirectory();
这个sdCard的路径为mnt/sdcard/ 即为SD卡根路径,我们可以指定访问的文件夹名
File sdCard = Environment.getExternalStorageDirectory();
File directory_pictures = new File(sdCard, "Pictures");
Log.i(TAG,"directory_pictures="+directory_pictures);
得到的路径如下:
第二种:Environment.getExternalStoragePublicDirectory(String type)
如果您需要往sdcard中保存特定类型的内容,可以考虑使用Environment.getExternalStoragePublicDirectory(String type)函数,该函数可以返回特定类型的目录,目前支持如下类型:
DIRECTORY_ALARMS //警报的铃声
DIRECTORY_DCIM //相机拍摄的图片和视频保存的位置
DIRECTORY_DOWNLOADS //下载文件保存的位置
DIRECTORY_MOVIES //电影保存的位置, 比如 通过google play下载的电影
DIRECTORY_MUSIC //音乐保存的位置
DIRECTORY_NOTIFICATIONS //通知音保存的位置
DIRECTORY_PICTURES //下载的图片保存的位置
DIRECTORY_PODCASTS //用于保存podcast(博客)的音频文件
DIRECTORY_RINGTONES //保存铃声的位置
File directory_pictures = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
Log.e(TAG, "directory_pictures="+directory_pictures);
得到的路径如下:
第二种方法是一个更加方便的访问Android给我们提供好的一些公共目录的方法,第一种方式更加灵活,可以自己指定目录。
===================================================================
Android系统提供了Environment.getExternalStorageDirectory()接口获得存储设备的路径,但是这个接口往往给出的结果并不是我们想要的,在某些设备上它返回的是手机内部存储,某些设备上返回的手机外部存储。还有就是某些android设备支持扩展多个sdcard,这个时候想要获得所有存储器的挂载路径,这个接口是没有办法办到的。
那么,Android系统的文件管理器是如何把所有挂载的存储设备加载出来的呢?通过查看文件管理器的源码发现是在MountPointManager类中处理的,通过调用StorageManager类的getVolumeList()方法获取的。
- /**
- * This method initializes MountPointManager.
- *
- * @param context Context to use
- */
- public void init(Context context) {
- mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
- final String defaultPath = getDefaultPath();
- LogUtils.d(TAG, "init,defaultPath = " + defaultPath);
- if (!TextUtils.isEmpty(defaultPath)) {
- mRootPath = ROOT_PATH;
- }
- mMountPathList.clear();
- // check media availability to init mMountPathList
- StorageVolume[] storageVolumeList = mStorageManager.getVolumeList();
- if (storageVolumeList != null) {
- for (StorageVolume volume : storageVolumeList) {
- MountPoint mountPoint = new MountPoint();
- mountPoint.mDescription = volume.getDescription(context);
- mountPoint.mPath = volume.getPath();
- mountPoint.mIsMounted = isMounted(volume.getPath());
- mountPoint.mIsExternal = volume.isRemovable();
- mountPoint.mMaxFileSize = volume.getMaxFileSize();
- LogUtils.d(TAG, "init,description :" + mountPoint.mDescription + ",path : "
- + mountPoint.mPath + ",isMounted : " + mountPoint.mIsMounted
- + ",isExternal : " + mountPoint.mIsExternal + ", mMaxFileSize: " + mountPoint.mMaxFileSize);
- mMountPathList.add(mountPoint);
- }
- }
- IconManager.getInstance().init(context, defaultPath + SEPARATOR);
- }
系统提供了StorageManager类,它有一个方法叫getVolumeList(),这个方法的返回值是一个StorageVolume数组,StorageVolume类中封装了挂载路径,挂载状态,以及是否可以移除等信息。下面是这个方法的源码。
- /**
- * Returns list of all mountable volumes.
- * @hide
- */
- public StorageVolume[] getVolumeList() {
- if (mMountService == null) return new StorageVolume[0];
- try {
- Parcelable[] list = mMountService.getVolumeList();
- if (list == null) return new StorageVolume[0];
- int length = list.length;
- StorageVolume[] result = new StorageVolume[length];
- for (int i = 0; i < length; i++) {
- result[i] = (StorageVolume)list[i];
- }
- return result;
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to get volume list", e);
- return null;
- }
- }
getVolumeList()方法是隐藏的,不能在应用代码中直接调用,所以我们只能通过反射来调用这个方法了。
通过反射机制获取Android设备的所有存储设备
- public class StorageInfo {
- public String path;
- public String state;
- public boolean isRemoveable;
- public StorageInfo(String path) {
- this.path = path;
- }
- public boolean isMounted() {
- return "mounted".equals(state);
- }
- @Override
- public String toString() {
- return "StorageInfo [path=" + path + ", state=" + state
- + ", isRemoveable=" + isRemoveable + "]";
- }
- }
- public static List<StorageInfo> listAllStorage(Context context) {
- ArrayList<StorageInfo> storages = new ArrayList<StorageInfo>();
- StorageManager storageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
- try {
- Class<?>[] paramClasses = {};
- Method getVolumeList = StorageManager.class.getMethod("getVolumeList", paramClasses);
- Object[] params = {};
- Object[] invokes = (Object[]) getVolumeList.invoke(storageManager, params);
- if (invokes != null) {
- StorageInfo info = null;
- for (int i = 0; i < invokes.length; i++) {
- Object obj = invokes[i];
- Method getPath = obj.getClass().getMethod("getPath", new Class[0]);
- String path = (String) getPath.invoke(obj, new Object[0]);
- info = new StorageInfo(path);
- Method getVolumeState = StorageManager.class.getMethod("getVolumeState", String.class);
- String state = (String) getVolumeState.invoke(storageManager, info.path);
- info.state = state;
- Method isRemovable = obj.getClass().getMethod("isRemovable", new Class[0]);
- info.isRemoveable = ((Boolean) isRemovable.invoke(obj, new Object[0])).booleanValue();
- storages.add(info);
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- storages.trimToSize();
- return storages;
- }
- public static List<StorageInfo> getAvaliableStorage(List<StorageInfo> infos){
- List<StorageInfo> storages = new ArrayList<StorageInfo>();
- for(StorageInfo info : infos){
- File file = new File(info.path);
- if ((file.exists()) && (file.isDirectory()) && (file.canWrite())) {
- if (info.isMounted()) {
- storages.add(info);
- }
- }
- }
- return storages;
- }
调用上述方法:
- List<StorageInfo> list = listAllStorage(this);
- for(StorageInfo info : list){
- Log.e(TAG, info.toString());
- }
- Log.e(TAG, "-----------------");
- List<StorageInfo> infos = getAvaliableStorage(list);
- for(StorageInfo info : infos){
- Log.e(TAG, info.toString());
- }
- Log.e(TAG, "Environment.getExternalStorageDirectory(): " + Environment.getExternalStorageDirectory());
连上手机进行验证,输出Log信息:
可以看到,通过listAllStorage()方法获取到了手机上的所有存储设备,通过getAvaliableStorage()方法的过滤获取到了挂载状态的所有存储设备。由于该手机只有一个可读写的存储设备,因此与Environment.getExternalStorageDirectory()方法获取到的结果一致。
===================================================================
getExternalFilesDir(null)参数传入的为null,这样默认访问的是files文件夹,我们可以指定子文件夹
getExternalFilesDir(null) 得到 "
”/mmn/sdcard/Android/data/< package name >/files/
getExternalFilesDir("Caches") 得到 "
/mmn/sdcard/Android/data/< package name >/files/Caches
"
有些时候我们的手机没有安装SD卡,所以我们使用前需要判断一下:
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
//SD卡已装入
}
APP中的存储路径的更多相关文章
- Android app中存储文件的路径
// 获得缓存文件路径,磁盘空间不足或清除缓存时数据会被删掉,一般存放一些临时文件 // /data/data/<application package>/cache目录 File cac ...
- 【转】Windows 8 desktop app中dll搜索路径设置的诡异现象,Bug?
原文地址:http://blog.csdn.net/my_business/article/details/8850151 某个桌面程序在win 8上运行异常的问题困扰了我有近一周,今天终于找到了根本 ...
- 转:Android文件存储路径getFilesDir()与getExternalFilesDir的区别
作为一个开发者,我们经常需要通过缓存一些文件到SD卡中,常见的方式就是,通过: File sdCard = Environment.getExternalStorageDirectory(); 获取S ...
- Android中的GreenDao框架修改数据库的存储路径
目前android中比较热门的数据库框架有greenDAO.OrmLite.AndrORM,其中我比较喜欢用GreenDao,其运行效率最高,内存消耗最少,性能最佳.具体怎么使用GreenDao,网上 ...
- unity中的文件存储路径与各平台(Android,iOS)的关系
原文链接:unity中的文件存储路径与各平台(Android,iOS)的关系 主要是这个问题困扰我了一阵子,所以特写写... unity中的的各种存储方法的对应关系(直接上截图吧) 重点说的是Appl ...
- Android存储路径你了解多少?
在了解存储路径之前,先来看看Android QQ的文件管理界面,了解一下QQ的数据文件路径来源,到底是来源于什么地方? 手Q文件管理对应存储目录 我的文件:是指放在QQ指定目录下的文件:/tencen ...
- [转]App离线本地存储方案
App离线本地存储方案 原文地址:http://ask.dcloud.net.cn/article/166 HTML5+的离线本地存储有如下多种方案:HTML5标准方案:cookie.localsto ...
- 存储路径与文件目录操作ZT
转自:https://www.cnblogs.com/zrr-notes/p/5953445.html (一)基本存储位置 我们的app在手机中存放的路径是:/var/mobile/Applicati ...
- Flask中获取参数(路径,查询,请求体,请求头)
上一篇中已经讲述了:HTTP协议向服务器传参有几种途径{ 链接 } 在Flask中同样通过这4中传参途径进行归纳: 1. URL中路径参数的获取: 拓展: # 路由参数/路径参数:http://127 ...
随机推荐
- linux限制用户内存使用
最近有内存使用报警的邮件发出,之后杀掉了内存占用高的进程,使内存恢复正常 但是发现某些程序被杀掉了,有过怀疑是被人手动杀掉的,看日志后发现应该是内存占用过大,系统自动杀掉的 内存耗尽会调用oom 对进 ...
- UOJ171 【WC2016】挑战NPC
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...
- Codeforces 294B Shaass and Bookshelf:dp
题目链接:http://codeforces.com/problemset/problem/294/B 题意: 有n本书,每本书的厚度为t[i],宽度为w[i] (1<=t[i]<=2, ...
- Angular Js 控制器
在Angularjs中用ng-controller指令定义了应用程序中的控制器:例如: <div ng-app="myApp" ng-controller="myC ...
- php设计模式课程---2、为什么会用到简单工厂设计模式
php设计模式课程---2.为什么会用到简单工厂设计模式 一.总结 一句话总结: 比如调用数据库的语句,如果调用的数据库名字改了,或者调用的数据库类型改了(比如从Mysql用到了Mysqli),那么要 ...
- PL/SQL Developer 的 SQL 编辑窗口显示行号
版权声明:本文为博主原创文章,未经博主允许不得转载. 一直奇怪为什么 PL/SQL 6 系列的版本可以显示行号,为什么到了 7 .8 版本之后反而还不行了?而且我都已经设置了“显示行号”的呀. 如图: ...
- Tstrings类简单介绍及实例
用TStrings保存文件;var S: TStrings;begin S := TStringList.Create(); { ... } S.SaveToFile('config.txt' ...
- Unity3D之Mesh(三)绘制四边形
前言: 由於之前的基本介紹,所以有關的知識點不做贅述,只上案例,知識作爲自己做試驗的記錄,便於日後查看. 步驟: 1.創建一個empty 的gameobject: 2.添加一個脚本給這個game ob ...
- bzoj 3302&2447&2103 树的双中心 树形DP
题目: 题解: bzoj 3302 == 2447 == 2103 三倍经验 首先我们考虑枚举两个中心的位置,然后统计答案. 我们发现,一定有一部分点离第一个中心更近,另一部分点离第二个中心更近 如果 ...
- Java中读取输入方式的性能比较
程序开发过程中,需要从键盘获取输入值是常有的事,但Java它偏偏就没有像c语言给我们提供的scanf(),C++给我们提供的cin()获取键盘输入值的现成函数!Java没有提供这样的函数也不代表遇到这 ...