当我们App的targetSdkVersion
更改为28以上,并且运行在Android 10以上设备时,我们无法再以绝对路径的方式,去读写非沙盒目录下的文件,当然,如果App是覆盖安装(如:targetSdkVersion 28 覆盖安装为 29),则会保持原来的访问方式。
requestLegacyExternalStorage属性
如果我们的app将targetSdkVersion更改为28以上,且想保持原来的访问方式,则需要在清单文件中将 requestLegacyExternalStorage
的值设置为 true
,如下:
<manifest …>
<application android:requestLegacyExternalStorage=“true” … >
…
此时,便可继续以原来的方式去读写文件,然而,在Android 11上,Google又给了它新的含义,来看看官网的原话
也就是说,在Android 11设备上,targetSdkVersion
为29以上的app,将强制开启分区存储,requestLegacyExternalStorage
属性失效
注意,只要同时满足以上两个条件,不管是覆盖安装还是requestLegacyExternalStorage = true
,都会强制开启分区存储
分区存储优势
- 对用户来说,解决了文件乱放的现象
- 对于开发者来说,我们无需写权限,就可以在分区目录下创建文件,并且访问自己创建的文件,不需要读权限(访问其它应用创建的文件,还是需要读权限)
新的文件访问方式
此图来源于作者[连续三届村草]分享的Android 10(Q)/11® 分区存储适配一文,感谢作者的总结
3、上传
3.1、简单上传
在介绍Android 10文件上传前,我们先来看看Android 10之前是如何上传文件的,如下:
//kotlin 协程
val result = RxHttp.postForm("/service/…")
.add(“key”, “value”)
.addFile(“file”, new File(“xxx/1.jpg”))
.awaitString() //awaitXxx系列方法是挂断方法
//RxJava
RxHttp.postForm("/service/…")
.add(“key”, “value”)
.addFile(“file”, new File(“xxx/1.jpg”))
.asString()
.subscribe({
//成功回调
}, {
//异常回调
})
以上,我们仅需调用 addFile
方法添加文件对象即可,RxHttp提供了一系列addFile
方法,列出几个常用的,如下:
//添加单个文件
addFile(String, File)
//添加多个文件,每个文件对应相同的key
addFile(String, List<? extends File> fileList)
//添加多个文件,每个文件对应不同的key
addFile(Map<String, ? extends File> fileMap)
//等等其它addFile方法
在Android 10,我们需要通过Uri对象去上传文件,在RxHttp中,通过addPart
方法添加Uri
对象,如下:
val context = getContext(); //获取上下文对象
//获取Uri对象,这里为了方便,随便写了一个Downlaod目录下的Uri地址
val uri = Uri.parse(“content://media/external/downloads/13417”)