Как получить дочерний TreeDocumentFile от дочернего Uri? - PullRequest
1 голос
/ 21 января 2020

[Переписать, основываясь на комментариях]

Упрощенный пример:

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 содержит все необходимые элементы: authority, rootTree documentId и childTree documentId. Таким образом, 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). Файл root из проводника в приложении получен ACTION_OPEN_DOCUMENT_TREE. Пользователь может обрабатывать файлы, а затем обработанные файлы сохраняются в том же каталоге, если пользователь выбрал папку на шаге 1, или рядом с выбранным файлом в новой папке, если пользователь выбрал файл на шаге 1 (для этого требуется доступ к родительской папке выбранный файл). Позже пользователь может выбрать другое расположение сохраненных файлов.

...