访问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()方法获取的。

  1. /**
  2. * This method initializes MountPointManager.
  3. *
  4. * @param context Context to use
  5. */
  6. public void init(Context context) {
  7. mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
  8. final String defaultPath = getDefaultPath();
  9. LogUtils.d(TAG, "init,defaultPath = " + defaultPath);
  10. if (!TextUtils.isEmpty(defaultPath)) {
  11. mRootPath = ROOT_PATH;
  12. }
  13. mMountPathList.clear();
  14. // check media availability to init mMountPathList
  15. StorageVolume[] storageVolumeList = mStorageManager.getVolumeList();
  16. if (storageVolumeList != null) {
  17. for (StorageVolume volume : storageVolumeList) {
  18. MountPoint mountPoint = new MountPoint();
  19. mountPoint.mDescription = volume.getDescription(context);
  20. mountPoint.mPath = volume.getPath();
  21. mountPoint.mIsMounted = isMounted(volume.getPath());
  22. mountPoint.mIsExternal = volume.isRemovable();
  23. mountPoint.mMaxFileSize = volume.getMaxFileSize();
  24. LogUtils.d(TAG, "init,description :" + mountPoint.mDescription + ",path : "
  25. + mountPoint.mPath + ",isMounted : " + mountPoint.mIsMounted
  26. + ",isExternal : " + mountPoint.mIsExternal + ", mMaxFileSize: " + mountPoint.mMaxFileSize);
  27. mMountPathList.add(mountPoint);
  28. }
  29. }
  30. IconManager.getInstance().init(context, defaultPath + SEPARATOR);
  31. }

系统提供了StorageManager类,它有一个方法叫getVolumeList(),这个方法的返回值是一个StorageVolume数组,StorageVolume类中封装了挂载路径,挂载状态,以及是否可以移除等信息。下面是这个方法的源码。

  1. /**
  2. * Returns list of all mountable volumes.
  3. * @hide
  4. */
  5. public StorageVolume[] getVolumeList() {
  6. if (mMountService == null) return new StorageVolume[0];
  7. try {
  8. Parcelable[] list = mMountService.getVolumeList();
  9. if (list == null) return new StorageVolume[0];
  10. int length = list.length;
  11. StorageVolume[] result = new StorageVolume[length];
  12. for (int i = 0; i < length; i++) {
  13. result[i] = (StorageVolume)list[i];
  14. }
  15. return result;
  16. } catch (RemoteException e) {
  17. Log.e(TAG, "Failed to get volume list", e);
  18. return null;
  19. }
  20. }

getVolumeList()方法是隐藏的,不能在应用代码中直接调用,所以我们只能通过反射来调用这个方法了。

 

通过反射机制获取Android设备的所有存储设备

  1. public class StorageInfo {
  2. public String path;
  3. public String state;
  4. public boolean isRemoveable;
  5. public StorageInfo(String path) {
  6. this.path = path;
  7. }
  8. public boolean isMounted() {
  9. return "mounted".equals(state);
  10. }
  11. @Override
  12. public String toString() {
  13. return "StorageInfo [path=" + path + ", state=" + state
  14. + ", isRemoveable=" + isRemoveable + "]";
  15. }
  16. }
  1. public static List<StorageInfo> listAllStorage(Context context) {
  2. ArrayList<StorageInfo> storages = new ArrayList<StorageInfo>();
  3. StorageManager storageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
  4. try {
  5. Class<?>[] paramClasses = {};
  6. Method getVolumeList = StorageManager.class.getMethod("getVolumeList", paramClasses);
  7. Object[] params = {};
  8. Object[] invokes = (Object[]) getVolumeList.invoke(storageManager, params);
  9. if (invokes != null) {
  10. StorageInfo info = null;
  11. for (int i = 0; i < invokes.length; i++) {
  12. Object obj = invokes[i];
  13. Method getPath = obj.getClass().getMethod("getPath", new Class[0]);
  14. String path = (String) getPath.invoke(obj, new Object[0]);
  15. info = new StorageInfo(path);
  16. Method getVolumeState = StorageManager.class.getMethod("getVolumeState", String.class);
  17. String state = (String) getVolumeState.invoke(storageManager, info.path);
  18. info.state = state;
  19. Method isRemovable = obj.getClass().getMethod("isRemovable", new Class[0]);
  20. info.isRemoveable = ((Boolean) isRemovable.invoke(obj, new Object[0])).booleanValue();
  21. storages.add(info);
  22. }
  23. }
  24. } catch (Exception e) {
  25. e.printStackTrace();
  26. }
  27. storages.trimToSize();
  28. return storages;
  29. }
  30. public static List<StorageInfo> getAvaliableStorage(List<StorageInfo> infos){
  31. List<StorageInfo> storages = new ArrayList<StorageInfo>();
  32. for(StorageInfo info : infos){
  33. File file = new File(info.path);
  34. if ((file.exists()) && (file.isDirectory()) && (file.canWrite())) {
  35. if (info.isMounted()) {
  36. storages.add(info);
  37. }
  38. }
  39. }
  40. return storages;
  41. }

调用上述方法:

  1. List<StorageInfo> list = listAllStorage(this);
  2. for(StorageInfo info : list){
  3. Log.e(TAG, info.toString());
  4. }
  5. Log.e(TAG, "-----------------");
  6. List<StorageInfo> infos = getAvaliableStorage(list);
  7. for(StorageInfo info : infos){
  8. Log.e(TAG, info.toString());
  9. }
  10. 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中的存储路径的更多相关文章

  1. Android app中存储文件的路径

    // 获得缓存文件路径,磁盘空间不足或清除缓存时数据会被删掉,一般存放一些临时文件 // /data/data/<application package>/cache目录 File cac ...

  2. 【转】Windows 8 desktop app中dll搜索路径设置的诡异现象,Bug?

    原文地址:http://blog.csdn.net/my_business/article/details/8850151 某个桌面程序在win 8上运行异常的问题困扰了我有近一周,今天终于找到了根本 ...

  3. 转:Android文件存储路径getFilesDir()与getExternalFilesDir的区别

    作为一个开发者,我们经常需要通过缓存一些文件到SD卡中,常见的方式就是,通过: File sdCard = Environment.getExternalStorageDirectory(); 获取S ...

  4. Android中的GreenDao框架修改数据库的存储路径

    目前android中比较热门的数据库框架有greenDAO.OrmLite.AndrORM,其中我比较喜欢用GreenDao,其运行效率最高,内存消耗最少,性能最佳.具体怎么使用GreenDao,网上 ...

  5. unity中的文件存储路径与各平台(Android,iOS)的关系

    原文链接:unity中的文件存储路径与各平台(Android,iOS)的关系 主要是这个问题困扰我了一阵子,所以特写写... unity中的的各种存储方法的对应关系(直接上截图吧) 重点说的是Appl ...

  6. Android存储路径你了解多少?

    在了解存储路径之前,先来看看Android QQ的文件管理界面,了解一下QQ的数据文件路径来源,到底是来源于什么地方? 手Q文件管理对应存储目录 我的文件:是指放在QQ指定目录下的文件:/tencen ...

  7. [转]App离线本地存储方案

    App离线本地存储方案 原文地址:http://ask.dcloud.net.cn/article/166 HTML5+的离线本地存储有如下多种方案:HTML5标准方案:cookie.localsto ...

  8. 存储路径与文件目录操作ZT

    转自:https://www.cnblogs.com/zrr-notes/p/5953445.html (一)基本存储位置 我们的app在手机中存放的路径是:/var/mobile/Applicati ...

  9. Flask中获取参数(路径,查询,请求体,请求头)

    上一篇中已经讲述了:HTTP协议向服务器传参有几种途径{ 链接 } 在Flask中同样通过这4中传参途径进行归纳: 1. URL中路径参数的获取: 拓展: # 路由参数/路径参数:http://127 ...

随机推荐

  1. EntityFramework 学习 一 Disconnected Entities

    如何把断开的实体添加到新的context上下文中 1.首先,我们需要把实体附加到新的context上下文实例中. 2.其次,手动的给实体设置适当的实体状态,因为新的context上下文不知道断开的实体 ...

  2. HDU 1255 覆盖的面积 (线段树扫描线+面积交)

    自己YY了一个的写法,不过时间复杂度太高了,网上的想法太6了  题意:给你一些矩阵,求出矩阵的面积并 首先按照x轴离散化线段到线段树上(因为是找连续区间,所以段建树更加好做). 然后我们可以想一下怎样 ...

  3. wget下载文件

    http://blog.sina.com.cn/s/blog_4af3f0d20100n1k0.html 一.下载目录 #wget -r -np -nd http://example.com/pack ...

  4. JAVA发送手机短信

    <p><span>JAVA发送手机短信,流传有几种方法:(1)使用webservice接口发送手机短信,这个可以使用sina提供的webservice进行发送,但是需要进行注册 ...

  5. PHP面试题,自己几斤几两,看看就知道了

    0.简单做一下自我介绍,? 然后谈一下近三年来你的得意之作? 1.面试官看过你的简历,会问一些你做的项目的用户量.pv.吞吐量.相关难点和解决方法等 2.数据库设计经验,为什么进行分表? 分库? 一般 ...

  6. javascript通用参数判断

    //判断value是小于等于max的数字function isNumberMax(value, max){    if(!isNumber(value) || !isNumber(max)){     ...

  7. pom详解

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/20 ...

  8. Appium-关于appium的原生控件的 xpath 定位问题及常用方法

    最近遇到的项目,发现很多元素,都没有标明id.text.content-desc,classname中又有很多是相同,导致无法定位 第一,appium1.5及之后的版本废弃了name属性(如name= ...

  9. PostgreSQL正则及模糊查询优化

    1.带前缀的模糊查询  ~'^abc' 可以使用btree索引优化 create index idx_info on table_name(info) 2.带后缀的模糊查询  ~'abc$' 可以使用 ...

  10. freeMarker(十)——模板语言之内建函数

    学习笔记,选自freeMarker中文文档,译自 Email: ddekany at users.sourceforge.net 1.字符串内建函数 这些内建函数作用于表达式左侧的字符串值. 如果左侧 ...