Android Storage Access Framework如何直接创建并写入文件数据?
核心原因
ACTION_CREATE_DOCUMENT的默认行为就是创建空文件,它本身不负责写入数据,你之前的代码只完成了「唤起系统选择器让用户选定保存路径、确认文件名」的步骤,缺失了拿到返回结果后写入实际数据的逻辑,所以最终只有空白文件。
不需要额外走ACTION_OPEN_DOCUMENT让用户二次选择文件,用户在创建流程确认后,系统会直接返回该空文件的可读写Uri,直接基于这个Uri写入数据即可完成全流程。
完整实现步骤
1. 发起文件创建请求
你原有创建Intent的代码缺少CATEGORY_OPENABLE分类,加上后可以保证系统返回的Uri是可读写的:
private static final int REQUEST_CODE_CREATE_FILE = 1001; private void startCreateFile() { Intent createIntent = new Intent(Intent.ACTION_CREATE_DOCUMENT); createIntent.addCategory(Intent.CATEGORY_OPENABLE); createIntent.setType("application/vnd.ms-excel"); createIntent.putExtra(Intent.EXTRA_TITLE, DATABASE_NAME + "_" + AppUtils.getCurrentDate() + ".xls"); startActivityForResult(createIntent, REQUEST_CODE_CREATE_FILE); }
2. 在回调中拿到Uri完成数据写入
用户确认创建后,会在onActivityResult中返回对应文件的Uri,直接通过ContentResolver打开输出流写入你的Excel数据即可:
@Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_CODE_CREATE_FILE && resultCode == RESULT_OK) { if (data == null || data.getData() == null) { Toast.makeText(this, "创建文件失败", Toast.LENGTH_SHORT).show(); return; } Uri targetUri = data.getData(); // 执行写入操作,注意大文件请放到子线程执行,避免主线程阻塞ANR try (OutputStream os = getContentResolver().openOutputStream(targetUri)) { // 替换为你实际的Excel写入逻辑,例:如果用POI则执行 workbook.write(os) byte[] fileContent = "测试写入内容".getBytes(StandardCharsets.UTF_8); os.write(fileContent); os.flush(); Toast.makeText(this, "文件保存成功", Toast.LENGTH_SHORT).show(); } catch (IOException e) { e.printStackTrace(); Toast.makeText(this, "写入失败:" + e.getMessage(), Toast.LENGTH_SHORT).show(); } } }
注意事项
- 流读写属于IO耗时操作,不要在主线程执行,建议配合协程、RxJava放到子线程处理
- 如果需要长期访问该创建好的文件,可以在拿到Uri后调用
getContentResolver().takePersistableUriPermission()持久化Uri权限,避免应用重启后权限失效 - 新项目建议使用
Activity Result API替代已经废弃的startActivityForResult,代码生命周期安全度更高 - 如果写入的是xls格式文件,使用POI等第三方库写入时,注意要把Workbook直接写入到获取到的OutputStream中,不要先写到本地私有目录再拷贝,减少不必要的IO开销
内容的提问来源于stack exchange,提问作者MD Tayobur Rahman
相关产品推荐
相关产品推荐

