在Android系统中,我们是不能通过正规的API获取到外卡【TF卡和USB】的路径,需要重写系统或是通过反射的方法获取。当然,修改系统文件是比较重的,所以我们选择通过反射方法来获取;
- 获取手机或平板中所有存储路径:
/**
* @return 返回所有存储路径
*/
public static String[] getAllVolumePaths(Context mContext) {
try {
//存储管理类
StorageManager sm = (StorageManager)mContext.getSystemService(STORAGE_SERVICE);
//获取存储路径的方法
Method getVolumePathsMethod = StorageManager.class.getMethod("getVolumePaths", null);
//获取路径数组
String[] paths = (String[]) getVolumePathsMethod.invoke(sm, null);
return paths;
} catch (Exception e) {
Log.e(TAG, "getPrimaryStoragePath() failed", e);
}
return null;
}
2.获取系统默认的内部存储:
paths[0] :是系統内存;
paths.lenght()大于1的时候,可能是TF卡,也可能是USB,也可能两者都存在,但是无法区别开;
3.使用系统属性来获取TF卡的路径:
属性系统是android的一个重要特性。它作为一个服务运行,管理系统配置和状态。所有这些配置和状态都是属性。每个属性是一个键值对(key/value pair),其类型都是字符串。这些属性可能是有些资源的使用状态,进程的执行状态,系统的特有属性……
特别属性 :
如果属性名称以“ro.”开头,那么这个属性被视为只读属性。一旦设置,属性值不能改变。
如果属性名称以“persist.”开头,当设置这个属性时,其值也将写入/data/property。
如果属性名称以“net.”开头,当设置这个属性时,“net.change”属性将会自动设置,以加入到最后修改的属性名。(这是很巧妙的。 netresolve模块的使用这个属性来追踪在net.*属性上的任何变化。)
属性“ ctrl.start ”和“ ctrl.stop ”是用来启动和停止服务。每一项服务必须在/init.rc中定义.系统启动时,与init守护进程将解析init.rc和启动属性服务。一旦收到设置“ ctrl.start ”属性的请求,属性服务将使用该属性值作为服务名找到该服务,启动该服务。这项服务的启动结果将会放入“ init.svc.<服务名>“属性中。客户端应用程序可以轮询那个属性值,以确定结果。】
通过Adb命令获取系统属性: 通过命令行打印系统属性:
C:\Users\xxx>adb shell
其中
root@KYD-H58:/ # getPprop
[vold.path.internal_storage]: []
vold.path.external_sd对应的值就是SD卡的存储路径。通过Java代码获取系统属性:
private static Method getStringPropMethod = null;
public static String getSystemPropString(final String key,
final String defaultValue) {
try {
if (getStringPropMethod == null) {
getStringPropMethod = Class.forName(
"android.os.SystemProperties").getMethod("get",
String.class, String.class);
}
return (String) getStringPropMethod.invoke(null, key, defaultValue);
} catch (Exception e) {
Log.e(TAG, "Reflect error: " + e.toString());
return defaultValue;
}
}
获取sd卡的路径:【如果没有获取到值,则返回sd】
String sd_path = getSystemPropString("vold.path.external_sd","sd");
4.根据key值获取对应的存储路径:
/**
* 6.0获取外置sdcard和U盘路径,并区分
*
* @param mContext
* @param keyword
* EXT = "内部存储"; SD = "SD卡"; USB = "U盘"
* @return
*/
public static String getStoragePath(Context mContext, String keyword) {
String resultpath = "";
String[] paths = getAllVolumePaths(mContext);
String sd_path = getSystemPropString("vold.path.external_sd","sd");
if ("EXT".equals(keyword)&&paths.length>0)
resultpath = paths[0];
if ("SD".equals(keyword)&&!"sd".equals(sd_path))
resultpath = sd_path;
if ("USB".equals(keyword)){
//0默认为内部存储
for (int i = 1; i <paths.length ; i++) {
if (sd_path.equals("sd"))
resultpath = paths[i];
else if(!sd_path.equals("sd")&&!paths[i].equals(sd_path)){
resultpath = paths[i];
}
}
}
return resultpath;
}
5.获取内卡、SD卡和USB路径
@Override
protected void onResume() {
super.onResume();
StringBuilder sb = new StringBuilder();
String ext_path = null;
String sd_path = null;
String usb_path = null;
ext_path = getStoragePath(this, "EXT");
sd_path = getStoragePath(this, "SD");
usb_path = getStoragePath(this, "USB");
sb.append("内部存储路径:"+ext_path+"\n"+"SD卡路径:"+sd_path+"\n"+"USB卡路径:"+usb_path);
logTv.setText(sb.toString());
}