Android读取外部存储纯文本文件出现EACCES权限异常崩溃问题
根因说明
- Android 10及以上版本启用了分区存储权限机制,即使申请了
READ_EXTERNAL_STORAGE权限,也不允许应用直接通过绝对路径访问公共存储目录(比如Download、DCIM等)下的文件,这是你报EACCES权限拒绝的核心原因。 - 你通过
ACTION_OPEN_DOCUMENT唤起系统文件选择器选中文件后,得到的是content://类型的Uri,你截取Uri中的路径转成本地File对象访问的逻辑本身就是错误用法:系统通过Uri给你授予的是对应文件的临时访问权限,必须通过ContentResolver操作Uri来读写内容,不需要额外申请存储权限。
修复方案
推荐使用系统授权的Uri访问方案,不需要申请任何存储权限,兼容所有Android版本:
- 可以移除
AndroidManifest.xml中的READ_EXTERNAL_STORAGE权限声明,以及MainActivity中所有和权限校验、请求相关的代码。 - 修改
onActivityResult中的文件读取逻辑,直接通过ContentResolver读取Uri的输入流:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (requestCode == OPEN_DOCUMENT_REQUEST_CODE) { if (resultCode == Activity.RESULT_OK) { data?.data?.also { documentUri -> Log.v(TAG, "Document URI is $documentUri") // 直接通过ContentResolver打开Uri输入流读取内容 contentResolver.openInputStream(documentUri)?.use { inputStream -> val readContent = inputStream.bufferedReader().use { it.readText() } Log.v(TAG, "Read content: $readContent") outputText.text = readContent } } } else { Log.v(TAG, "onActivityResult resultCode is not OK=$resultCode") } } else { Log.v(TAG, "onActivityResult unknown requestCode=$requestCode") } }
临时兼容方案(仅支持Android 10,不推荐)
如果你一定要用绝对路径访问文件,可以在AndroidManifest.xml的application标签中添加android:requestLegacyExternalStorage="true"属性,关闭分区存储的限制,这个配置在Android 11及以上版本会失效,不建议长期使用。
内容的提问来源于stack exchange,提问作者ArthurTheLearner
相关产品推荐
相关产品推荐

