You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何获取手机SD卡或内置存储中指定文件夹的路径?

搞定Android读取指定文件夹(内置/SD卡)的问题

嘿,我懂你遇到的麻烦了——之前用Environment.getExternalStorageDirectory()的方法,在高版本Android上可能不好使,尤其是SD卡的访问,现在Google的存储规则变了嘛。下面给你分情况讲清楚怎么适配:

一、为啥旧方法会失效?

从Android 10(API 29)开始,谷歌搞了个Scoped Storage(分区存储),原来的Environment.getExternalStorageDirectory()被标成废弃了,而且直接硬怼外部存储路径会被限制,SD卡的访问权限管得更严,不同品牌手机的SD卡路径还不一样,很容易踩坑。

二、分版本适配方案

1. Android 10及以上(必看!)

如果你的应用目标SDK是30+,推荐用**SAF(存储访问框架)**来让用户自己选文件夹——这是最合规的方式,还不用纠结SD卡路径的问题。步骤很简单:

  • 先启动文件夹选择器:
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(intent, REQUEST_CODE_PICK_FOLDER);
// 要是用AndroidX的话,建议用registerForActivityResult替代startActivityForResult
  • 然后在回调里拿到用户选的文件夹Uri,还能把权限持久化,下次打开不用再选:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == REQUEST_CODE_PICK_FOLDER && resultCode == RESULT_OK) {
        Uri treeUri = data.getData();
        // 把权限存下来,下次启动直接用
        getContentResolver().takePersistableUriPermission(treeUri,
                Intent.FLAG_GRANT_READ_URI_PERMISSION);
        DocumentFile selectedFolder = DocumentFile.fromTreeUri(this, treeUri);
        // 遍历文件夹里的文件
        for (DocumentFile file : selectedFolder.listFiles()) {
            String fileName = file.getName();
            Uri fileUri = file.getUri();
            // 这里就可以处理你的文件啦
        }
    }
}

这个方法的好处是:不管是内置存储还是SD卡的自定义文件夹都能访问,完全符合高版本Android的权限要求,不会被系统限制。

2. Android 9及以下

低版本还能继续用旧的File API,但SD卡的路径得找对:

  • 内置存储的"myfolder":还是用new File(Environment.getExternalStorageDirectory(), "myfolder")就行
  • SD卡的路径:别硬编码!用getExternalFilesDirs()来获取所有外部存储目录:
File[] externalDirs = getExternalFilesDirs(null);
// externalDirs[0]是内置存储的应用专属目录,externalDirs[1]存在的话就是SD卡的对应目录
// 要访问SD卡根目录下的myfolder,得往上跳两级目录
for (File dir : externalDirs) {
    if (dir != null && !dir.equals(getExternalFilesDir(null))) {
        File sdFolder = new File(dir.getParentFile().getParentFile(), "myfolder");
        if (sdFolder.exists() && sdFolder.isDirectory()) {
            // 找到SD卡上的目标文件夹啦,开始处理文件
        }
    }
}

注意:这种方法在Android 10+会因为分区存储的限制失效,所以只适合低版本适配。

三、统一适配小技巧

如果你的应用要覆盖多个版本,加个版本判断就行:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
    // 用SAF的方式
} else {
    // 用旧的File API方式
}

另外,要是你暂时不想改SAF,在AndroidManifest里加android:requestLegacyExternalStorage="true"(仅针对API 29)能暂时绕过分区存储,但这只是过渡方案,谷歌未来可能会禁用,不建议长期用哦。


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

火山引擎 最新活动