本文覆盖的问题场景:
- uniapp的文件IO接口报“targetSdkVersion设置>=29后在Android10+系统设备不支持当前路径。请更改为应用运行路径!具体请看…”错误
- uni.uploadFile接口上传图片视频正常,上传pdf,doc等非媒体文件报400,但无明确错误原因。
- Android 10及以上,使用uni或plus读取公共目录文件报错。(或Android 11及以上正常,Android 10报错)
关于外部存储读写
我们知道Android开发中关于存储主要分两大部分:内部存储和外部存储。
内部存储是给每个应用自动授权的一个仅供此应用自身读写的目录,无需申请。
外部存储则包括了:
本应用外部存储目录、其他应用外部存储目录、公共目录媒体文件、公共目录非媒体文件四类。
在最初的Android开发中,应用可以随意读取上面的四类文件。
从Android 4.4(API 19)开始,默认授予
本应用外部存储目录访问
权限,无需申请;但如果需要访问
公共目录的媒体文件或非媒体文件
,必须申请外部存储的读取权限。(
其他应用外部存储目录
是申请任何权限也无法访问的)
出于安全考虑,从Android 10开始,对外部存储的读取权限进行了限制,默认只能访问:
公共目录媒体文件
。
但为了方便过度,在Android 10和Android 11下,如果应用在AndroidManifest.xml注册了
android:requestLegacyExternalStorage="true"
的话,应用可以暂时停用分区存储,继续上面除了其他应用外部存储目录外的其他三类文件。(如果目标版本是Android 11+,则在Android 11+上这个属性不生效。)
从Android 11开始,新增了【管理所有文件】(也叫:所有文件访问权限)权限,如果应用申请了这个权限,可以访问
本应用外部存储目录、公共目录媒体文件、公共目录非媒体文件
三类文件。多了一个公共目录非媒体文件的访问。
但这个权限授予条件比较苛刻,建议如果选择单个文件的话,尽量使用
存储访问框架
Uniapp中对外部存储的访问
主要可以参考
适配Android10+设备注意事项
。
uniapp中访问文件相关的包括
plus.io
和
uni.getFileInfo
、
uni.uploadFile
等一些API。
uniapp为了适配Android 10+,针对外部存储的访问,默认也是只能访问
本应用外部存储目录、公共目录媒体文件
。
针对Android 11+,如果应用有管理所有文件权限的话,也可以访问
公共目录非媒体文件
,就是有三类权限。
但uniapp没有兼容
android:requestLegacyExternalStorage
,所以即使添加了这个标签,在Android 10上面,uniapp的文件API依然无法访问公共目录非媒体权限。
针对公共目录非媒体文件的访问:
版本 | 管理所有文件 | 原生APP开发 | uniapp开发 |
---|---|---|---|
Android 10 | 无 | 可读 | 不可读 |
Android 11 | 可申请 | 可读 | 申请后可读 |
Android 12 | 可申请 | 申请后可读 | 申请后可读 |
公共目录非媒体文件访问实践
针对Android 11及以上的设备,有两种方法:
- 申请管理所有文件权限,原生开发和uniapp都可以访问
- 通过存储访问框架选择文件,未测试
针对Android 10,也有两种方法:
-
添加
android:requestLegacyExternalStorage
,原生开发可访问,uniapp开发依然不可访问。(可将对文件的操作读取上传等转移到原生逻辑实现,或者可通过原生插件将文件复制到本应用外部存储私有目录下,uniapp即可访问文件副本) - 通过存储访问框架选择文件,未测试
注意
上面总结的内容可能部分有误,如果发现请评论告知更新~