RxHttp 完美適配Android 10/11 上傳/下載/進度監聽
阿新 • • 發佈:2020-12-27
# 1、前言
隨著Android 11的正式釋出,適配Android 10/11 分割槽儲存就更加的迫切了,因為Android 11開始,將強制開啟分割槽儲存,我們就無法再以絕對路徑的方式去讀寫非沙盒目錄下的檔案,為此,[RxHttp ](https://github.com/liujingxing/okhttp-RxHttp)在`2.4.0`版本中就正式適配了分割槽儲存,並且,可以非常優雅的實現檔案上傳/下載/進度監聽,三步即可搞懂任意請求。
老規矩,先看看請求三部曲
![](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/cd222bde222e4f7d88e3f69e6eabd0be~tplv-k3u1fbpfcp-watermark.image)
如果你想了解RxHttp更過功能,請檢視以下系列文章
[RxHttp 2000+star,協程請求,僅需三步](https://juejin.im/post/6856550856796897287)
[RxHttp 讓你眼前一亮的Http請求框架](https://juejin.im/post/6844904016380428302)
***gradle依賴***
## 必須
```java
//使用kapt依賴rxhttp-compiler時必須
apply plugin: 'kotlin-kapt'
android {
//必須,java 8或更高
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation 'com.ljx.rxhttp:rxhttp:2.5.2'
implementation 'com.squareup.okhttp3:okhttp:4.9.0' //rxhttp v2.2.2版本起,需要手動依賴okhttp
kapt 'com.ljx.rxhttp:rxhttp-compiler:2.5.2' //生成RxHttp類,純Java專案,請使用annotationProcessor代替kapt
}
```
## 可選
```java
android {
defaultConfig {
javaCompileOptions {
annotationProcessorOptions {
arguments = [
//使用asXxx方法時必須,告知RxHttp你依賴的rxjava版本,可傳入rxjava2、rxjava3
rxhttp_rxjava: 'rxjava3',
rxhttp_package: 'rxhttp' //非必須,指定RxHttp類包名
]
}
}
}
}
dependencies {
implementation 'com.ljx.rxlife:rxlife-coroutine:2.0.1' //管理協程生命週期,頁面銷燬,關閉請求
//rxjava2 (RxJava2/Rxjava3二選一,使用asXxx方法時必須)
implementation 'io.reactivex.rxjava2:rxjava:2.2.8'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
implementation 'com.ljx.rxlife2:rxlife-rxjava:2.0.0' //管理RxJava2生命週期,頁面銷燬,關閉請求
//rxjava3
implementation 'io.reactivex.rxjava3:rxjava:3.0.6'
implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
implementation 'com.ljx.rxlife3:rxlife-rxjava:3.0.0' //管理RxJava3生命週期,頁面銷燬,關閉請求
//非必須,根據自己需求選擇 RxHttp預設內建了GsonConverter
implementation 'com.ljx.rxhttp:converter-fastjson:2.5.2'
implementation 'com.ljx.rxhttp:converter-jackson:2.5.2'
implementation 'com.ljx.rxhttp:converter-moshi:2.5.2'
implementation 'com.ljx.rxhttp:converter-protobuf:2.5.2'
implementation 'com.ljx.rxhttp:converter-simplexml:2.5.2'
}
```
# 2、Android 10/11 分割槽儲存
當我們App的`targetSdkVersion`更改為28以上,並且執行在Android 10以上裝置時,我們無法再以絕對路徑的方式,去讀寫非沙盒目錄下的檔案,當然,如果App是覆蓋安裝(如:targetSdkVersion 28 覆蓋安裝為 29),則會保持原來的訪問方式。
***requestLegacyExternalStorage屬性***
如果我們的app將targetSdkVersion更改為28以上,且想保持原來的訪問方式,則需要在清單檔案中將 `requestLegacyExternalStorage` 的值設定為 `true`,如下:
```xml
```
此時,便可繼續以原來的方式去讀寫檔案,然而,在Android 11上,Google又給了它新的含義,來看看[官網的原話](https://developer.android.google.cn/training/data-storage/use-cases#opt-out-scoped-storage)
![](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/eea88335b9424484a4e85fa8bf1cb4dc~tplv-k3u1fbpfcp-watermark.image)
也就是說,在Android 11裝置上,`targetSdkVersion`為29以上的app,將強制開啟分割槽儲存,`requestLegacyExternalStorage`屬性失效
***注意,只要同時滿足以上兩個條件,不管是覆蓋安裝還是`requestLegacyExternalStorage = true`,都會強制開啟分割槽儲存***
***分割槽儲存優勢***
- 對使用者來說,解決了檔案亂放的現象
- 對於開發者來說,我們無需寫許可權,就可以在分割槽目錄下建立檔案,並且訪問自己建立的檔案,不需要讀許可權(訪問其它應用建立的檔案,還是需要讀許可權)
***新的檔案訪問方式***
![](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f54452cb69f9425eb2b77dea7041efa6~tplv-k3u1fbpfcp-watermark.image)
此圖來源於作者[連續三屆村草]分享的[Android 10(Q)/11(R) 分割槽儲存適配](https://juejin.im/post/6862633674089693197#heading-2)一文,感謝作者的總結
# 3、上傳
## 3.1、簡單上傳
在介紹Android 10檔案上傳前,我們先來看看Android 10之前是如何上傳檔案的,如下:
```java
//kotlin 協程
val result = RxHttp.postForm("/service/...")
.add("key", "value")
.addFile("file", File("xxx/1.jpg"))
.awaitString() //awaitXxx系列方法是結束通話方法
//RxJava
RxHttp.postForm("/service/...")
.add("key", "value")
.addFile("file", File("xxx/1.jpg"))
.asString()
.subscribe({
//成功回撥
}, {
//異常回調
})
```
以上,我們僅需呼叫 `addFile`方法新增檔案物件即可,RxHttp提供了一系列`addFile`方法,列出幾個常用的,如下:
```java
//新增單個檔案
addFile(String, File)
//新增多個檔案,每個檔案對應相同的key
addFile(String, List fileList)
//新增多個檔案,每個檔案對應不同的key
add