文件与分享
文件与分享 · androidx.documentfile
DocumentFile:统一的文档树访问DocumentFile 1.1.0-rc01
fromFile、fromSingleUri 与 fromTreeUri 的职责划分与平台差异。
最后更新 2026-08-01
复制即用:打开文档树
// 请求用户选择一个目录(返回 treeUri)
private static final int OPEN_TREE_CODE = 1;
private void openDirectory() {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(intent, OPEN_TREE_CODE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == OPEN_TREE_CODE && resultCode == RESULT_OK) {
Uri treeUri = data.getData();
// 持久化权限(可选)
getContentResolver().takePersistableUriPermission(
treeUri,
Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
);
DocumentFile tree = DocumentFile.fromTreeUri(this, treeUri);
useTree(tree);
}
}
private void useTree(DocumentFile tree) {
// 列出文件
for (DocumentFile child : tree.listFiles()) {
Log.d("DocTree", child.getName() + " / " + child.getType());
}
// 创建文件
DocumentFile note = tree.createFile("text/plain", "note.txt");
// 创建目录
DocumentFile dir = tree.createDirectory("images");
}三种入口,三种权限来源
| 入口 | 权限来源 | 平台要求 |
|---|---|---|
fromFile(File) | 不获得额外权限(java.io.File 原有权限) | 无 |
fromSingleUri(context, uri) | ACTION_OPEN_DOCUMENT/ACTION_CREATE_DOCUMENT 单次授权 | API 19+ |
fromTreeUri(context, uri) | ACTION_OPEN_DOCUMENT_TREE 目录授权 | API 21+ |
核心:DocumentFile 只做访问,不替你获得权限——权限来自用户选择的 URI。
树内操作
DocumentFile tree = DocumentFile.fromTreeUri(context, treeUri);
tree.listFiles() // 遍历子项
tree.createFile(mime, name) // 建文件
tree.createDirectory(name) // 建目录
tree.findFile(name) // 查找
file.delete() // 删除
file.renameTo(name) // 重命名底层实现类(RawDocumentFile、SingleDocumentFile、TreeDocumentFile、DocumentsContractApi19)按平台版本分发——API 24 和 API 33 调用走不同实现。
读写内容
// DocumentFile 不处理流,读写用 ContentResolver
Uri uri = file.getUri();
InputStream input = getContentResolver().openInputStream(uri);
// 或用 OutputStream 写
OutputStream output = getContentResolver().openOutputStream(uri, "w");常见陷阱
- 忘持久化权限:重启后 treeUri 权限丢失(用
takePersistableUriPermission)。 - 虚拟文档:
isVirtual()为 true 的可能没有直接流。 - fromFile 无额外权限:不能访问其他应用私有目录。
- DocumentFile 不做复制:流复制自己写。
明确不解决什么
- 不授予权限:权限来自用户选择的 URI,
DocumentFile只做访问。 - 不做流复制与编码转换:读写仍需
ContentResolver或InputStream/OutputStream。 - 不是通用文件系统抽象:虚拟文档(
isVirtual())可能没有可直接读取的流。
要点
- 三种入口对应三种权限来源;treeUri 是目录管理的常用入口。
- 树内 listFiles/createFile/createDirectory/findFile 递归工作。
- 读写流走 ContentResolver;DocumentFile 只封装元数据操作。
- 持久化权限记得 takePersistableUriPermission。