Android使用Intent操作文件后无法写入数据问题
问题原因
你的代码核心问题在于:通过Intent.ACTION_CREATE_DOCUMENT或ACTION_OPEN_DOCUMENT获取的是文件的Content URI,但你的writeToFile方法却直接用文件名在Environment.DIRECTORY_DOCUMENTS目录下创建/查找文件——这和用户实际选择的文件根本不是同一个(比如用户可能在Downloads目录创建文件,你却去Documents目录找同名文件),自然无法写入数据。
另外,Android 10及以上的Scoped Storage限制了直接访问文件路径,必须通过ContentResolver操作Content URI来读写文件。
修复方案
1. 保留Uri引用,不要只存文件名
把currentProject的作用改为记录文件名(仅用于显示),实际读写依赖uriFile变量,因为Uri是唯一指向文件的标识。
2. 重写writeToFile方法,通过ContentResolver写入
替换原来的writeToFile方法,用ContentResolver打开输出流来写入数据:
private void writeToFile(String data, Context context) { if (uriFile == null) { // 如果没有选中文件,使用默认文件逻辑 File dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS); File file = new File(dir, "amirLight.txt"); try (FileWriter fileWriter = new FileWriter(file, true)) { fileWriter.append(data); fileWriter.write(System.lineSeparator()); } catch (IOException e) { Log.e("FileWrite", "默认文件写入失败", e); } return; } // 通过Content URI写入文件 try (OutputStreamWriter writer = new OutputStreamWriter( context.getContentResolver().openOutputStream(uriFile, "wa"))) { writer.append(data); writer.write(System.lineSeparator()); Log.e("FileWrite", "数据写入成功"); } catch (IOException e) { Log.e("FileWrite", "写入失败", e); Toast.makeText(context, "文件写入失败", Toast.LENGTH_SHORT).show(); } }
3. 获取持久化文件访问权限(可选但推荐)
当用户通过ACTION_OPEN_DOCUMENT打开文件后,获取持久化权限,这样App重启后仍能访问该文件:
在onActivityResult的requestCode==3分支里添加:
// 获取持久化权限 final int takeFlags = data.getFlags() & (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); getContentResolver().takePersistableUriPermission(uriFile, takeFlags);
4. 调用修改后的writeToFile方法
在getLocation方法里,把调用改为:
writeToFile("Lux "+currentLux+" Y "+wayLatitude+" X "+wayLongitude, getApplicationContext());
5. 处理默认文件的情况
如果用户没有选择任何文件,仍使用原来的默认文件逻辑,这样兼容原来的功能。
关键说明
openOutputStream的第二个参数"wa"表示追加写入,和原来的FileWriter(file, true)效果一致。- Content URI是Android系统文件访问的标准方式,尤其是Scoped Storage下,必须用这种方式操作非App私有目录的文件。
- 持久化权限确保App重启后不需要重新选择文件,提升用户体验。
内容的提问来源于stack exchange,提问作者Amir
相关产品推荐
相关产品推荐

