Android 7.0写入SD卡报错:FileNotFoundException问题咨询
排查Android 7.0写入SD卡时FileNotFoundException的原因和解决方案
让我来帮你定位这个文件找不到的问题,先从几个核心问题入手分析:
一、导致异常的关键原因
- 路径完全错误:你代码里的目标路径
/data/Cindy/KWMusic是系统应用的私有存储目录,普通第三方APP没有读写权限,而且这和你要写入SD卡的需求完全不匹配——SD卡的存储路径应该是外部存储目录,比如/storage/emulated/0/或者SD卡挂载的外部路径。 - 单级目录创建失败:你用了
dir.mkdir()来创建目录,这个方法只能创建单级目录。如果父目录(比如/data/Cindy)不存在,mkdir()会直接返回false,导致目录创建失败,后续创建文件自然会报“找不到目录”的错误。 - 权限逻辑可能存在遗漏:虽然你做了动态权限回调,但要确保:
- 清单文件
AndroidManifest.xml里已经声明了WRITE_EXTERNAL_STORAGE权限; - 权限回调里的逻辑是否真的在权限授予后正确执行了目录和文件创建。
- 清单文件
二、具体解决方案
1. 修正存储路径
把错误的/data/Cindy路径替换为SD卡的合法路径,分两种场景:
- 公共存储目录(比如音乐目录):适合需要让其他APP访问的文件,代码示例:
// 获取SD卡公共音乐目录 String DOWNLOAD_PATH = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC).getAbsolutePath() + "/Cindy"; - APP私有外部存储目录:适合仅当前APP访问的文件,Android 4.4+无需动态申请
WRITE_EXTERNAL_STORAGE权限,代码示例:// 获取APP私有外部存储的音乐目录 String DOWNLOAD_PATH = getExternalFilesDir(Environment.DIRECTORY_MUSIC).getAbsolutePath() + "/Cindy";
2. 替换mkdir()为mkdirs()
用mkdirs()替代mkdir(),它能自动创建所有不存在的父级目录:
File dir = new File(DOWNLOAD_PATH); if (!dir.exists()) { // 改用mkdirs()创建多级目录 boolean isCreated = dir.mkdirs(); Log.i("test", "Directory create result: " + isCreated + ", path: " + dir.getAbsolutePath()); }
3. 完善权限相关检查
- 确保
AndroidManifest.xml中添加权限声明:<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- 如果是Android 10+,还可以添加这个限制避免不必要的权限申请 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29" /> - 在权限回调中,建议增加权限拒绝后的处理逻辑,避免后续代码执行出错:
@Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { switch (requestCode) { case 1: { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // 获取到权限,执行文件创建逻辑 createFile(); } else { // 用户拒绝了权限,给出提示 Toast.makeText(this, "需要存储权限才能下载音乐", Toast.LENGTH_SHORT).show(); } return; } } } // 把文件创建逻辑抽成单独方法,便于复用 private void createFile() { String DOWNLOAD_PATH = getExternalFilesDir(Environment.DIRECTORY_MUSIC).getAbsolutePath() + "/Cindy"; File dir = new File(DOWNLOAD_PATH); if (!dir.exists()) { boolean isCreated = dir.mkdirs(); Log.i("test", "Directory create result: " + isCreated + ", path: " + dir.getAbsolutePath()); } File file = new File(dir, "KWMusic"); Log.i("test file", "Full file path: " + file.getAbsolutePath()); // 后续写入文件的逻辑 }
4. 调试时打印完整路径
不要只打印文件名,要打印文件的完整绝对路径,比如用file.getAbsolutePath(),这样能直观看到实际要操作的路径是否正确,方便排查问题。
内容的提问来源于stack exchange,提问作者CindyYu
相关产品推荐
相关产品推荐

