如何从DocumentFile获取用于EXTRA_INITIAL_URI的目录URI?

移动开发 2026-07-09

我的应用让用户选择一个公共目录(使用 Intent.ACTION_OPEN_DOCUMENT_TREE)来创建一个用于保存文件的目录,稍后可以从设备中提取。我还想把创建的目录的路径持久化,以便在应用中更容易访问。

为此我尝试使用 File.mkdir()Files.createDirectory(),但都没能创建出目录,因此我决定如下所示使用 DocumentFile

fun saveFileDirectory(uri: Uri) {

    val chosenDirectory = DocumentFile.fromTreeUri(applicationContext, uri)
    if (chosenDirectory != null) {
        val newDirectory = chosenDirectory.createDirectory("newDirectory")

        newDirectory?.createDirectory("dir1")
        newDirectory?.createDirectory("dir2")

        val newUri = newDirectory?.uri

        //persisting the path
        viewModelScope.launch {
            applicationContext.dataStore.updateData { data ->
                data.copy(saveFileDirectory = newUri!!)
            }
        }
}

这段代码能够成功创建目录并将创建目录的Uri保存下来,但当我把该持久化的Uri作为文件选择器的初始Uri使用时,用户所选的目录(它是创建目录的父目录)会被打开。

例如,用户选择了 “/save” 目录,因此输入Uri为

content://com.android.externalstorage.documents/tree/primary:save

函数 saveFileDirectory 将保存以下路径:

content://com.android.externalstorage.documents/tree/primary:save/document/primary:save/newDirectory

随后,该Uri会被读入一个名为 localSaveFileDirectory 的变量,并像下面这样用作文件选择器的初始Uri:

val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
    addCategory(Intent.CATEGORY_OPENABLE)
    putExtra(Intent.EXTRA_TITLE, "test.csv")
    putExtra(DocumentsContract.EXTRA_INITIAL_URI, Uri.withAppendedPath(localSaveFileDirectory, "dir1"))
    type = "*/*"
}
launcherRead.launch(intent)

然而,当用户尝试选择文件时,会打开 “/save” 目录。
我希望它打开 “/save/newDirectory”。

解决方案

我最终为所有必需的目录分别持久化 Uri 的值

fun saveFileDirectory(uri: Uri) {
    val chosenDirectory = DocumentFile.fromTreeUri(applicationContext, uri)
    if (chosenDirectory != null) {
        val newDirectory = chosenDirectory.createDirectory("newDirectory")

        val dir1Directory = newDirectory?.createDirectory("dir1")
        val dir2Directory = newDirectory?.createDirectory("dir2")

        val dir1Uri = dir1Directory?.uri
        val dir2Uri = dir2Directory?.uri

        saveFileDirectory1 = dir1Uri!!
        saveFileDirectory2 = dir2Uri!!

        viewModelScope.launch {
            applicationContext.dataStore.updateData { data ->
                data.copy(
                    saveFileDirectory1 = dir1Uri!!,
                    saveFileDirectory2 = dir2Uri!!
                )
            }
        }
    }
}

然后为需要它们的每个函数获取这些 Uri,如下例所示。
getSaveFileDirectory1() 输出 saveFileDirectory1 变量的值。

val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
    addCategory(Intent.CATEGORY_OPENABLE)
    putExtra(Intent.EXTRA_TITLE, "test.csv")
    putExtra(DocumentsContract.EXTRA_INITIAL_URI, getSaveFileDirectory1())
    type = "*/*"
}
launcherRead.launch(intent)
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章