记一次bug改正——open failed: EACCES (Permission denied)

问题

在做项目的时候,部分功能需要访问本地相册进行上传图片(将图片转化为Base64上传),测试机型为Android 11,当时没有考虑到Android版本对本地相册等系统共享文件的管理不同,直接采用了 指定File(绝对路径) 的方式对图片文件直接读取,没有出现问题,但是在Android Q版本下出现报错----open failed: EACCES (Permission denied)。

问题原因

Android Q版本之后,文件存储机制修改成了沙盒模式,APP只能访问自己目录下的文件和公共媒体文件。对于AndroidQ以下,还是使用老的文件存储方式。

Android Q版本之后仍然使用READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE作为存储相关运行时权限,但现在即使获取了这些权限,访问外部存储也受到了限制。

这里我们就要思考为什么Android Q中报错,而更高版本的Android 11确不会呢?

翻寻了Android 11的系统变更之后发现,原来在Android 11版本下虽然文件存储机制也是沙盒模式,但是允许使用除 MediaStore API 之外的 API 通过文件路径直接访问共享存储空间中的媒体文件,其中包括:

  • File API。
  • 原生库,例如 fopen()。

问题解决

  1. 如果你适配的机型只截止到Android Q(显然不太可能),可以打开AndroidManifest.xml文件
    找到<application 标签 在此标签中加一行代码就可以了。
  android:requestLegacyExternalStorage="true"

此行代码意思为:
使用旧的存储策略,不使用Android Q的新策略。但这个不是长久之计,很快将会强制都使用新策略。

在Android 11 中如果应用targetSdkVersion >= 30,强制执行分区存储机制。之前在AndroidManifest.xml中添加 android:requestLegacyExternalStorage="true"的适配方式就不起作用。

  1. 官方强烈建议直接使用 MediaStore API。
    不是说File API等一些API在之后是可以继续使用访问的吗?不过,使用原始文件路径直接访问共享存储空间中的媒体文件会重定向到 MediaStore API,这次重定向会造成性能影响(随机读写慢一倍左右)。而且直接使用原始文件路径,并不会比使用 MediaStore API 有更多优势,因此官方强烈建议直接使用 MediaStore API(详细使用就不讲了)。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值