You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android申请SD卡读取权限被拒后仍能读取文件的问题咨询

问题根源:存储访问框架(SAF) vs 传统外部存储权限

哦,这个问题其实是因为你搞混了Android两种完全不同的文件访问权限逻辑,我来给你掰扯清楚:

  • 存储访问框架的独立权限体系
    你用的Intent.ACTION_OPEN_DOCUMENT属于Android的存储访问框架(SAF),这是API 19(Android 4.4)之后引入的机制,它的权限逻辑和READ_EXTERNAL_STORAGE完全脱节:

    • 当用户通过系统文件选择器手动选中某个文件时,系统会自动给你的应用授予该特定文件的临时精细化权限——这个权限是绑定在返回的Uri上的,不需要依赖READ_EXTERNAL_STORAGE这种宽泛的全外部存储权限。
    • 你代码里的getContentResolver().openInputStream(uri)就是通过SAF的Uri权限来读取文件的,和你是否申请/授予READ_EXTERNAL_STORAGE没有任何关系。
  • 传统外部存储权限的作用场景
    READ_EXTERNAL_STORAGE权限是用来让应用直接访问整个外部存储目录下的任意文件(比如/sdcard/根目录下的所有文件),不需要用户手动选择。但SAF的设计初衷就是为了替代这种“一刀切”的权限,让用户能精准控制应用能访问哪些文件——所以用SAF的时候,这个权限根本派不上用场。

  • 为什么拒绝权限后仍能读取文件
    你代码里虽然做了权限检查,但不管权限结果如何都调用了startActivityForResult启动文件选择器,而SAF本身不需要READ_EXTERNAL_STORAGE权限。只要用户在文件选择器里选了文件,系统就会给你该文件的访问权限,自然就能读取成功。

  • 关于MIUI的影响
    其实这个现象和MIUI关系不大,这是Android系统的标准行为。MIUI可能在权限提示的UI上有自己的定制,但核心的权限逻辑还是遵循Android官方规范的。

给你的建议
  1. 如果仅用SAF获取文件:可以直接移除清单文件里的READ_EXTERNAL_STORAGE权限,因为你完全不需要它。SAF已经通过用户的手动选择完成了授权。
  2. 如果需要同时访问其他外部存储文件:比如你既要用SAF让用户选文件,又要直接读取外部存储里的其他文件(比如下载目录下的所有文件),那才需要申请READ_EXTERNAL_STORAGE权限,并且在权限授予后再执行对应的读取操作。
  3. 权限检查的正确姿势:针对不同的文件访问方式做不同处理:
    • 用SAF(ACTION_OPEN_DOCUMENT/ACTION_GET_CONTENT):不需要检查READ_EXTERNAL_STORAGE,直接启动文件选择器即可。
    • 直接访问外部存储文件:检查并申请READ_EXTERNAL_STORAGE权限,权限通过后再执行读取操作。

举个例子,你代码里的这段SAF调用是完全合规的:

Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("text/*");
startActivityForResult(intent, READ_REQ);

onActivityResult里通过getContentResolver().openInputStream(uri)读取文件,也是SAF授权后的合法操作,和READ_EXTERNAL_STORAGE权限无关。

内容的提问来源于stack exchange,提问作者SimpleOne

火山引擎 最新活动