You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

API 19+下验证文件路径是否为SD卡及获取SD卡目录方案求助

解决API 19+下获取可移除SD卡路径的问题

我之前也踩过一模一样的坑!尤其是三星Tab S2这类设备,Environment.getExternalStorageDirectory()返回的居然是内置的不可移除存储,完全不是我们要的SD卡路径。毕竟Android对“外部存储”的定义本来就包含了内置可共享存储和可移除SD卡,旧方法根本没法区分两者。

针对API 19及以上的适配,给你两个靠谱的方案:

方案一:用Context.getExternalFilesDirs()(推荐)

这个API从API 19开始支持,会返回所有外部存储的App专属目录数组,包括内置存储和SD卡的。我们只需要从中筛选出可移除的SD卡路径即可:

import android.content.Context;
import android.os.Environment;
import java.io.File;

public class StorageUtils {
    // 获取可移除SD卡的根目录
    public static String getRemovableSdCardRoot(Context context) {
        File[] externalDirs = context.getExternalFilesDirs(null);
        
        for (File dir : externalDirs) {
            if (dir == null) continue;
            // 排除内置外部存储,剩下的就是SD卡的App专属目录
            if (!isInternalExternalStorage(dir)) {
                // 从App专属目录截取到SD卡根目录
                // 示例路径:/storage/XXXX-XXXX/Android/data/com.yourapp.package/files
                String appDirPath = dir.getAbsolutePath();
                return appDirPath.substring(0, appDirPath.indexOf("/Android/data"));
            }
        }
        return null; // 未检测到可移除SD卡
    }

    // 判断是否是内置的外部存储
    private static boolean isInternalExternalStorage(File dir) {
        return Environment.getExternalStorageDirectory().equals(dir);
    }
}

注意事项:

  • 这个方法返回的是SD卡的根目录,如果你只需要访问App在SD卡上的私有目录,直接用dir.getAbsolutePath()即可,无需截取
  • 权限方面:API 19-28需要添加READ_EXTERNAL_STORAGE权限;API 29+如果只访问App私有目录不需要额外权限,若要访问SD卡其他公共目录,需要适配分区存储,或者针对API 30+申请MANAGE_EXTERNAL_STORAGE权限

方案二:读取系统挂载信息(备选,兼容性稍差)

如果上面的方法不满足需求,还可以通过读取/proc/mounts文件来解析SD卡挂载路径,但这种方法依赖厂商的挂载规则,稳定性不如方案一:

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class StorageUtils {
    public static List<String> getSdCardPaths() {
        List<String> paths = new ArrayList<>();
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader("/proc/mounts"));
            String line;
            while ((line = reader.readLine()) != null) {
                // 筛选出vfat或exfat格式的可移除存储(SD卡常见格式)
                if ((line.contains("vfat") || line.contains("exfat")) && line.contains("/storage/")) {
                    String[] parts = line.split(" ");
                    String path = parts[1];
                    // 排除内置存储的挂载路径
                    if (!path.equals(Environment.getExternalStorageDirectory().getAbsolutePath())) {
                        paths.add(path);
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return paths;
    }
}

提示:

  • 这个方法可能会返回多个路径,需要你自己验证哪些是有效的可移除SD卡路径
  • 同样需要对应的存储权限才能访问这些路径

内容的提问来源于stack exchange,提问作者Projava

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 09:20:16