昨天项目需要向指定的文件夹下保存图片,需要使用文件管理器去选择指定的文件夹,当然最后由于逻辑太奇葩(不能选择文件夹,只能选择文件夹下的某一个文件)被否定了,改为自己读取手机存储的文件夹,并且可以创建。当中遇到了几个问题记录一下:

1.手机存储现在由三部分组成了基本上:内部存储、手机内置外部存储(ROM)、手机SD卡

1)内部存储:

     getFilesDir() 

这个方法可以的到手机内部的存储(好像是包文件夹下的,我没测试)

2)手机内置外部存储(Rom):

    new File(Environment.getExternalStorageDirectory().getAbsolutePath())

这个方法可以得到文件

3)SD卡存储 问题来了,上面的方法好像似曾相识,不就是得到Sd卡吗?我也是被困扰了很久,当然也没得到答案,没办法了,通过下面方法得到了:

        File file = new File("/storage/sdcard1");if (null != file.listFiles() && file.listFiles().length > 0) {fileNameList.add("外置存储");}

更正:如果用以上方法来判断是否挂在sd卡,以及获取sd卡的根目录,测试中有些手机是不准确的,因为有的手机外置sd卡的根路径不一定是“/storage/sdcard1”,因此找个一个大神的方法,抽取出来他的工具类以及bean类,如下:

  public class StorageUtils {public static ArrayList<StorageBean> getStorageData(Context pContext) {final StorageManager storageManager = (StorageManager) pContext.getSystemService(Context.STORAGE_SERVICE);try {//得到StorageManager中的getVolumeList()方法的对象final Method getVolumeList = storageManager.getClass().getMethod("getVolumeList");//得到StorageVolume类的对象final Class<?> storageValumeClazz = Class.forName("android.os.storage.StorageVolume");//获得StorageVolume中的一些方法final Method getPath = storageValumeClazz.getMethod("getPath");Method isRemovable = storageValumeClazz.getMethod("isRemovable");Method mGetState = null;//getState 方法是在4.4_r1之后的版本加的,之前版本(含4.4_r1)没有// (http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.4_r1/android/os/Environment.java/)if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) {try {mGetState = storageValumeClazz.getMethod("getState");} catch (NoSuchMethodException e) {e.printStackTrace();}}//调用getVolumeList方法,参数为:“谁”中调用这个方法final Object invokeVolumeList = getVolumeList.invoke(storageManager);final int length = Array.getLength(invokeVolumeList);ArrayList<StorageBean> list = new ArrayList<>();for (int i = 0; i < length; i++) {final Object storageValume = Array.get(invokeVolumeList, i);//得到StorageVolume对象final String path = (String) getPath.invoke(storageValume);final boolean removable = (Boolean) isRemovable.invoke(storageValume);String state;if (mGetState != null) {state = (String) mGetState.invoke(storageValume);} else {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {state = Environment.getStorageState(new File(path));} else {if (removable) {state = EnvironmentCompat.getStorageState(new File(path));} else {//不能移除的存储介质,一直是mountedstate = Environment.MEDIA_MOUNTED;}}}long totalSize = 0;long availaleSize = 0;if (Environment.MEDIA_MOUNTED.equals(state)) {totalSize = StorageUtils.getTotalSize(path);availaleSize = StorageUtils.getAvailableSize(path);}StorageBean storageBean = new StorageBean();storageBean.setAvailableSize(availaleSize);storageBean.setTotalSize(totalSize);storageBean.setMounted(state);storageBean.setPath(path);storageBean.setRemovable(removable);list.add(storageBean);}return list;} catch (NoSuchMethodException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}return null;}private static long getTotalSize(String path) {try {final StatFs statFs = new StatFs(path);long blockSize = 0;long blockCountLong = 0;if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {blockSize = statFs.getBlockSizeLong();blockCountLong = statFs.getBlockCountLong();} else {blockSize = statFs.getBlockSize();blockCountLong = statFs.getBlockCount();}return blockSize * blockCountLong;} catch (Exception e) {e.printStackTrace();return 0;}}private static long getAvailableSize(String path) {try {final StatFs statFs = new StatFs(path);long blockSize = 0;long availableBlocks = 0;if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {blockSize = statFs.getBlockSizeLong();availableBlocks = statFs.getAvailableBlocksLong();} else {blockSize = statFs.getBlockSize();availableBlocks = statFs.getAvailableBlocks();}return availableBlocks * blockSize;} catch (Exception e) {e.printStackTrace();return 0;}}private static final long A_GB = 1073741824;private static final long A_MB = 1048576;private static final int A_KB = 1024;public static String fmtSpace(long space) {if (space <= 0) {return "0";}double gbValue = (double) space / A_GB;if (gbValue >= 1) {return String.format("%.2fGB", gbValue);} else {double mbValue = (double) space / A_MB;if (mbValue >= 1) {return String.format("%.2fMB", mbValue);} else {final double kbValue = space / A_KB;return String.format("%.2fKB", kbValue);}}}
}
public class StorageBean implements Parcelable {/*** 根路径*/private String path;/***挂在情况 一种是挂在了 mounted  一种是未挂在 removed*/private String mounted;/*** 是否可以移除,如果不可移除表示内部存储,可移除代表TF存储(外挂SD卡)*/private boolean removable;/*** 总共大小*/private long totalSize;/*** 可用大小*/private long availableSize;public String getPath() {return path;}public void setPath(String path) {this.path = path;}public String getMounted() {return mounted;}public void setMounted(String mounted) {this.mounted = mounted;}public boolean getRemovable() {return removable;}public void setRemovable(boolean removable) {this.removable = removable;}public long getTotalSize() {return totalSize;}public void setTotalSize(long totalSize) {this.totalSize = totalSize;}public long getAvailableSize() {return availableSize;}public void setAvailableSize(long availableSize) {this.availableSize = availableSize;}@Overridepublic int describeContents() {return 0;}@Overridepublic void writeToParcel(Parcel dest, int flags) {dest.writeString(this.path);dest.writeString(this.mounted);dest.writeByte(removable ? (byte) 1 : (byte) 0);dest.writeLong(this.totalSize);dest.writeLong(this.availableSize);}public StorageBean() {}protected StorageBean(Parcel in) {this.path = in.readString();this.mounted = in.readString();this.removable = in.readByte() != 0;this.totalSize = in.readLong();this.availableSize = in.readLong();}public static final Parcelable.Creator<StorageBean> CREATOR = new Parcelable.Creator<StorageBean>() {@Overridepublic StorageBean createFromParcel(Parcel source) {return new StorageBean(source);}@Overridepublic StorageBean[] newArray(int size) {return new StorageBean[size];}};@Overridepublic String toString() {return "StorageBean{" +"path='" + path + '\'' +", mounted='" + mounted + '\'' +", removable=" + removable +", totalSize=" + totalSize +", availableSize=" + availableSize +'}';}
}

以上工具类就可以了,不过发现有的手机读取出来的集合中居然后8个存储位置,当然只要取前两个就可以了(其他的不知道什么鬼)。

2. Android6.0系统的手机读取不到外置存储下面的文件和文件夹

   File[] files = file.listFiles();

这个方法中files为空。什么鬼?后来发现是权限问题,虽然在功能清单文件中申请了权限,但是6.0需要代码中对危险权限进行动态二次申请所以加上如下代码:

                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {//6.0手机if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED ||ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {//没有授权权限ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE},MY_PERMISSIONS_REQUEST_READ_CONTACTS_SD);} else {//授权了权限file = new File("/storage/sdcard1");nextFileList(file);}} else {//6.0以下系统file = new File("/storage/sdcard1");nextFileList(file);}
    @Overridepublic void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {switch (requestCode) {case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {//手机内置外部存贮// If request is cancelled, the result arrays are empty.if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {//授权同意file = new File(Environment.getExternalStorageDirectory().getAbsolutePath());nextFileList(file);} else {//授权被拒绝}}break;case MY_PERMISSIONS_REQUEST_READ_CONTACTS_SD://sd卡if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {//授权同意file = new File("/storage/sdcard1");nextFileList(file);} else {//授权被拒绝}break;}}

当然这里对于用户拒绝了需要再次请求处理我们没有处理,就没有继续研究。

3.显示的文件夹中含有隐藏的文件夹,需要删除掉,这个其实很简单,因为隐藏的文件夹都是以“.”开头的,所以使用如下方法就可以,顺便还有文件夹按照字母排序的方法

        for (int num = 0; num < files.length; num++) {if (files[num].isDirectory()) {String name = files[num].getName();if (!name.startsWith(".")) {//排除掉隐藏的文件夹fileNameList.add(name);}}}Collections.sort(fileNameList, Collator.getInstance(Locale.ENGLISH));//对文件夹名称排序

最后把整个demo放到我们资源中,有需要的可以下载。。。。

Android 读取手机文件夹向指定文件夹下存放相关推荐

  1. android 自动下一首,Android播播放完SD卡指定文件夹音乐之后,自动播放下一首

    最近做一个项目,需要连续播放音乐,播放完一首歌之后,自动播放完下一首歌.不要重复播放. 代码如下: package com.example.asyncplayer_ex; import java.io ...

  2. python写入指定路径的文件_python 从shell读取指定文件以及写入指定文件

    python 从shell读取指定文件以及写入指定文件 运行不同的文件每次都要修改脚本,能不能指定输入文件以及输出文件? python abstract_element.py 1.txt 2.txt ...

  3. python中怎么压缩文件夹_python-对指定文件夹进行压缩

    python-对指定文件夹进行压缩 目的 首先,我试验了一下[1]的效果: import os from zipfile import ZipFile def backupZip(folder): # ...

  4. Android安卓手机能不能实现BT文件边下边播?

    Android安卓手机能不能实现BT文件边下边播?Android安卓手机实现类似pc端的bt边下载边播放技术的可行性分析 PC端实现对BT文件的边下载边播放功能,已经有很长时间,也在很多领域得到了很好 ...

  5. linux scp 排除文件夹,scp复制文件时排除指定文件

    1. 前言 本文主要讲解如何在scp复制文件时排除指定文件. 举例: 我需要将所有*.c文件从名为hostA的电脑复制到hostB,包括所有目录.我使用以下scp命令,但不知道如何排除特定的文件(如* ...

  6. bat复制文件到指定目录同名_scp复制文件时排除指定文件

    请关注本头条号,每天坚持更新原创干货技术文章. 如需学习视频,请在微信搜索公众号"智传网优"直接开始自助视频学习 1. 前言 本文主要讲解如何在scp复制文件时排除指定文件. 举例 ...

  7. Android 读取手机SD卡根目录下某个txt文件的文件内容

    1.先看activity_main.xml文件: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/and ...

  8. Android读取手机根目录文件即本地SD卡

    前言 有需要所以学习了一下关于读取本地文件目录的知识,自己也仿照着写了个.哈哈,初学花了不少时间,感谢原文博客的分享!不废话见图. 大家如果有学习需要可以去我GitHub下载,下载的兄弟给我右上角随手 ...

  9. apk当安装程序将文件复制到手机自带的指定文件夹

    项目已获得,今天.apk文件以获得另一个非调试手机,发现一个问题. 由于涂料.所以绘图数据的点存储在一个.txt文字档.把它用usb传到指定目录下的,可是明显不科学,由于用户下载了你的.apk文件,你 ...

最新文章

  1. Android应用中通过AIDL机制实现进程间的通讯实例
  2. ASP.NET 2.0 AJAX中Webservice调用方法示例
  3. 298.2亿美元的机器人市场,为什么过得有点“惨”
  4. 生活永远这样,在自己放松自己的时候,会让你摔个跟头,忍耐生老练,老练生盼望...
  5. C++继承的概念及语法
  6. 十七、深入Java的类
  7. HDU - 2825 Wireless Password(AC自动机+状压dp)
  8. 扎心了,程序员2017到2019经历了什么?
  9. linux之universal usb installer安装ubuntu
  10. 栈应用_计算按运算符优先级分布的算式(代码、分析、汇编)
  11. 我是如何查找RFC官方资料的
  12. ORA-01552 :非系统表空间 'xxxx'不能使用系统回退段
  13. erp框架 saas_传统ERP软件和SaaS管理软件的区别
  14. 利用Python抓取搜索引擎结果
  15. 钱盾率先提出的“全流程屏障”究竟是怎样的一种能力?
  16. css3媒体查询实例,css3 响应式媒体查询的示例代码
  17. Shiro(一)——Shiro概述
  18. python读取lmdb文件_使用python制作LMDB数据库
  19. 可以旅游了_原水_新浪博客
  20. 函数名作为字符串输出(Function Names as Strings)

热门文章

  1. Winform UI界面设计例程——进度条
  2. Linux命令:install
  3. Hive源码阅读之路
  4. transformjs玩转星球
  5. Oracle11g或19c imp/impdp导入记录
  6. C语言-如何将大写字母转化成小写字母输出(新手初学版)
  7. 全新 QQ Linux 3.0 正式上线
  8. 加一度分享:高薪信息流优化师必备技能
  9. Python 文件的序列化和反序列化
  10. 软考中级,【软件评测师】经验分享