获取Android外部SD卡的路径

3

如果可用,我希望能够获取设备上的外部SdCard路径。通过使用Environment.getExternalStorageDirectory().getAbsolutePath(),我可以获取到内部存储的路径。因此,我使用了下面的类来检测外部存储。

public class ExternalStorage {
public static final String SD_CARD = "sdCard";
public static final String EXTERNAL_SD_CARD = "externalSdCard";

/**
 * @return True if the external storage is available. False otherwise.
 */
public static boolean isAvailable() {
    String state = Environment.getExternalStorageState();
    if (Environment.MEDIA_MOUNTED.equals(state) || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
        return true;
    }
    return false;
}

public static String getSdCardPath() {
    return Environment.getExternalStorageDirectory().getPath() + "/";
}

/**
 * @return True if the external storage is writable. False otherwise.
 */
public static boolean isWritable() {
    String state = Environment.getExternalStorageState();
    if (Environment.MEDIA_MOUNTED.equals(state)) {
        return true;
    }
    return false;

}

/**
 * @return A map of all storage locations available
 */
public static Map<String, File> getAllStorageLocations() {
    Map<String, File> map = new HashMap<String, File>(10);

    List<String> mMounts = new ArrayList<String>(10);
    List<String> mVold = new ArrayList<String>(10);
    mMounts.add("/mnt/sdcard");
    mVold.add("/mnt/sdcard");

    try {
        File mountFile = new File("/proc/mounts");
        if(mountFile.exists()){
            Scanner scanner = new Scanner(mountFile);
            while (scanner.hasNext()) {
                String line = scanner.nextLine();
                if (line.startsWith("/dev/block/vold/")) {
                    String[] lineElements = line.split(" ");
                    String element = lineElements[1];

                    // don't add the default mount path
                    // it's already in the list.
                    if (!element.equals("/mnt/sdcard"))
                        mMounts.add(element);
                }
            }
        }
    }
    catch (Exception e) {
        e.printStackTrace();
    }

    try {
        File voldFile = new File("/system/etc/vold.fstab");
        if(voldFile.exists()){
            Scanner scanner = new Scanner(voldFile);
            while (scanner.hasNext()) {
                String line = scanner.nextLine();
                if (line.startsWith("dev_mount")) {
                    String[] lineElements = line.split(" ");
                    String element = lineElements[2];

                    if (element.contains(":"))
                        element = element.substring(0, element.indexOf(":"));
                    if (!element.equals("/mnt/sdcard"))
                        mVold.add(element);
                }
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

    for (int i = 0; i < mMounts.size(); i++) {
        String mount = mMounts.get(i);
        if (!mVold.contains(mount))
            mMounts.remove(i--);
    }
    mVold.clear();

    List<String> mountHash = new ArrayList<String>(10);

    for(String mount : mMounts){
        File root = new File(mount);
        if (root.exists() && root.isDirectory() && root.canWrite()) {
            File[] list = root.listFiles();
            String hash = "[";
            if(list!=null){
                for(File f : list){
                    hash += f.getName().hashCode()+":"+f.length()+", ";
                }
            }
            hash += "]";
            if(!mountHash.contains(hash)){
                String key = SD_CARD + "_" + map.size();
                if (map.size() == 0) {
                    key = SD_CARD;
                } else if (map.size() == 1) {
                    key = EXTERNAL_SD_CARD;
                }
                mountHash.add(hash);
                map.put(key, root);
            }
        }
    }

    mMounts.clear();

    if(map.isEmpty()){
        map.put(SD_CARD, Environment.getExternalStorageDirectory());
    }
    return map;
}

示例用法

    Map <String, File> externalLocations = ExternalStorage.getAllStorageLocations();
    File sdCard = externalLocations.get(ExternalStorage.SD_CARD);
    File externalSdCard=externalLocations.get(ExternalStorage.EXTERNAL_SD_CARD);

在一些设备上,例如三星Galaxy S3,它可以正确检测到外部SD卡并返回路径/storage/extSdCard。但是在其他设备上,如Sony Experia Z1和Z2,它无法检测到外部SD卡并给出了内部存储的路径。我该如何解决这个问题?


由于大多数Android设备(所有运行Android 4.4或更高版本的设备)无法访问可移动媒体上的任意位置,因此您可能需要重新考虑您正在进行的操作。 - CommonsWare
2个回答

2

使用以下代码以获取SD卡路径

public class DiskHelper
{

    public static final int MODE_INTERNAL = 0;
    public static final int MODE_EXTERNAL = 1;
    public static final int MODE_EXTERNAL_SD = 2;
    private  StatFs statFs;
    protected String path;
    public DiskHelper(int mode)
    {
        try
        {
            if(mode == 0)
            {
                path = Environment.getRootDirectory().getAbsolutePath();
                statFs = new StatFs(path);
                statFs.restat(path);
            }
            else if(mode == 1)
            {
                path = Environment.getExternalStorageDirectory().getAbsolutePath();
                statFs = new StatFs(path);
                statFs.restat(path);
            }
            else
            {
                for(String str : getExternalMounts())
                {
                    path = str;
                    statFs = new StatFs(str);
                    statFs.restat(str);
                    break;
                }
            }
        }
        catch(Exception e)
        {
            KLog.error(e);
        }
    }
    public String getPath()
    {
        return path;
    }
    public long getTotalMemory()
    {
        if(statFs == null)
        {
            return 0;
        }
        long total = ((long)statFs.getBlockCount() * (long)statFs.getBlockSize());
        return total;
    }

    public long getFreeMemory()
    {
        if(statFs == null)
        {
            return 0;
        }

        long free = ((long)statFs.getAvailableBlocks() * (long)statFs.getBlockSize());
        return free;
    }

    public long getBusyMemory()
    {
        if(statFs == null)
        {
            return 0;
        }
        long   total  = getTotalMemory();
        long   free   = getFreeMemory();
        long   busy   = total - free;
        return busy;
    }


    public static HashSet<String> getExternalMounts()
    {

        final HashSet<String> out = new HashSet<String>();
        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(Exception e)
        {
            KLog.error(e);
        }
        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;
    }
    private static final long  MEGABYTE = 1024L * 1024L;
    public static String humanReadableByteCount(long bytes, boolean si)
    {
        if(true)
        {
            long ret =  bytes / MEGABYTE;
            return ret + " MB";
        }
        int unit = si ? 1000 : 1024;
        if (bytes < unit) return bytes + " B";
        int exp = (int) (Math.log(bytes) / Math.log(unit));
        String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp-1) + (si ? "" : "i");
        return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre);
    }


}

那么

final DiskHelper sdDiskHelper = new DiskHelper(DiskHelper.MODE_EXTERNAL_SD);
path = sdDiskHelper.getPath();

你可以自定义这个类。

我使用了你的类,但在LG G3设备上出现了权限被拒绝的异常。Android不允许我在外部存储器上创建目录。 - Narsis

0

String secStore = System.getenv("SECONDARY_STORAGE");

File externalsdpath = new File(secStore);

这将获取外部SD卡的路径。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接