在不使用 findFiles() 的情况下获取作为文档树 child 的 DocumentFile
Get a DocumentFile that is a child of a document tree without using findFiles()
我有一个从 ACTION_OPEN_DOCUMENT_TREE
获得的树 URI,如何在不使用 findFiles()
[ 的情况下获得作为这棵树的 child 的 DocumentFile =44=]?假设我知道如何获取它的 documentId、它的绝对路径或它的 URI。我需要与文档树关联的权限。
这是我现在拥有的:
DocumentFile rootTree = DocumentFile.fromTreeUri(context, rootTreeUri);
DocumentFile docFile = rootTree.findFile(fileName);
它 returns docFile
作为 TreeDocumentFile,child 我的根目录。我有写权限,可以在上面使用 createFile()
,因为它在 ACTION_OPEN_DOCUMENT_TREE
.
的文档树下
所以它有效,但 findFile()
真的很慢。
如果我尝试像这样使用 DocumentsContract:
// 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"
它 returns 一个新的 TreeDocumentFile 以 docFile
为根,而不是 docFile
作为我原始文档树(根)的 child。所以我没有这棵树的写权限。
如果我这样尝试:
Uri docUri = DocumentsContract.buildDocumentUriUsingTree(rootTreeUri, documentId);
// Result: "content://com.android.externalstorage.documents/tree/1A0E-0E2E:/document/1A0E-0E2E:myChildDirectory"
我得到的 URI 实际上看起来像我想要的,但它是 URI,而不是 DocumentFile。
如果我执行与上面相同的操作,但使用 fromTreeUri() 从此 uri 构建一个 DocumentFile:
Uri docUri = DocumentsContract.buildDocumentUriUsingTree(rootTreeUri, documentId);
DocumentFile docFile = DocumentFile.fromTreeUri(context, docUri);
// Result: "content://com.android.externalstorage.documents/tree/1A0E-0E2E:/document/1A0E-0E2E:"
我得到的是原始树 DocumentFile,而不是代表 child 的 DocumentFile。
当前的 API 无法满足您的需求。获得 make a TreeDocumentFile(支持 createFile
、createDirectory
、listFiles
和 renameTo
的 DocumentFile
的私有子类的唯一方法是通过 DocumentFile.fromTreeUri
(它只为您提供您所找到的根树 URI)或通过现有的 TreeDocumentFile
的 listFiles()
方法,这是 findFile
内部使用的方法。
您应该在 issuetracker.google.com 上提交功能请求以添加满足您需要的新静态方法。
可能的解决方案:
下面是上面的引用 link:
@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.
我有一个从 ACTION_OPEN_DOCUMENT_TREE
获得的树 URI,如何在不使用 findFiles()
[ 的情况下获得作为这棵树的 child 的 DocumentFile =44=]?假设我知道如何获取它的 documentId、它的绝对路径或它的 URI。我需要与文档树关联的权限。
这是我现在拥有的:
DocumentFile rootTree = DocumentFile.fromTreeUri(context, rootTreeUri);
DocumentFile docFile = rootTree.findFile(fileName);
它 returns docFile
作为 TreeDocumentFile,child 我的根目录。我有写权限,可以在上面使用 createFile()
,因为它在 ACTION_OPEN_DOCUMENT_TREE
.
所以它有效,但 findFile()
真的很慢。
如果我尝试像这样使用 DocumentsContract:
// 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"
它 returns 一个新的 TreeDocumentFile 以 docFile
为根,而不是 docFile
作为我原始文档树(根)的 child。所以我没有这棵树的写权限。
如果我这样尝试:
Uri docUri = DocumentsContract.buildDocumentUriUsingTree(rootTreeUri, documentId);
// Result: "content://com.android.externalstorage.documents/tree/1A0E-0E2E:/document/1A0E-0E2E:myChildDirectory"
我得到的 URI 实际上看起来像我想要的,但它是 URI,而不是 DocumentFile。
如果我执行与上面相同的操作,但使用 fromTreeUri() 从此 uri 构建一个 DocumentFile:
Uri docUri = DocumentsContract.buildDocumentUriUsingTree(rootTreeUri, documentId);
DocumentFile docFile = DocumentFile.fromTreeUri(context, docUri);
// Result: "content://com.android.externalstorage.documents/tree/1A0E-0E2E:/document/1A0E-0E2E:"
我得到的是原始树 DocumentFile,而不是代表 child 的 DocumentFile。
当前的 API 无法满足您的需求。获得 make a TreeDocumentFile(支持 createFile
、createDirectory
、listFiles
和 renameTo
的 DocumentFile
的私有子类的唯一方法是通过 DocumentFile.fromTreeUri
(它只为您提供您所找到的根树 URI)或通过现有的 TreeDocumentFile
的 listFiles()
方法,这是 findFile
内部使用的方法。
您应该在 issuetracker.google.com 上提交功能请求以添加满足您需要的新静态方法。
可能的解决方案:
下面是上面的引用 link:
@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.