如何在Intent.ACTION_OPEN_DOCUMENT_TREE选中的目录写入文件?
如何在选中的目录下写入文件?
嘿,我来帮你搞定这个问题!你已经通过ACTION_OPEN_DOCUMENT_TREE拿到了Tree URI,还转成了实际路径,现在要在这个路径下写文件对吧?这里有两种方法,我给你详细拆解:
方法一:直接用转换后的路径写入(注意权限限制)
如果你想直接用FileUtil.getFullPathFromTreeUri返回的路径操作,可以直接创建File对象,通过FileOutputStream写入内容。代码示例如下:
@Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode) { case FILE_CHOOSER_REQUEST_CODE: if (data != null) { String targetDirPath = FileUtil.getFullPathFromTreeUri(data.getData(), getActivity()); // 在选中目录下创建要写入的目标文件,比如test.txt File targetFile = new File(targetDirPath, "test.txt"); try (FileOutputStream fos = new FileOutputStream(targetFile)) { // 写入自定义内容 String content = "这是要写入文件的内容"; fos.write(content.getBytes(StandardCharsets.UTF_8)); Toast.makeText(getActivity(), "文件写入成功", Toast.LENGTH_SHORT).show(); } catch (IOException e) { e.printStackTrace(); Toast.makeText(getActivity(), "写入失败,请检查权限", Toast.LENGTH_SHORT).show(); } dismiss(); } break; } }
注意事项
这种方法在Android 10(API 29)及以上版本可能失效,因为分区存储政策限制了直接访问外部存储的文件路径。如果你的APP需要适配Android 10,可以在AndroidManifest.xml的<application>标签里添加android:requestLegacyExternalStorage="true"作为过渡方案,但Android 11及以上这个属性就不再起作用了,所以更推荐下面的官方合规方法。
方法二:直接用Tree URI操作(官方推荐,适配全版本)
其实不用转成路径也能操作,这是Android官方推荐的方式——ACTION_OPEN_DOCUMENT_TREE已经授予了你该目录的读写权限,用DocumentFile配合ContentResolver操作更安全,还能持久化权限,下次打开APP不用再让用户重复选择目录。代码示例:
@Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode) { case FILE_CHOOSER_REQUEST_CODE: if (data != null && data.getData() != null) { Uri treeUri = data.getData(); // 可选:持久化权限,下次打开APP仍能访问该目录 getActivity().getContentResolver().takePersistableUriPermission( treeUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION ); // 获取选中目录的DocumentFile对象 DocumentFile selectedDir = DocumentFile.fromTreeUri(getActivity(), treeUri); if (selectedDir != null && selectedDir.isDirectory()) { // 在目录下创建新文件,第一个参数是MIME类型,第二个是文件名 DocumentFile newFile = selectedDir.createFile("text/plain", "test.txt"); if (newFile != null) { // 打开输出流写入内容 try (OutputStream outputStream = getActivity().getContentResolver().openOutputStream(newFile.getUri())) { String content = "这是通过DocumentFile写入的内容"; outputStream.write(content.getBytes(StandardCharsets.UTF_8)); Toast.makeText(getActivity(), "文件写入成功", Toast.LENGTH_SHORT).show(); } catch (IOException e) { e.printStackTrace(); Toast.makeText(getActivity(), "写入失败", Toast.LENGTH_SHORT).show(); } } } dismiss(); } break; } }
为什么推荐这个方法?
- 完全适配Android 10+的分区存储政策,不会出现权限异常
- 可以通过
takePersistableUriPermission持久化权限,提升用户体验 - 不需要依赖第三方工具类转换路径,减少潜在的兼容性问题
内容的提问来源于stack exchange,提问作者Morgan
相关产品推荐
相关产品推荐

