Android 读取手机文件夹向指定文件夹下存放
2016-10-10 19:10
232 查看
昨天项目需要向指定的文件夹下保存图片,需要使用文件管理器去选择指定的文件夹,当然最后由于逻辑太奇葩(不能选择文件夹,只能选择文件夹下的某一个文件)被否定了,改为自己读取手机存储的文件夹,并且可以创建。当中遇到了几个问题记录一下:
1.手机存储现在由三部分组成了基本上:内部存储、手机内置外部存储(ROM)、手机SD卡
1)内部存储:
2)手机内置外部存储(Rom):
3)SD卡存储 问题来了,上面的方法好像似曾相识,不就是得到Sd卡吗?我也是被困扰了很久,当然也没得到答案,没办法了,通过下面方法得到了:
更正:如果用以上方法来判断是否挂在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 {
//不能移除的存储介质,一直是mounted
state = 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);
}
}
}
}
2. Android6.0系统的手机读取不到外置存储下面的文件和文件夹
3.显示的文件夹中含有隐藏的文件夹,需要删除掉,这个其实很简单,因为隐藏的文件夹都是以“.”开头的,所以使用如下方法就可以,顺便还有文件夹按照字母排序的方法
最后把整个demo放到我们资源中,有需要的可以下载。。。。
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 {
//不能移除的存储介质,一直是mounted
state = 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; } @Override public int describeContents() { return 0; } @Override public 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>() { @Override public StorageBean createFromParcel(Parcel source) { return new StorageBean(source); } @Override public StorageBean[] newArray(int size) { return new StorageBean[size]; } }; @Override public 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); }
@Override public 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设备从外置TF卡文件夹中复制指定文件到到另手机内存文件夹中
- android手机开发之读取收件箱中指定号码短信
- android读取指定文件夹里的所有文件
- Android 读取手机某个文件夹目录及子文件夹中所有的txt文件
- android 读取手机文件夹 子级父级 炫酷
- Android 私有文件夹 文件的写入与读取
- Android程序函数 将assets文件夹下的文件复制到手机的sd卡中(包括子文件夹)
- php读取指定目录文件夹下所有文件夹及文件的方法
- 读取android手机流量信息
- VC下读取文件夹目录 + 读取该目录下所有指定文件 + 把所有读取结果输出到CListBox并智能设置水平滚动条宽度
- 怎么样清除android手机长按home键后,出现的最近运行的6个任务中的指定一个的图标
- 读取android手机流量信息
- 读取android手机流量信息
- Android手机开发:ImageView使用和从内存读取图片显示
- adb shell下使用命令行删除android系统中指定文件和文件夹 转
- 关于android读取用户号码,手机串号,SIM卡序列号
- 读取指定文件夹的所有文件+_finddata_t的使用
- android读取手机通讯录
- android2.2 手机号码的读取