有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java在不使用findFiles()的情况下获取文档树的子文档文件

我有一个从ACTION_OPEN_DOCUMENT_TREE获取的树URI,如果不使用findFiles()如何获取此树的子文档文件?假设我知道如何获取它的documentId、绝对路径或URI。我需要与文档树关联的权限

这就是我现在拥有的:

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

它返回docFile作为TreeDocumentFile,即我的根目录的子目录。我有写权限,可以对它使用createFile(),因为它位于ACTION_OPEN_DOCUMENT_TREE的文档树下

所以它可以工作,但是findFile()非常慢

如果我尝试使用文档,请这样做:

// 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.安卓.externalstorage.documents/tree/1A0E-0E2E:myChildDirectory/document/1A0E-0E2E:myChildDirectory"

它返回一个以docFile为根的新TreeDocumentFile,而不是作为原始文档树(root)的子级返回docFile。所以我没有写这棵树的权限

如果我这样做:

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

我得到了一个看起来像我想要的URI,但它是一个URI,而不是一个文档文件

如果我执行与上面相同的操作,但使用fromTreeUri()从此uri构建文档文件:

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

我得到的是原始的树文档文件,而不是代表孩子的文档文件


共 (2) 个答案

  1. # 1 楼答案

    使用当前的API无法实现您想要的功能。获得make aTreeDocumentFile(支持createFilecreateDirectorylistFilesrenameToDocumentFile的私有子类)的唯一方法是通过DocumentFile.fromTreeUri(它只提供您找到的根树URI)或通过现有的TreeDocumentFile{}方法,这是findFile内部使用的方法

    您应该在issuetracker.google.com上提交一个功能请求,以添加一个新的静态方法来满足您的需要

  2. # 2 楼答案

    有可能的解决方案:

    https://www.reddit.com/r/androiddev/comments/orytnx/fixing_treedocumentfilefindfile_lousy_performance/

    以下是以上链接的引文:

      @Nullable
    static public DocumentFile findFile(@NonNull context, @NonNull DocumentFile documentFile, @NonNull String displayName) {
    
    
        if(!(documentFile instanceof TreeDocumentFile)) {
            return documentFile.findFile(displayName);
        }
    
        final ContentResolver resolver = context.getContentResolver();
        final Uri childrenUri = DocumentsContract.buildChildDocumentsUriUsingTree(documentFile.getUri(),
                DocumentsContract.getDocumentId(documentFile.getUri()));
    
        Cursor c = null;
        try {
            c = resolver.query(childrenUri, new String[] {
                    DocumentsContract.Document.COLUMN_DOCUMENT_ID,
                    DocumentsContract.Document.COLUMN_DISPLAY_NAME,
            }, null, null, null);
    
            if(c != null) {
                while (c.moveToNext()) {
                    if (displayName.equals(c.getString(1))) {
                        return new TreeDocumentFile(documentFile,
                                context,
                                DocumentsContract.buildDocumentUriUsingTree(documentFile.getUri(), c.getString(0)));
                    }
                }
            }
        } catch (Exception e) {
            Log.w(TAG, "query failed: " + e);
        } finally {                 
            IOUtils.closeQuietly(c);
        }
    
        return null;
    }
    

    Note that for accessing package protected class TreeDocumentFile, you will have to put function above in a helper class in package androidx.documentfile.provider. After this, replace all calls of DocumentFile#findFile by this replacement or a Kotlin adaptation of it.