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

求助:Android Scoped Storage本地文件目录合法Uri获取方案

解决Android Scoped Storage下统一操作内部目录与SD卡的问题

问题原因

你遇到的异常是因为 DocumentFile.fromTreeUri() 仅支持 content:// 格式的树Uri,而 DocumentFile.fromFile() 生成的是 file:// 格式的Uri,不符合该方法的要求,因此抛出"Invalid URI"异常。

可行解决方案

其实你完全不需要将内部目录转成Tree Uri,就能用同一套DocumentFile API操作内部目录和SD卡:

  1. 内部私有目录(context.filesDir):直接通过DocumentFile.fromFile()获取实例,app本身拥有该目录的完整访问权限,无需额外申请权限:
    val internalDirDoc = DocumentFile.fromFile(context.filesDir)
    // 直接用DocumentFile API操作,比如列出文件、创建文件
    val files = internalDirDoc.listFiles()
    val newFile = internalDirDoc.createFile("text/plain", "test.txt")
    
  2. SD卡目录:通过SAF(存储访问框架)的ACTION_OPEN_DOCUMENT_TREE让用户选择SD卡根目录或目标子目录,获取合法的content://树Uri后,再用DocumentFile.fromTreeUri()获取实例:
    // 启动SAF选择目录
    val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).apply {
        flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION or Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
    }
    startActivityForResult(intent, REQUEST_CODE_PICK_SD_DIR)
    
    // 在onActivityResult或registerForActivityResult中处理返回结果
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == REQUEST_CODE_PICK_SD_DIR && resultCode == Activity.RESULT_OK) {
            data?.data?.let { treeUri ->
                // 持久化权限,避免重启后失效
                context.contentResolver.takePersistableUriPermission(
                    treeUri,
                    Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
                )
                val sdDirDoc = DocumentFile.fromTreeUri(context, treeUri)
                // 同样用DocumentFile API操作SD卡目录
            }
        }
    }
    

为什么这样能统一操作

DocumentFile.fromFile()和DocumentFile.fromTreeUri()返回的都是DocumentFile实例,两者拥有完全一致的API(如listFiles()、createFile()、delete()、exists()等),你可以直接用同一套函数接收DocumentFile参数,无需区分来源。

关于获取内部目录合法Tree Uri的说明

系统不允许通过SAF或其他方式获取app私有目录的content://树Uri,因为该目录属于app私有空间,只有app本身有权限直接访问,无需通过Scoped Storage的SAF机制。强行转换只会触发异常,没有实际意义。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 07:10:29