Get請求
@query
@Query會以key=value的方式拼接在url後面
Query非必填,如果請求參數非必填,可以傳null
如:https://api.douban.com/v2/movie/top250?start=0&count=10
ApiServer.kt
@GET("top250")
fun getTopMovie(@Query("start") start: Int, @Query("count") count: Int): Call<ResponseEntity>
MainActivity.kt
@OnClick(R.id.tv_main)
fun getTopMovie() {
val retrofit = Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl("https://api.douban.com/v2/movie/")
.build()
val apiService = retrofit.create(ApiServer::class.java)
val call = apiService.getTopMovie(0, 10)
call.enqueue(object : Callback<ResponseEntity> {
override fun onFailure(call: Call<ResponseEntity>?, t: Throwable?) {
}
override fun onResponse(call: Call<ResponseEntity>?, response: Response<ResponseEntity>?) {
Log.i("qfxl", "response = ${response?.body()}")
}
})
}
@QueryMap
如果Query參數比較多,那麼可以通過@QueryMap方式將所有的參數集成在一個Map。
如:https://api.douban.com/v2/movie/top250?start=0&count=10
ApiServer.kt
@GET("top250")
fun getTopMovie(@QueryMap params: Map<String, String>): Call<ResponseEntity>
MainActivity.kt
@OnClick(R.id.tv_main)
fun getTopMovie() {
val retrofit = Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl("https://api.douban.com/v2/movie/")
.build()
val apiService = retrofit.create(ApiServer::class.java)
val params = mapOf("start" to "0", "count" to "10")
val call = apiService.getTopMovie(params)
call.enqueue(object : Callback<ResponseEntity> {
override fun onFailure(call: Call<ResponseEntity>?, t: Throwable?) {
}
override fun onResponse(call: Call<ResponseEntity>?, response: Response<ResponseEntity>?) {
Log.i("qfxl", "response = ${response?.body()}")
}
})
}
Query集合
假如需要添加相同Key值,但是value卻有多個的情況,一種方式是添加多個@Query參數,還有一種簡便的方式是將所有的value放置在列表中,然後在同一個@Query下完成添加
如:https://api.douban.com/v2/movie/top250?start=0&start=1
ApiServer.kt
@GET("top250")
fun getTopMovie(@Query("start") paramList: List<String>): Call<ResponseEntity>
MainActivity.kt
@OnClick(R.id.tv_main)
fun getTopMovie() {
val retrofit = Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl("http://gank.io/api/data/")
.build()
val apiService = retrofit.create(ApiServer::class.java)
val listParam = listOf("0","1")
val call = apiService.getTopMovie(listParam)
call.enqueue(object : Callback<ResponseEntity> {
override fun onFailure(call: Call<ResponseEntity>?, t: Throwable?) {
}
override fun onResponse(call: Call<ResponseEntity>?, response: Response<ResponseEntity>?) {
Log.i("qfxl", "response = ${response?.body()}")
}
})
}
@Path
如果請求的相對地址也是需要調用方傳遞,那麼可以使用@Path註解
@Path可以用於任何請求方式,包括Post,Put,Delete等等
如:http://gank.io/api/data/Android/10/1
ApiServer.kt
@GET("Android/{pageSize}/{page}")
fun getAndroid(@Path("pageSize") pageSize: Int, @Path("page") page: Int): Call<ResponseEntity>
MainActivity.kt
@OnClick(R.id.tv_main)
fun getAndroid() {
val retrofit = Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl("http://gank.io/api/data/")
.build()
val apiService = retrofit.create(ApiServer::class.java)
val call = apiService.getAndroid(10, 1)
call.enqueue(object : Callback<ResponseEntity> {
override fun onFailure(call: Call<ResponseEntity>?, t: Throwable?) {
}
override fun onResponse(call: Call<ResponseEntity>?, response: Response<ResponseEntity>?) {
Log.i("qfxl", "response = ${response?.body()}")
}
})
}
#Post請求
@Field
Post請求需要把請求參數放置在請求體中,而非拼接在url後面。
如:https://gank.io/api/add2gank
字段 | 描述 | 備註 |
---|---|---|
url | 想要提交的網頁地址 | |
desc | 對乾貨內容的描述 | 單獨的文字描述 |
who | 提交者 ID | 乾貨提交者的網絡 ID |
type | 乾貨類型 | 可選參數: Android、iOS、休息視頻、福利、拓展資源、前端、瞎推薦、App |
debug | 當前提交爲測試數據 | 如果想要測試數據請設置 debug 爲 true! 可選參數: true、false |
ApiServer.kt
@FormUrlEncoded
@POST("add2gank")
fun addToGank(@Field("url") url: String, @Field("desc") desc: String, @Field("who") who: String, @Field("type") type: String, @Field("debug") debug: Boolean): Call<ResponseEntity>
MainActivity.kt
@OnClick(R.id.tv_main)
fun addToGank() {
val retrofit = Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl("https://gank.io/api/")
.build()
val apiService = retrofit.create(ApiServer::class.java)
val call = apiService.addToGank("http://gank.io/api", "test", "qfxl", "App", true)
call.enqueue(object : Callback<ResponseEntity> {
override fun onFailure(call: Call<ResponseEntity>?, t: Throwable?) {
}
override fun onResponse(call: Call<ResponseEntity>?, response: Response<ResponseEntity>?) {
Log.i("qfxl", "response = ${response?.body()}")
}
})
}
注:@FormUrlEncoded將會自動將請求參數的類型調整爲application/x-www-form-urlencoded
Field註解將每一個請求參數都存放至請求體中,還可以添加encoded參數,該參數爲boolean型,encoded參數爲true的話,key-value-pair將會被編碼,即將中文和特殊字符進行編碼轉換
如:
@FormUrlEncoded
@POST("add2gank")
fun addToGank(@Field("url", encoded = true) url: String):Call<ResponseEntity>
@FieldMap
假如有多個請求參數,這個時候就可以用FieldMap
如:https://gank.io/api/add2gank
字段 | 描述 | 備註 |
---|---|---|
url | 想要提交的網頁地址 | |
desc | 對乾貨內容的描述 | 單獨的文字描述 |
who | 提交者 ID | 乾貨提交者的網絡 ID |
type | 乾貨類型 | 可選參數: Android、iOS、休息視頻、福利、拓展資源、前端、瞎推薦、App |
debug | 當前提交爲測試數據 | 如果想要測試數據請設置 debug 爲 true! 可選參數: true、false |
ApiServer.kt
@FormUrlEncoded
@POST("add2gank")
fun addToGank(@FieldMap mapParam: Map<String, String>, @Field("debug") debug: Boolean): Call<ResponseEntity>
MainActivity.kt
@OnClick(R.id.tv_main)
fun addToGank() {
val retrofit = Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl("https://gank.io/api/")
.build()
val apiService = retrofit.create(ApiServer::class.java)
val mapParam = mapOf(
"url" to "http://gank.io/api",
"desc" to "test",
"who" to "qfxl",
"type" to "App"
)
val call = apiService.addToGank(mapParam, true)
call.enqueue(object : Callback<ResponseEntity> {
override fun onFailure(call: Call<ResponseEntity>?, t: Throwable?) {
}
override fun onResponse(call: Call<ResponseEntity>?, response: Response<ResponseEntity>?) {
Log.i("qfxl", "response = ${response?.body()}")
}
})
}
注意,Map泛型不接受Any(Java中的Object)
@Body
只針對Post請求,參數爲json形式的時候使用
上傳(帶進度)
定義上傳進度回調接口
interface UploadListener {
/**
* 上傳進度
*
* @param progress
* @param total
* @param done
*/
fun onProgress(progress: Long, total: Long, done: Boolean)
}
改造RequestBody
class ProgressRequestBody(private val mRequestBody: RequestBody, private val mUploadListener: UploadListener) : RequestBody() {
private var mCountingSink: CountingSink? = null
override fun contentType(): MediaType? {
return mRequestBody.contentType()
}
override fun contentLength(): Long {
try {
return mRequestBody.contentLength()
} catch (e: IOException) {
e.printStackTrace()
return -1
}
}
@Throws(IOException::class)
override fun writeTo(sink: BufferedSink) {
val bufferedSink: BufferedSink
mCountingSink = CountingSink(sink)
bufferedSink = Okio.buffer(mCountingSink!!)
mRequestBody.writeTo(bufferedSink)
bufferedSink.flush()
}
internal inner class CountingSink(delegate: Sink) : ForwardingSink(delegate) {
private var bytesWritten: Long = 0
@Throws(IOException::class)
override fun write(source: Buffer, byteCount: Long) {
super.write(source, byteCount)
bytesWritten += byteCount
mUploadListener.onProgress(bytesWritten, contentLength(), bytesWritten == contentLength())
}
}
}
定義上傳api
interface UploadApi {
@Multipart
@POST
fun upload(@Url url: String, @Part parts: List<MultipartBody.Part>): Call<ResponseBody>
}
定義攔截器
class UploadInterceptor(private val uploadListener: UploadListener) : Interceptor {
@Throws(IOException::class)
override fun intercept(chain: Interceptor.Chain): Response {
val originRequest = chain.request()
if (null == originRequest.body()) {
return chain.proceed(originRequest)
}
val newRequest = originRequest.newBuilder()
.method(originRequest.method(), ProgressRequestBody(originRequest.body()!!, uploadListener))
.build()
return chain.proceed(newRequest)
}
}
封裝上傳
class ZbyUploadManager private constructor() {
private var mRetrofit: Retrofit? = null
/**
* 佔位BaseUrl
*/
private val ZBY_CORP = "http://www.zbycorp.com/"
/**
* okHttp的攔截器
*/
private val interceptors = SparseArray<Interceptor>()
private var uploadListener: UploadListener? = null
/**
* 線程調度
*/
private val dispatchHandler: Handler
/**
* 默認的Retrofit
*
* @return
*/
private val defaultRetrofit: Retrofit
get() = Retrofit.Builder()
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(ZBY_CORP)
.client(defaultOkHttp)
.build()
/**
* 默認的okHttpClient
*
* @return
*/
//添加攔截器
val defaultOkHttp: OkHttpClient
get() {
val builder = OkHttpClient.Builder()
builder.readTimeout(3, TimeUnit.MINUTES)
.writeTimeout(3, TimeUnit.MINUTES)
.addInterceptor(UploadInterceptor(object : UploadListener {
override fun onProgress(progress: Long, total: Long, done: Boolean) {
val msg = Message.obtain()
msg.arg1 = progress.toInt()
msg.arg2 = total.toInt()
msg.obj = done
dispatchHandler.sendMessage(msg)
}
}))
if (interceptorSize > 0) {
for (i in 0 until interceptorSize) {
builder.addInterceptor(interceptors.get(i))
}
}
return builder.build()
}
/**
* 獲取Retrofit
*
* @return
*/
/**
* 設置Retrofit(如果有特殊需求的話)
*
* @param retrofit
*/
var retrofit: Retrofit?
get() = if (mRetrofit == null) {
defaultRetrofit
} else mRetrofit
set(retrofit) = if (retrofit == null) {
mRetrofit = defaultRetrofit
} else {
mRetrofit = retrofit
}
/**
* 獲取攔截器數量
*
* @return
*/
private val interceptorSize: Int
get() = interceptors.size()
init {
dispatchHandler = Handler(Looper.getMainLooper(), Handler.Callback { msg ->
val progress = msg.arg1.toLong()
val total = msg.arg2.toLong()
val done = msg.obj as Boolean
if (uploadListener != null) {
//如果需要轉換成100進度的話(100 * progress) / total
uploadListener!!.onProgress(progress, total, done)
}
true
})
}
private object Holder {
val INSTANCE = ZbyUploadManager()
}
/**
* 添加攔截器
*
* @param interceptor
*/
fun addInterceptor(interceptor: Interceptor) {
interceptors.put(interceptorSize, interceptor)
}
/**
* 清空所有攔截器
*/
fun clearInterceptors() {
interceptors.clear()
}
/**
* 移除指定攔截器
*
* @param key
*/
fun clearInterceptorAt(key: Int) {
interceptors.removeAt(key)
}
/**
* 上傳
*
* @param url
* @param uploadParams
*/
fun upload(url: String, uploadParams: UploadParams, callback: Callback<ResponseBody>) {
val uploadApi = retrofit?.create(UploadApi::class.java)
val builder = MultipartBody.Builder()
for (entry in uploadParams.entries) {
if (entry.value is String) {
builder.addFormDataPart(entry.key, entry.value)
} else if (entry.value is File) {
val file = entry.value
builder.addFormDataPart(entry.key, file.name, RequestBody.create(MediaType.parse("multipart/form-data"), file))
}
}
val body = builder.build()
uploadApi?.upload(url, body.parts())
?.enqueue(callback)
}
/**
* 上傳帶進度帶回調
*
* @param url
* @param uploadParams
* @param uploadListener
* @param callback
*/
fun upload(url: String, uploadParams: UploadParams, uploadListener: UploadListener, callback: Callback<ResponseBody>) {
this.uploadListener = uploadListener
val uploadApi = retrofit?.create(UploadApi::class.java)
val builder = MultipartBody.Builder()
for (entry in uploadParams.entries) {
if (entry.value is String) {
builder.addFormDataPart(entry.key, entry.value)
} else if (entry.value is File) {
val file = entry.value
builder.addFormDataPart(entry.key, file.name, RequestBody.create(MediaType.parse("multipart/form-data"), file))
}
}
val body = builder.build()
uploadApi?.upload(url, body.parts())
?.enqueue(callback)
}
companion object {
fun get(): ZbyUploadManager {
return Holder.INSTANCE
}
}
}
##UploadParams
class UploadParams {
val entries = ArrayList<Entry>()
fun put(key: String, value: Any) {
entries.add(Entry(key, value))
}
inner class Entry(val key: String, val value: Any)
}
下載(帶進度)
定義進度回調接口
interface ProgressListener {
/**
* 進度監聽
*
* @param progress 當前上傳下載字節數
* @param total 總的字節數
* @param done 是否完成
*/
fun onProgress(progress: Long, total: Long, done: Boolean)
}
改造ResponseBody
class ProgressResponseBody(private val responseBody: ResponseBody, private val progressListener: ProgressListener) : ResponseBody() {
private var bufferedSource: BufferedSource? = null
override fun contentType(): MediaType? {
return responseBody.contentType()
}
override fun contentLength(): Long {
return responseBody.contentLength()
}
override fun source(): BufferedSource? {
if (bufferedSource == null) {
bufferedSource = Okio.buffer(source(responseBody.source()))
}
return bufferedSource
}
private fun source(source: Source): Source {
return object : ForwardingSource(source) {
internal var totalBytesRead = 0L
@Throws(IOException::class)
override fun read(sink: Buffer, byteCount: Long): Long {
val bytesRead = super.read(sink, byteCount)
totalBytesRead += if (bytesRead != -1L) bytesRead else 0
progressListener.onProgress(totalBytesRead, responseBody.contentLength(), bytesRead == -1L)
return bytesRead
}
}
}
}
定義下載API
interface DownloadApi {
/**
* 下載
*
* @param url 下載的url
* @return
*/
@GET
fun download(@Url url: String): Call<ResponseBody>
}
下載並保存到本地
class DownloadManager {
private val TAG = DownloadManager::class.java.simpleName
private var mRetrofit: Retrofit? = null
/**
* 進度監聽
*/
private var mProgressListener: ProgressListener? = null
/**
* 佔位BaseUrl
*/
private val ZBY_CORP = "http://www.zbycorp.com/"
/**
* 線程調度
*/
private val dispatchHandler: Handler
/**
* okHttp的攔截器
*/
private val interceptors = SparseArray<Interceptor>()
/**
* 下載回調
*/
var onDownloadListener: OnDownloadListener? = null
/**
* 默認的Retrofit
*
* @return
*/
private val defaultRetrofit: Retrofit
get() = Retrofit.Builder()
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(ZBY_CORP)
.client(defaultOkHttp)
.build()
/**
* 獲取攔截器數量
*
* @return
*/
private val interceptorSize: Int
get() = interceptors.size()
/**
* 默認的okHttpClient
*
* @return
*/
//將進度回調到主線程
//添加攔截器
val defaultOkHttp: OkHttpClient
get() {
val builder = OkHttpClient.Builder()
builder.readTimeout(3, TimeUnit.MINUTES)
.writeTimeout(3, TimeUnit.MINUTES)
.networkInterceptors()
.add(Interceptor { chain ->
val originalResponse = chain.proceed(chain.request())
originalResponse.newBuilder().body(
ProgressResponseBody(originalResponse.body()!!, object : ProgressListener {
override fun onProgress(progress: Long, total: Long, done: Boolean) {
val msg = Message.obtain()
msg.arg1 = progress.toInt()
msg.arg2 = total.toInt()
msg.obj = done
dispatchHandler.sendMessage(msg)
}
})).build()
})
if (interceptorSize > 0) {
for (i in 0 until interceptorSize) {
builder.addInterceptor(interceptors.get(i))
}
}
return builder.build()
}
/**
* 獲取Retrofit
*
* @return
*/
/**
* 設置Retrofit(如果有特殊需求的話)
*
* @param retrofit
*/
var retrofit: Retrofit?
get() = if (mRetrofit == null) {
defaultRetrofit
} else mRetrofit
set(retrofit) = if (retrofit == null) {
mRetrofit = defaultRetrofit
} else {
mRetrofit = retrofit
}
init {
dispatchHandler = Handler(Looper.getMainLooper(), Handler.Callback { msg ->
val progress = msg.arg1.toLong()
val total = msg.arg2.toLong()
val done = msg.obj as Boolean
if (mProgressListener != null) {
//如果需要轉換成100進度的話(100 * progress) / total
mProgressListener!!.onProgress(progress, total, done)
}
true
})
}
/**
* 添加攔截器
*
* @param interceptor
*/
fun addInterceptor(interceptor: Interceptor) {
interceptors.put(interceptorSize, interceptor)
}
/**
* 清空所有攔截器
*/
fun clearInterceptors() {
interceptors.clear()
}
/**
* 移除指定攔截器
*
* @param key
*/
fun removeInterceptorAt(key: Int) {
interceptors.removeAt(key)
}
/**
* 下載帶進度
*
* @param url 下載的url
* @param progressListener 進度監聽
* @param destFile 存儲目標文件
*/
fun download(url: String, progressListener: ProgressListener, destFile: File?) {
mProgressListener = progressListener
val downloadApi = retrofit!!.create(DownloadApi::class.java)
downloadApi.download(url)
.enqueue(object : Callback<ResponseBody> {
override fun onResponse(call: retrofit2.Call<ResponseBody>, response: Response<ResponseBody>) {
saveFileToLocal(destFile, response.body())
onDownloadListener?.onDownloadSuccess(destFile!!)
}
override fun onFailure(call: retrofit2.Call<ResponseBody>, t: Throwable) {
onDownloadListener?.onDownloadFailed(t.message!!)
}
})
}
/**
* 下載不帶進度
*
* @param url 下載的url
* @param destFile 存儲目標文件
*/
fun download(url: String, destFile: File?) {
val downloadApi = retrofit!!.create(DownloadApi::class.java)
downloadApi.download(url)
.enqueue(object : Callback<ResponseBody> {
override fun onResponse(call: retrofit2.Call<ResponseBody>, response: Response<ResponseBody>) {
saveFileToLocal(destFile, response.body())
onDownloadListener?.onDownloadSuccess(destFile!!)
}
override fun onFailure(call: retrofit2.Call<ResponseBody>, t: Throwable) {
onDownloadListener?.onDownloadFailed(t.message!!)
}
})
}
/**
* 保存文件到本地
*
* @param destFile 目標文件
* @param responseBody 響應體
*/
private fun saveFileToLocal(destFile: File?, responseBody: ResponseBody?) {
if (responseBody != null && destFile != null) {
val ins = responseBody.byteStream()
destFile.writeBytes(ins.readBytes())
ins.close()
}
}
interface OnDownloadListener {
/**
* 下載成功回調
*/
fun onDownloadSuccess(file: File)
/**
* 下載失敗回調
*/
fun onDownloadFailed(errorMsg: String)
}
}
使用
val downloadManager = ZbyDownloadManager()
downloadManager.setOnDownloadListener(object : ZbyDownloadManager.OnDownloadListener {
override fun downloadSuccess(destFile: File) {
}
override fun downloadFailed(errorMsg: String) {
}
})
val destFileFolder = File(Environment.getExternalStorageDirectory(), "apks")
if (!destFileFolder.exists()) {
destFileFolder.mkdirs()
}
val destFile = File(destFileFolder, "iWMS.apk")
downloadManager.download("http://192.168.8.104:8080/apks/iwms.apk", { progress, total, done ->
updateDialog?.setProgress(((100 * progress) / total).toInt())
}, destFile)
參數加密
加密規則
所有請求添加公用參數如下:
client_id=android
ts=時間戳
dev=imei
req_id=uuid
sign=所有參數(不包含sign參數)按key自然升序排序,然後拼接kv(如:a1b2c3),1次md5,全部轉大寫,最後1次md5
MD5(UPPER(MD5(a1b2c3client_idandroiddevuuidts1234567890)))
java代碼如下(晚點改爲kotlin)
public class AddParamsInterceptor implements Interceptor {
/**
* 公用參數
*/
private Map<String, String> commonParams = new ArrayMap<>();
private Context context;
public AddParamsInterceptor(Context context) {
String timestamp = String.valueOf(TimeUtils.getServerCurrentTimeMillis());
String imei = CommonUtil.isEmpty(DeviceUuidFactory.getInstance()
.getIMEI(context)) ? "" : DeviceUuidFactory.getInstance()
.getIMEI(context);
commonParams.put("client_id", "android_mobile");
commonParams.put("ts", timestamp);
commonParams.put("dev", imei);
commonParams.put("req_id", DeviceUuidFactory.getInstance()
.getDeviceUuidString(context));
this.context = context;
}
@Override
public Response intercept(Chain chain) throws IOException {
Request orgRequest = chain.request();
RequestBody body = orgRequest.body();
String accessToken = (String) SpUtil.get(context, SpUtil.FILE_USER, SpUtil.KEY_USER_ACCESS_TOKEN, "");
//收集請求參數,最後用於sign簽名
StringBuilder paramsBuilder = new StringBuilder();
if (body != null) {
RequestBody newBody = null;
if (body instanceof FormBody) {
newBody = addParamsToFormBody((FormBody) body, paramsBuilder);
} else if (body instanceof MultipartBody) {
newBody = addParamsToMultipartBody((MultipartBody) body, paramsBuilder);
}
if (null != newBody) {
Request.Builder requestBuilder = orgRequest.newBuilder();
//添加authorization
if (!TextUtils.isEmpty(accessToken)) {
requestBuilder.addHeader("Authorization", accessToken);
}
requestBuilder.url(orgRequest.url())
.method(orgRequest.method(), newBody)
.build();
return chain.proceed(requestBuilder.build());
}
} else {
if (!TextUtils.isEmpty(orgRequest.method()) && "get".equals(orgRequest.method().toLowerCase())) {
HttpUrl.Builder authorizedUrlBuilder = orgRequest.url()
.newBuilder()
.scheme(orgRequest.url().scheme())
.host(orgRequest.url().host());
if (commonParams == null || commonParams.size() == 0) {
return chain.proceed(orgRequest);
}
Iterator iter = commonParams.entrySet().iterator();
List<String> keyList = new ArrayList<>();
ArrayMap<String, String> paramMap = new ArrayMap<>();
//公用參數
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
keyList.add(entry.getKey().toString());
paramMap.put(entry.getKey().toString(), entry.getValue().toString());
}
//原始參數
int originParamsSize = orgRequest.url().queryParameterNames().size();
for (int i = 0; i < originParamsSize; i++) {
String key = orgRequest.url().queryParameterName(i);
String value = orgRequest.url().queryParameter(key);
keyList.add(key);
paramMap.put(key, value);
}
Collections.sort(keyList);
int keySize = keyList.size();
//添加公用參數
for (int i = 0; i < keySize; i++) {
//防止重複添加k=v
if (TextUtils.isEmpty(orgRequest.url().queryParameter(keyList.get(i)))) {
authorizedUrlBuilder.addQueryParameter(keyList.get(i), paramMap.get(keyList.get(i)));
}
paramsBuilder.append(keyList.get(i))
.append(paramMap.get(keyList.get(i)));
}
//所有參數的k=v
String originParamStr = paramsBuilder.toString();
String md5Sign = CommonUtil.getMD5(CommonUtil.getMD5(originParamStr)
.toUpperCase());
authorizedUrlBuilder.addQueryParameter("sign", md5Sign);
// 新的請求
Request.Builder requestBuilder = orgRequest.newBuilder();
//添加authorization
if (!TextUtils.isEmpty(accessToken)) {
requestBuilder.addHeader("Authorization", accessToken);
}
requestBuilder.method(orgRequest.method(), orgRequest.body())
.url(authorizedUrlBuilder.build())
.build();
return chain.proceed(requestBuilder.build());
}
}
return chain.proceed(orgRequest);
}
/**
* 爲MultipartBody類型請求體添加參數
*
* @param body
* @param paramsBuilder
* @return
*/
private MultipartBody addParamsToMultipartBody(MultipartBody body, StringBuilder paramsBuilder) {
MultipartBody.Builder builder = new MultipartBody.Builder();
builder.setType(MultipartBody.FORM);
List<String> keyList = new ArrayList<>();
ArrayMap<String, String> paramsMap = new ArrayMap<>();
//動態添加新的參數
if (commonParams == null || commonParams.size() == 0) {
return builder.build();
}
Iterator iter = commonParams.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
keyList.add(entry.getKey().toString());
paramsMap.put(entry.getKey().toString(), entry.getValue().toString());
}
Collections.sort(keyList);
int keySize = keyList.size();
for (int i = 0; i < keySize; i++) {
builder.addFormDataPart(keyList.get(i), paramsMap.get(keyList.get(i)));
paramsBuilder.append(keyList.get(i))
.append(paramsMap.get(keyList.get(i)));
}
//所有參數的k=v
String originParamStr = paramsBuilder.toString();
String md5Sign = CommonUtil.getMD5(CommonUtil.getMD5(originParamStr)
.toUpperCase());
//添加sign
builder.addFormDataPart("sign", md5Sign);
//添加原請求體
for (int i = 0; i < body.size(); i++) {
builder.addPart(body.part(i));
}
return builder.build();
}
/**
* 爲FormBody類型請求體添加參數
*
* @param body
* @param paramsBuilder
* @return
*/
private FormBody addParamsToFormBody(FormBody body, StringBuilder paramsBuilder) {
FormBody.Builder builder = new FormBody.Builder();
//動態添加新的參數
if (commonParams == null || commonParams.size() == 0) {
return builder.build();
}
Iterator iter = commonParams.entrySet().iterator();
List<String> keyList = new ArrayList<>();
ArrayMap<String, String> paramsMap = new ArrayMap<>();
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
keyList.add(entry.getKey().toString());
paramsMap.put(entry.getKey().toString(), entry.getValue().toString());
}
//添加原請求體
for (int i = 0; i < body.size(); i++) {
keyList.add(body.encodedName(i));
paramsMap.put(body.encodedName(i), body.encodedValue(i));
}
Collections.sort(keyList);
int keySize = keyList.size();
for (int i = 0; i < keySize; i++) {
builder.addEncoded(keyList.get(i), paramsMap.get(keyList.get(i)));
paramsBuilder.append(keyList.get(i))
.append(paramsMap.get(keyList.get(i)));
}
//所有請求參數的k=v
String originParamStr = paramsBuilder.toString();
String md5Sign = CommonUtil.getMD5(CommonUtil.getMD5(originParamStr)
.toUpperCase());
builder.addEncoded("sign", md5Sign);
return builder.build();
}
}
最後添加到okHttp的攔截器中。
okHttpClientBuilder.addInterceptor(new AddParamsInterceptor(context));