有没有一种通用的方法来查找外部SD卡的位置?
请不要与外部存储混淆。
Environment.getExternalStorageState()
返回内部SD挂载点的路径,例如/mnt/sdcard
。但是问题是关于外部SD卡的。我怎么才能获得像/mnt/sdcard/external_sd
这样的路径(它可能因设备而异)?
我想我最终会通过文件系统名称过滤mount
命令的输出。但我不确定这种方法是否足够健壮。
有没有一种通用的方法来查找外部SD卡的位置?
请不要与外部存储混淆。
Environment.getExternalStorageState()
返回内部SD挂载点的路径,例如/mnt/sdcard
。但是问题是关于外部SD卡的。我怎么才能获得像/mnt/sdcard/external_sd
这样的路径(它可能因设备而异)?
我想我最终会通过文件系统名称过滤mount
命令的输出。但我不确定这种方法是否足够健壮。
public String isRemovableSDCardAvailable() {
final String FLAG = "mnt";
final String SECONDARY_STORAGE = System.getenv("SECONDARY_STORAGE");
final String EXTERNAL_STORAGE_DOCOMO = System.getenv("EXTERNAL_STORAGE_DOCOMO");
final String EXTERNAL_SDCARD_STORAGE = System.getenv("EXTERNAL_SDCARD_STORAGE");
final String EXTERNAL_SD_STORAGE = System.getenv("EXTERNAL_SD_STORAGE");
final String EXTERNAL_STORAGE = System.getenv("EXTERNAL_STORAGE");
Map<Integer, String> listEnvironmentVariableStoreSDCardRootDirectory = new HashMap<Integer, String>();
listEnvironmentVariableStoreSDCardRootDirectory.put(0, SECONDARY_STORAGE);
listEnvironmentVariableStoreSDCardRootDirectory.put(1, EXTERNAL_STORAGE_DOCOMO);
listEnvironmentVariableStoreSDCardRootDirectory.put(2, EXTERNAL_SDCARD_STORAGE);
listEnvironmentVariableStoreSDCardRootDirectory.put(3, EXTERNAL_SD_STORAGE);
listEnvironmentVariableStoreSDCardRootDirectory.put(4, EXTERNAL_STORAGE);
File externalStorageList[] = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
externalStorageList = getContext().getExternalFilesDirs(null);
}
String directory = null;
int size = listEnvironmentVariableStoreSDCardRootDirectory.size();
for (int i = 0; i < size; i++) {
if (externalStorageList != null && externalStorageList.length > 1 && externalStorageList[1] != null)
directory = externalStorageList[1].getAbsolutePath();
else
directory = listEnvironmentVariableStoreSDCardRootDirectory.get(i);
directory = canCreateFile(directory);
if (directory != null && directory.length() != 0) {
if (i == size - 1) {
if (directory.contains(FLAG)) {
Log.e(getClass().getSimpleName(), "SD Card's directory: " + directory);
return directory;
} else {
return null;
}
}
Log.e(getClass().getSimpleName(), "SD Card's directory: " + directory);
return directory;
}
}
return null;
}
/**
* Check if can create file on given directory. Use this enclose with method
* {@link BeginScreenFragement#isRemovableSDCardAvailable()} to check sd
* card is available on device or not.
*
* @param directory
* @return
*/
public String canCreateFile(String directory) {
final String FILE_DIR = directory + File.separator + "hoang.txt";
File tempFlie = null;
try {
tempFlie = new File(FILE_DIR);
FileOutputStream fos = new FileOutputStream(tempFlie);
fos.write(new byte[1024]);
fos.flush();
fos.close();
Log.e(getClass().getSimpleName(), "Can write file on this directory: " + FILE_DIR);
} catch (Exception e) {
Log.e(getClass().getSimpleName(), "Write file error: " + e.getMessage());
return null;
} finally {
if (tempFlie != null && tempFlie.exists() && tempFlie.isFile()) {
// tempFlie.delete();
tempFlie = null;
}
}
return directory;
}
private static ArrayList<String> getAllStorages(Context context)
{
ArrayList<String> storagePaths = new ArrayList<>();
storagePaths.add(Environment.getExternalStorageDirectory().getAbsolutePath());
try
{
File[] externalDirs = context.getExternalFilesDirs(null);
if (externalDirs != null)
for (File file : externalDirs)
{
storagePaths.add(file.getAbsolutePath());
}
externalDirs = context.getExternalMediaDirs();
if (externalDirs != null)
for (File file : externalDirs)
{
storagePaths.add(file.getAbsolutePath());
}
}
catch (Throwable e)
{
// ignore
}
try
{
StorageManager sm=(StorageManager) context.getSystemService(context.STORAGE_SERVICE);
for (StorageVolume e:sm.getStorageVolumes())
{
String s= (String) StorageVolume.class.getMethod("getPath").invoke(e);
storagePaths.add(s);
}
}
catch (Throwable e)
{
//ignore
}
for (String key: new String[]{
"SECONDARY_STORAGE",
"EXTERNAL_STORAGE",
"EMULATED_STORAGE_TARGET",
"EXTERNAL_STORAGE_DOCOMO",
"EXTERNAL_SDCARD_STORAGE",
"EXTERNAL_SD_STORAGE",
// add more if you have :-D
})
{
String externalStorage = System.getenv(key);
if (externalStorage != null && !externalStorage.isEmpty())
{
String[] externalPaths = externalStorage.split(":");
for (String e:externalPaths)
{
storagePaths.add(e);
}
}
}
ArrayList<String> result=new ArrayList<>();
for (String s:storagePaths)
{
File f=new File(s);
File f2=f;
while (f2 != null)
{
if (f2.canRead())
{
f = f2;
}
f2 = f2.getParentFile();
}
try
{
f = f.getCanonicalFile();
}
catch (IOException e)
{
// ignore
}
s = f.getPath();
if (!result.contains(s))
{
result.add(s);
}
}
return result;
}
它适用于所有外部设备,但请确保仅获取外部设备文件夹名称,然后使用File类从给定位置获取文件。
public static List<String> getExternalMounts() {
final List<String> out = new ArrayList<>();
String reg = "(?i).*vold.*(vfat|ntfs|exfat|fat32|ext3|ext4).*rw.*";
String s = "";
try {
final Process process = new ProcessBuilder().command("mount")
.redirectErrorStream(true).start();
process.waitFor();
final InputStream is = process.getInputStream();
final byte[] buffer = new byte[1024];
while (is.read(buffer) != -1) {
s = s + new String(buffer);
}
is.close();
} catch (final Exception e) {
e.printStackTrace();
}
// parse output
final String[] lines = s.split("\n");
for (String line : lines) {
if (!line.toLowerCase(Locale.US).contains("asec")) {
if (line.matches(reg)) {
String[] parts = line.split(" ");
for (String part : parts) {
if (part.startsWith("/"))
if (!part.toLowerCase(Locale.US).contains("vold"))
out.add(part);
}
}
}
}
return out;
}
调用:
List<String> list=getExternalMounts();
if(list.size()>0)
{
String[] arr=list.get(0).split("/");
int size=0;
if(arr!=null && arr.length>0) {
size= arr.length - 1;
}
File parentDir=new File("/storage/"+arr[size]);
if(parentDir.listFiles()!=null){
File parent[] = parentDir.listFiles();
for (int i = 0; i < parent.length; i++) {
// get file path as parent[i].getAbsolutePath());
}
}
}
获取外部存储器的访问权限
为了在外部存储器上读取或写入文件,您的应用程序必须获取READ_EXTERNAL_STORAGE或WRITE_EXTERNAL_STORAGE系统权限。例如:
<manifest ...>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
...
</manifest>
这是我找到外部存储路径的方法。
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
大多数情况下这应该是正确的...不过最好再确认一下!
/sdcard
是我的索尼2305上外部链接。 - jiggunjer
adb shell echo $EXTERNAL_STORAGE
- Charles L.