如何借助Uri权限在Android/data目录下正确写入文件?
解决Android/data目录通过SAF授权后File无法写入的问题
问题原因
从你的输出能看到,df.getUri().getPath()返回的是/tree/primary:Android/data/document/primary:Android/data,这压根不是真实的文件系统路径,只是SAF提供的虚拟路径。Android 10及以上版本,直接用File对象访问通过SAF授权的目录完全无效——系统限制了File API对这类授权目录的直接操作,必须用SAF相关的API(DocumentFile、ContentResolver)来完成读写。
解决方案
要在授权的Android/data目录下写入文件,得靠DocumentFile创建子文件,再用ContentResolver写入内容,具体步骤如下:
创建目标文件的DocumentFile对象
通过已授权的目录DocumentFile,调用createFile()方法生成要写入的文件:// 已授权的Android/data目录的DocumentFile实例 DocumentFile androidDataDir = DocumentFile.fromSingleUri(activity.getApplicationContext(), uriPath); // 创建目标zip文件,第一个参数是MIME类型,第二个是文件名 DocumentFile targetFile = androidDataDir.createFile("application/zip", product + ".zip");通过ContentResolver写入文件内容
用ContentResolver.openOutputStream()拿到输出流,直接写入数据:if (targetFile != null) { try (OutputStream outputStream = activity.getContentResolver().openOutputStream(targetFile.getUri())) { // 这里替换成你的文件写入逻辑,比如从下载的输入流复制数据 byte[] buffer = new byte[4096]; int bytesRead; // 假设inputStream是你下载的数据源 while ((bytesRead = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); } } catch (IOException e) { e.printStackTrace(); } }
额外提示
- 要确保你拿到的SAF授权是目录权限(通过
ACTION_OPEN_DOCUMENT_TREE请求的),而不是单个文件权限,这样才能在目录下创建子文件。 - 如果需要覆盖已存在的文件,先判断文件是否存在,存在就删掉再创建:
DocumentFile existingFile = androidDataDir.findFile(product + ".zip"); if (existingFile != null) { existingFile.delete(); } DocumentFile targetFile = androidDataDir.createFile("application/zip", product + ".zip");
内容的提问来源于stack exchange,提问作者Warley Soares
相关产品推荐
相关产品推荐

