今天做项目的时候发现获取存储的方式不一样,搞了一个上午,计算sd卡的容量.总结一下.以免后面走弯路
Android 获取SD卡路径:
外置sd卡路径,也许很多同学在平时的工作中并不会用到,因为现在很多机型都不支持外置sd卡(这也是Google目标),所以并不用考虑外置sd卡的路径问题。除了开发文件管理类的应用之外,其他应用使用 Enviroment
方法一:
//内置sd卡路径
String sdcardPath = System.getenv("EXTERNAL_STORAGE");
//内置sd卡路径
String sdcardPath = Environment.getExternalStorageDirectory().getAbsolutePath();
//外置置sd卡路径
String extSdcardPath = System.getenv("SECONDARY_STORAGE");
不过在编写过程中发现在API 23版本中 SECONDARY_STORAGE 被移除。
所以我们只能通过发射拿到外置和内置sd卡的路径
反射的方式使用在sdk中被 隐藏 的类 StroageVolume 中的方法getVolumeList(),获取所有的存储空间(Stroage Volume),然后通过参数is_removable控制,来获取内部存储和外部存储(内外sd卡)的路径,参数 is_removable为false时得到的是内置sd卡路径,为true则为外置sd卡路径。
代码如下:
/**
* 通过反射调用获取内置存储和外置sd卡根路径(通用)
*
* @param mContext 上下文
* @param is_removale 是否可移除,false返回内部存储路径,true返回外置SD卡路径
* @return
*/
public static String getStoragePath(Context mContext, boolean is_removale) {
String path = "";
//使用getSystemService(String)检索一个StorageManager用于访问系统存储功能。
StorageManager mStorageManager = (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE);
Class<?> storageVolumeClazz = null;
try {
storageVolumeClazz = Class.forName("android.os.storage.StorageVolume");
Method getVolumeList = mStorageManager.getClass().getMethod("getVolumeList");
Method getPath = storageVolumeClazz.getMethod("getPath");
Method isRemovable = storageVolumeClazz.getMethod("isRemovable");
Object result = getVolumeList.invoke(mStorageManager);
for (int i = 0; i < Array.getLength(result); i++) {
Object storageVolumeElement = Array.get(result, i);
path = (String) getPath.invoke(storageVolumeElement);
boolean removable = (Boolean) isRemovable.invoke(storageVolumeElement);
if (is_removale == removable) {
return path;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return path;
}
方法二
我也总结了一下一种方式,判断是否存在外置sd卡
//判断是否存在外置tf卡
public static boolean isStorageTf(Context context) {
try {
StorageManager sm = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
Method getVolumeStateMethod = StorageManager.class.getMethod("getVolumeState", new Class[]{String.class});
String state = (String) getVolumeStateMethod.invoke(sm, getTfStoragePath(context));
if (state.equals(Environment.MEDIA_MOUNTED)) {
return true;
}
} catch (Exception e) {
Log.e("TF error", "not find tf", e);
}
return false;
}
//获取外置tf卡路径
public static String getTfStoragePath(Context context) {
try {
@SuppressLint("WrongConstant")
StorageManager sm = (StorageManager) context.getSystemService("storage");
Method getVolumePathsMethod = StorageManager.class.getMethod("getVolumePaths", new Class[0]);
String[] paths = (String[]) getVolumePathsMethod.invoke(sm, new Object[]{});
// second element in paths[] is secondary storage path
return paths[1];
} catch (Exception e) {
Log.e("TF error", "get Tf failed", e);
}
return null;
}
拿到了外部sd卡,我们就可以计算容量了
以下是我个人用到的
/**
* 获取Sd卡的状态
*
* @return
*/
public static String getSDAllSize(Context context) {
long GB = 1024 * 1024 * 1024;//定义GB的计算常量
long MB = 1024 * 1024;//定义MB的计算常量
long KB = 1024;//定义KB的计算常量
DecimalFormat df = new DecimalFormat("0.00");//格式化小数
if (!isStorageTf(context)) {
return "0GB";
}
// File path = Environment.getExternalStorageDirectory();
// Log.e(TAG, "getSDAllSize:path: " + path);
String path1 = getTfStoragePath(context);
StatFs sf = new StatFs(path1);
long blockSize = sf.getBlockSize();
long allBlocks = sf.getBlockCount();
long freeBlocks = sf.getAvailableBlocks();
// 总空间
String totalMemory = df.format((allBlocks * blockSize) / (float) GB) + "GB";
// 可用空间
String availableMemory = df.format((freeBlocks * blockSize) / (float) GB) + "GB";
return availableMemory + "/" + totalMemory;
//return (allBlocks * blockSize) / 1024 / 1024 + "GB"; //单位G
}