Android物理SD卡写入问题求助:代码写入内置存储而非SD卡
解决Android写入物理SD卡的问题
嘿,我懂你现在的困扰——明明想把文件写到物理SD卡上,结果用Environment.getExternalStorageDirectory()拿到的却是内置存储,属实是Android存储命名的坑搞的鬼!先给你理清楚问题根源,再给你分版本的解决方案。
为什么当前代码不行?
Android里的getExternalStorageDirectory()这个方法的“external”是个历史遗留的命名误区:它指的是对外可访问的存储区域(比如手机厂商划分的、可以通过USB传输文件的内置分区),而非字面意义上的“可移除SD卡”。你看到isExternalStorageRemovable()返回false,就正好验证了这一点——当前拿到的是内置的“外部存储”。
分版本解决方案
Android不同版本的存储权限机制差异很大,得针对性处理:
Android 10及以上(API 29+):用存储访问框架(SAF)
从Android 10开始引入了Scoped Storage,禁止APP直接访问SD卡的任意路径,必须通过**存储访问框架(SAF)**让用户手动选择要操作的SD卡目录,才能进行读写。
- 发起请求让用户选择SD卡目录:
private static final int REQUEST_CODE_PICK_DIR = 1001; // 触发目录选择 Intent pickDirIntent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); startActivityForResult(pickDirIntent, REQUEST_CODE_PICK_DIR);
- 处理用户选择后的回调,写入文件:
@Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_CODE_PICK_DIR && resultCode == RESULT_OK && data != null) { Uri selectedDirUri = data.getData(); // 持久化权限,避免下次打开APP还要重新选择 getContentResolver().takePersistableUriPermission(selectedDirUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); // 创建要写入的文件 DocumentFile targetDir = DocumentFile.fromTreeUri(this, selectedDirUri); DocumentFile newFile = targetDir.createFile("text/plain", "my_sd_file.txt"); // 写入内容 try (OutputStream outputStream = getContentResolver().openOutputStream(newFile.getUri())) { outputStream.write("终于写到物理SD卡啦!".getBytes()); } catch (IOException e) { e.printStackTrace(); } } }
Android 9及以下(API 28及以下):直接获取SD卡路径
这个版本还允许直接访问SD卡的APP专属目录,你可以通过Context.getExternalFilesDirs()方法获取所有外部存储目录:
// 获取所有外部存储目录,数组第一个是内置外部存储,第二个是物理SD卡(如果存在) File[] externalStorageDirs = getExternalFilesDirs(null); if (externalStorageDirs.length > 1 && externalStorageDirs[1] != null) { File sdCardAppDir = externalStorageDirs[1]; // 创建要写入的文件 File targetFile = new File(sdCardAppDir, "my_sd_file.txt"); // 写入内容 try (FileWriter writer = new FileWriter(targetFile)) { writer.write("成功写入物理SD卡的APP专属目录!"); } catch (IOException e) { e.printStackTrace(); } }
注意:这个版本需要在Manifest中添加权限,并且针对API 23+要动态申请权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
额外提醒
- 如果想访问SD卡上的非APP专属目录(比如SD卡根目录的自定义文件夹),Android 10之前需要
WRITE_EXTERNAL_STORAGE权限;Android 10及以上只能通过SAF让用户手动选择,没办法直接硬编码路径访问。 - 尽量优先使用APP专属目录,这样不需要额外的权限申请(Android 10+甚至不需要
WRITE_EXTERNAL_STORAGE),也不会因为Scoped Storage的限制出问题。
内容的提问来源于stack exchange,提问作者AndyAndroid
相关产品推荐
相关产品推荐

