为何用推荐的getExternalStorageState()替换已废弃的getExternalStorageDirectory()会返回错误路径
问题根源
你完全搞错了两个API的功能和对应关系:
getExternalStorageDirectory()是用于返回外部存储根路径的API,因分区存储规则推行被标记废弃getExternalStorageState()是用于查询外部存储挂载状态的API,返回值如mounted仅代表存储正常可读写,和路径完全无关,根本不是getExternalStorageDirectory()的官方替代方案,你是误用API才导致路径异常崩溃。
另外你之前使用的RealPathUtil本质是通过各种兼容逻辑把Uri转换为原始绝对路径,在Android 10及以上的分区存储规则下,普通应用默认没有公共存储的原始路径访问权限,就算拿到路径也无法直接读写,这类工具早晚会完全失效,不建议长期依赖。
正确适配方案
根据你的文件使用场景选择对应方案即可:
场景1:文件仅为你的应用自用,不需要对外暴露
直接使用Context提供的私有外部存储API,不需要申请任何存储权限,应用可直接读写:
// 获取应用私有下载目录,路径格式为 /storage/emulated/0/Android/data/你的应用包名/files/Download File privateDownloadDir = context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS); File targetFile = new File(privateDownloadDir, fileName); // 直接对targetFile做输入输出流操作即可 FileInputStream fis = new FileInputStream(targetFile);
场景2:文件需要保存到公共下载目录,可被其他应用访问
Android 10及以上版本使用MediaStore操作,不需要申请存储权限:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { ContentValues values = new ContentValues(); values.put(MediaStore.Downloads.DISPLAY_NAME, fileName); values.put(MediaStore.Downloads.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS); // 插入文件拿到对应Uri Uri fileUri = getContentResolver().insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, values); // 写入文件直接开输出流 OutputStream os = getContentResolver().openOutputStream(fileUri); // 读取已有文件可通过MediaStore查询拿到Uri后开输入流 FileInputStream fis = (FileInputStream) getContentResolver().openInputStream(fileUri); } else { // 低于Android 10版本可继续使用原有逻辑,申请WRITE_EXTERNAL_STORAGE权限即可 File publicDownloadDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS); File targetFile = new File(publicDownloadDir, fileName); FileInputStream fis = new FileInputStream(targetFile); }
场景3:需要读取用户自选的任意公共文件
使用系统存储访问框架(SAF)拉起文件选择器,由用户主动选择文件后获取Uri操作即可,不需要申请存储权限。
内容的提问来源于stack exchange,提问作者svstackoverflow
相关产品推荐
相关产品推荐

