有没有一种通用的方法来找到外置SD卡的位置?
请不要与外部存储混淆。
Environment.getExternalStorageState()返回内部SD挂载点的路径,例如/mnt/sdcard。但问题是关于外部SD的。我如何获得类似/mnt/sdcard/external_sd的路径(它可能因设备而异)?
我想我将以根据文件系统名称过滤mount命令的输出作为结束。但我不确定这种方式是否足够稳健。
有没有一种通用的方法来找到外置SD卡的位置?
请不要与外部存储混淆。
Environment.getExternalStorageState()返回内部SD挂载点的路径,例如/mnt/sdcard。但问题是关于外部SD的。我如何获得类似/mnt/sdcard/external_sd的路径(它可能因设备而异)?
我想我将以根据文件系统名称过滤mount命令的输出作为结束。但我不确定这种方式是否足够稳健。
当前回答
谷歌已经阻止了许多选项,以获得外部sd卡路径,并添加权限级别,以保护sd卡目录从应用程序的垃圾。 我尝试过的每个解决方案都没有提供足够的方法来获得外部和可移动sd卡路径。
在那之后, 谷歌确实提供了一种方法来获取外部路径,应用程序可以写入它,并检查它是否可移动。
使用这个简单的API,您可以获得可移动外部目录的路径,并具有正确的写/读权限。
File[] files = getExternalFilesDirs(null);
for(File file : files){
if(Environment.isExternalStorageRemovable(file)){
return file;
}
}
其他回答
这是我用来找到外部卡的方法。使用mount cmd返回然后解析vfat部分。
String s = "";
try {
Process process = new ProcessBuilder().command("mount")
.redirectErrorStream(true).start();
process.waitFor();
InputStream is = process.getInputStream();
byte[] buffer = new byte[1024];
while (is.read(buffer) != -1) {
s = s + new String(buffer);
}
is.close();
} catch (Exception e) {
e.printStackTrace();
}
//用行分隔mount列表
String[] lines = s.split("\n");
for(int i=0; i<lines.length; i++) {
//如果行内有挂载路径且为vfat类型,说明可能是内置或者外置sd的挂载点
if(-1 != lines[i].indexOf(path[0]) && -1 != lines[i].indexOf("vfat")) {
//再用空格分隔
String[] blocks = lines[i].split("\\s");
for(int j=0; j<blocks.length; j++) {
//判断是否是挂载为vfat类型
if(-1 != blocks[j].indexOf(path[0])) {
//Test if it is the external sd card.
}
}
}
}
我有一个使用ListPreference的应用程序,其中要求用户选择他们想要保存东西的位置。
在那个应用程序中,我扫描了/proc/mounts和/system/etc/vold。Fstab用于sdcard挂载点。我将每个文件的挂载点存储到两个单独的arraylist中。
然后,我将一个列表与另一个列表进行比较,并丢弃了不在两个列表中的项目。这给了我一个到每个sdcard的根路径列表。
从那里,我用File.exists()、File.isDirectory()和File.canWrite()测试了这些路径。如果这些测试中的任何一个为假,我将从列表中丢弃该路径。
无论列表中剩下什么,我都转换为String[]数组,以便ListPreference值属性可以使用它。
您可以在这里查看代码
这就是我如何找到外部存储路径。
public static String getExternalStoragePath(Context context){
File[] f = ContextCompat.getExternalFilesDirs(context, null);
String internalPath = Environment.getExternalStorageDirectory().getAbsolutePath();
String excessive = "";
String externalPath = "";
for (File file : f) {
if (file.getAbsolutePath().startsWith(internalPath)) {
excessive = file.getAbsolutePath().replaceAll(internalPath, "");
}
}
for (File file : f) {
if (!file.getAbsolutePath().startsWith(excessive)) {
externalPath = file.getAbsolutePath().replaceAll(excessive, "");
}
}
return externalPath;
}
/sdcard =>内部存储(这是一个符号链接,但应该工作)
/mnt/extSdCard =>外部sd卡
这是三星Galaxy S3
你可以相信这对大多数人来说都是真的……但是要仔细检查!
这么晚了,但最终我得到了一些东西,我已经测试了大多数设备(通过制造商和android版本),它在android 2.2+上工作。如果您发现它不起作用,请用您的设备名称注释它。我会解决的。如果有人感兴趣,我会解释它是如何工作的。
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStreamReader;
import android.util.Log;
/**
* @author ajeet
*05-Dec-2014 2014
*
*/
public class StorageUtil {
public boolean isRemovebleSDCardMounted() {
File file = new File("/sys/class/block/");
File[] files = file.listFiles(new MmcblkFilter("mmcblk\\d$"));
boolean flag = false;
for (File mmcfile : files) {
File scrfile = new File(mmcfile, "device/scr");
if (scrfile.exists()) {
flag = true;
break;
}
}
return flag;
}
public String getRemovebleSDCardPath() throws IOException {
String sdpath = null;
File file = new File("/sys/class/block/");
File[] files = file.listFiles(new MmcblkFilter("mmcblk\\d$"));
String sdcardDevfile = null;
for (File mmcfile : files) {
Log.d("SDCARD", mmcfile.getAbsolutePath());
File scrfile = new File(mmcfile, "device/scr");
if (scrfile.exists()) {
sdcardDevfile = mmcfile.getName();
Log.d("SDCARD", mmcfile.getName());
break;
}
}
if (sdcardDevfile == null) {
return null;
}
FileInputStream is;
BufferedReader reader;
files = file.listFiles(new MmcblkFilter(sdcardDevfile + "p\\d+"));
String deviceName = null;
if (files.length > 0) {
Log.d("SDCARD", files[0].getAbsolutePath());
File devfile = new File(files[0], "dev");
if (devfile.exists()) {
FileInputStream fis = new FileInputStream(devfile);
reader = new BufferedReader(new InputStreamReader(fis));
String line = reader.readLine();
deviceName = line;
}
Log.d("SDCARD", "" + deviceName);
if (deviceName == null) {
return null;
}
Log.d("SDCARD", deviceName);
final File mountFile = new File("/proc/self/mountinfo");
if (mountFile.exists()) {
is = new FileInputStream(mountFile);
reader = new BufferedReader(new InputStreamReader(is));
String line = null;
while ((line = reader.readLine()) != null) {
// Log.d("SDCARD", line);
// line = reader.readLine();
// Log.d("SDCARD", line);
String[] mPonts = line.split("\\s+");
if (mPonts.length > 6) {
if (mPonts[2].trim().equalsIgnoreCase(deviceName)) {
if (mPonts[4].contains(".android_secure")
|| mPonts[4].contains("asec")) {
continue;
}
sdpath = mPonts[4];
Log.d("SDCARD", mPonts[4]);
}
}
}
}
}
return sdpath;
}
static class MmcblkFilter implements FilenameFilter {
private String pattern;
public MmcblkFilter(String pattern) {
this.pattern = pattern;
}
@Override
public boolean accept(File dir, String filename) {
if (filename.matches(pattern)) {
return true;
}
return false;
}
}
}