javaandroidstorage-access-frameworkdocumentfile

Get a DocumentFile that is a child of a document tree without using findFiles()


I have a tree URI that I got from ACTION_OPEN_DOCUMENT_TREE, how can I get a DocumentFile that is a child of this tree without using findFiles()? Given that I know how to get its documentId, its absolute path or its URI. I need the permissions associated with the document tree.

This is what I have right now:

DocumentFile rootTree = DocumentFile.fromTreeUri(context, rootTreeUri);
DocumentFile docFile = rootTree.findFile(fileName);

It returns docFile as a TreeDocumentFile, child of my root. I have write permission and can use createFile() on it since it is under the document tree from ACTION_OPEN_DOCUMENT_TREE.

So it works but findFile() is really slow.

If I try to use DocumentsContract like so:

// I know how to build the documentId from the file's absolute path
Uri uri = DocumentsContract.buildTreeDocumentUri(rootTreeUri.getAuthority(), documentId);
DocumentFile docFile = DocumentFile.fromTreeUri(context, uri);
// Result: "content://com.android.externalstorage.documents/tree/1A0E-0E2E:myChildDirectory/document/1A0E-0E2E:myChildDirectory"

It returns a new TreeDocumentFile rooted at docFile, not docFile as a child of my original document tree (root). So I don't have write permission on this tree.

And if I try like so:

Uri docUri = DocumentsContract.buildDocumentUriUsingTree(rootTreeUri, documentId);
// Result: "content://com.android.externalstorage.documents/tree/1A0E-0E2E:/document/1A0E-0E2E:myChildDirectory"

I get a URI that actually looks like what I want, but it's a URI, not a DocumentFile.

If I do the same as above but build a DocumentFile from this uri with fromTreeUri():

Uri docUri = DocumentsContract.buildDocumentUriUsingTree(rootTreeUri, documentId);
DocumentFile docFile = DocumentFile.fromTreeUri(context, docUri);
// Result: "content://com.android.externalstorage.documents/tree/1A0E-0E2E:/document/1A0E-0E2E:"

I get the original tree DocumentFile, not a DocumentFile representing the child.


Solution

  • What you want is not possible with the current APIs. The only way to get make a TreeDocumentFile (the private subclass of DocumentFile that supports createFile, createDirectory, listFiles, and renameTo) is through DocumentFile.fromTreeUri (which only gives you the root tree URI as you've found) or through an existing TreeDocumentFile's listFiles() method, which is what findFile uses internally.

    You should file a feature request on issuetracker.google.com to add a new static method that does what you need.