不需要系统权限!!!
理论:proc/partitions可以获取主设备和次设备号(sd[a/b/c]为u盘,mmcblk[数字][p为分区]),
proc/mounts可以获取/dev/block/vold/public:179,129 /mnt/media_rw/0403-0201 也包含了主设备和次设备号
(注意凡是外部存储(sdcard 和u盘)都是/dev/block/vold/...形式,android 6.0后形式有所变化为/dev/block/vold/public:179,129)
linux执行方法:
public static String execRootCmd(String cmd) {
String result = "";
DataOutputStream dos = null;
DataInputStream dis = null;
try {
Process p = Runtime.getRuntime().exec(cmd);
dos = new DataOutputStream(p.getOutputStream());
dis = new DataInputStream(p.getInputStream());
dos.writeBytes("exit\n");
dos.flush();
String line = null;
while ((line = dis.readLine()) != null) {
result += line;
}
p.waitFor();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (dos != null) {
try {
dos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (dis != null) {
try {
dis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return result;
}
识别方法:
private final static String ROOT_PATH="/storage/";
public static void distinguishExternalPath(List<String> externalSdcardPathParam, List<String> externalUsbPathParam) {
List<String> externalSdcardPath = new ArrayList<String>();
List<String> externalUsbPath = new ArrayList<String>();
String s = LinuxCmdUtil.execRootCmd("cat proc/partitions");
s = s.replaceAll("\\s+", "|");
String[] partitions = s.split("\\|");
final List<String> usbStoreMajorMinor = new ArrayList<>();
int repeatCurrent = 0;
for (String item : partitions) {//get usb storage major and minor!!!!
if (item.contains("sd")) {
String majorMinor = partitions[repeatCurrent - 3] + "|" + partitions[repeatCurrent - 2];
usbStoreMajorMinor.add(majorMinor);
}
repeatCurrent++;
}
String condition = "/dev/block/vold";
String s1 = LinuxCmdUtil.execRootCmd("cat proc/mounts");
String[] mounts = s1.split(" ");
int currentRepeatCount = 0;
for (String item : mounts) {
if (item.length() > condition.length() && item.contains(condition)) {
boolean contains = false;
for (String usbMajorMinor : usbStoreMajorMinor) {
String[] split = usbMajorMinor.split("\\|");
contains = item.contains(split[0]) && item.contains(split[1]);
if (contains)break;
}
if (contains) {
String mount = mounts[currentRepeatCount + 1];
if (!externalUsbPath.contains(mount)) {
externalUsbPath.add(mounts[currentRepeatCount + 1]);
}
} else {
String mount = mounts[currentRepeatCount + 1];
if (!externalSdcardPath.contains(mount)) {
externalSdcardPath.add(mount);
}
}
}
currentRepeatCount++;
}
for(String usbItemPath:externalUsbPath){
String[] split = usbItemPath.split("/");
String dirName=split[split.length-1];
String storagePath=ROOT_PATH+dirName;
File file=new File(storagePath);
boolean b = file.exists() && file.isDirectory();
if (b){
externalUsbPathParam.add(storagePath);
}
}
for(String sdcardPath:externalSdcardPath){
String[] split = sdcardPath.split("/");
String dirName=split[split.length-1];
String storagePath=ROOT_PATH+dirName;
File file=new File(storagePath);
boolean b = file.exists() && file.isDirectory();
if (b){
externalSdcardPathParam.add(storagePath);
}
}
}
由于测试时发现mnt/media_rw/....用File.exist 和File.isDirectory发现不认为是文件夹(都是false),所以不能直接使用这种路径,所以后面的两个for循环就是为了解决这个问题的(/storage目录下是可以识别为文件夹的)