2

[根据评论重写]

简化示例:

rootUri由 获得ACTION_OPEN_DOCUMENT_TREE。然后我创建一个文件夹(或更多嵌套文件夹):

val rootTree = DocumentFile.fromTreeUri(context, rootUri) // rootTree.name == "treeRoot" 
val childTree = rootTree.createDirectory("ChildDir1") // childTree.name == "ChildDir1"
val childUriStr = childTree.uri.toString()

我存储childUriStr到本地数据库中,以便以后重新创建childTree. childUriStr包含所需的所有元素:authorityrootTreedocumentId 和childTreedocumentId。所以childTree可以通过以下方式重新创建:

val childUri = Uri.parse(childUriStr)
val childTreeCopy = TreeDocumentFile(
                        DocumentFile.fromTreeUri(context, childTree), // equals rootTree
                        context,
                        childUri
                    )

但是TreeDocumentFile()构造函数是包私有的,只能在内部使用,并且由DocumentFile.fromTreeUri().

解决方法 1(慢):

var childTree = DocumentFile.fromTreeUri(context, childUri)!! // rootTree

// get subfolders
val subfolders = DocumentsContract.getDocumentId(childUri)
                     .substringAfter(
                         // root documentId
                         DocumentsContract.getDocumentId(childTree.uri))
                     ).trim('/').split('/')

// move down the folder structure
subfolders.forEach { childTree = childTree.findFile(it)!! }

// result
childTree

解决方法 2(有关 rootTree 的信息丢失):

val childAsRootUri = DocumentsContract.buildTreeDocumentUri(
                         childUri.authority,
                         DocumentsContract.getDocumentId(childUri)
                     )

var childAsRootTree = DocumentFile.fromTreeUri(context, childAsRootUri)!!

在这里,树种在子文件夹中,所以我不能使用childAsRootTree.parent,不能解析名称childAsRootTree.name == null,可能还有其他一些小问题 - 绝对不推荐。DocumentFile.fromSingleUri()TreeDocumentFile.

解决方法 3(要维护的其他代码):

基于编写我自己的包装器TreeDocumentFile

用例(无需阅读)

请注意,上面描述的是一个简化的例子。一个与我类似的潜在用例是:用户通过应用内文件资源管理器选择单个文件或包含多个文件的文件夹(步骤 1)。应用内文件资源管理器的根文件通过ACTION_OPEN_DOCUMENT_TREE. 用户可以处理文件,然后如果用户在步骤 1 中选择了文件夹,则处理后的文件将保存在同一目录中,如果用户在步骤 1 中选择了文件,则处理后的文件将保存在新文件夹中的新文件夹中(这需要访问选定的文件)。用户稍后可以决定选择不同的保存文件排列方式。

4

1 回答 1

0

尝试这个。

    fun fromSubDirectoryUri(context: Context, uri: Uri): DocumentFile? {
        val documentId = DocumentsContract.getDocumentId(uri)
        return DocumentsContract.buildTreeDocumentUri(uri.authority, documentId)
            ?.let { DocumentFile.fromTreeUri(context, it) }
    }

它在我的环境中工作。但是,我不确定它是否适用于其他环境,因为我在 developer.android.com 上找不到官方文档。

于 2021-05-16T09:08:19.587 回答