使用功能强大,可以传参(包括json)、传header信息,Cookie的处理,回调函数处理等。先看下调用的代码:
private static final String CONTENT_TYPE = "application/json; charset=utf-8"; public static void login() { HashMap<String, String> headerMap = new HashMap<>(); HashMap<String, String> paramsMap = new HashMap<>(); headerMap.put("Content-Type", CONTENT_TYPE);//头部信息 paramsMap.put("userName", USER_NAME);//参数 paramsMap.put("password", PASSWORD); OkhttpUtil.okHttpPost(loginUrl, paramsMap, headerMap, new CallBackUtil.CallBackDefault() {//回调 @Override public void onFailure(Call call, Exception e) { LogUtil.e(TAG, e.getMessage()); TVAppUtil.showToast("网络异常!请确认是否联网,以及服务器地址是否正确!"); SharedPreferencesUtil.sharePut("newServerAddress",""); } @Override public void onResponse(Response response) { try { isLogin = true; Headers responseHeaders = response.headers(); String c = responseHeaders.get("Set-Cookie");//cookie的处理 TVAppUtil.setCookie(c); updateReportData(); HandlerUtil.sendTimingRequest(); } catch (Exception e) { LogUtil.e(TAG, e.getMessage()); TVAppUtil.showToast("登录异常!"); } finally { try { response.body().close(); } catch (Exception e) { } } } }); }
如果参数是json,则调用:
OkhttpUtil.okHttpPostJson(queryWorkerUrl, jsonStr, headerMap, new CallBackUtil.CallBackString() {
@Override
public void onFailure(Call call, Exception e) {
}
@Override
public void onResponse(String response) {
}
});
使用的步骤如下:
1、配置gradle
compile 'com.squareup.okhttp3:okhttp:3.2.0'
2、准备好这三个搭配使用的工具类(从别的博客获得的,不知来源了,如有侵权还请告知!):
OkhttpUtil、CallBackUtil<T>、RequestUtil
3、代码如下
package com.sinotcc.www.zhonghuakaoqintv.util;
import java.io.File;
import java.util.List;
import java.util.Map;
public class OkhttpUtil {
public static final String METHOD_GET = "GET";
public static final String METHOD_POST = "POST";
public static final String METHOD_PUT = "PUT";
public static final String METHOD_DELETE = "DELETE";
public static final String FILE_TYPE_FILE = "file/*";
public static final String FILE_TYPE_IMAGE = "image/*";
public static final String FILE_TYPE_AUDIO = "audio/*";
public static final String FILE_TYPE_VIDEO = "video/*";
/**
* get请求
*
* @param url:url
* @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用,这两个方法都执行在UI线程。
*/
public static void okHttpGet(String url, CallBackUtil callBack) {
okHttpGet(url, null, null, callBack);
}
/**
* get请求,可以传递参数
*
* @param url:url
* @param paramsMap:map集合,封装键值对参数
* @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用,这两个方法都执行在UI线程。
*/
public static void okHttpGet(String url, Map<String, String> paramsMap, CallBackUtil callBack) {
okHttpGet(url, paramsMap, null, callBack);
}
/**
* get请求,可以传递参数
*
* @param url:url
* @param paramsMap:map集合,封装键值对参数
* @param headerMap:map集合,封装请求头键值对
* @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用,这两个方法都执行在UI线程。
*/
public static void okHttpGet(String url, Map<String, String> paramsMap, Map<String, String> headerMap, CallBackUtil callBack) {
new RequestUtil(METHOD_GET, url, paramsMap, headerMap, callBack).execute();
}
/**
* post请求
*
* @param url:url
* @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用,这两个方法都执行在UI线程。
*/
public static void okHttpPost(String url, CallBackUtil callBack) {
okHttpPost(url, null, callBack);
}
/**
* post请求,可以传递参数
*
* @param url:url
* @param paramsMap:map集合,封装键值对参数
* @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用,这两个方法都执行在UI线程。
*/
public static void okHttpPost(String url, Map<String, String> paramsMap, CallBackUtil callBack) {
okHttpPost(url, paramsMap, null, callBack);
}
/**
* post请求,可以传递参数
*
* @param url:url
* @param paramsMap:map集合,封装键值对参数
* @param headerMap:map集合,封装请求头键值对
* @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用,这两个方法都执行在UI线程。
*/
public static void okHttpPost(String url, Map<String, String> paramsMap, Map<String, String> headerMap, CallBackUtil callBack) {
new RequestUtil(METHOD_POST, url, paramsMap, headerMap, callBack).execute();
}
/**
* post请求
*
* @param url:url
* @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用,这两个方法都执行在UI线程。
*/
public static void okHttpPut(String url, CallBackUtil callBack) {
okHttpPut(url, null, callBack);
}
/**
* post请求,可以传递参数
*
* @param url:url
* @param paramsMap:map集合,封装键值对参数
* @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用,这两个方法都执行在UI线程。
*/
public static void okHttpPut(String url, Map<String, String> paramsMap, CallBackUtil callBack) {
okHttpPut(url, paramsMap, null, callBack);
}
/**
* post请求,可以传递参数
*
* @param url:url
* @param paramsMap:map集合,封装键值对参数
* @param headerMap:map集合,封装请求头键值对
* @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用,这两个方法都执行在UI线程。
*/
public static void okHttpPut(String url, Map<String, String> paramsMap, Map<String, String> headerMap, CallBackUtil callBack) {
new RequestUtil(METHOD_PUT, url, paramsMap, headerMap, callBack).execute();
}
/**
* post请求
*
* @param url:url
* @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用,这两个方法都执行在UI线程。
*/
public static void okHttpDelete(String url, CallBackUtil callBack) {
okHttpDelete(url, null, callBack);
}
/**
* post请求,可以传递参数
*
* @param url:url
* @param paramsMap:map集合,封装键值对参数
* @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用,这两个方法都执行在UI线程。
*/
public static void okHttpDelete(String url, Map<String, String> paramsMap, CallBackUtil callBack) {
okHttpDelete(url, paramsMap, null, callBack);
}
/**
* post请求,可以传递参数
*
* @param url:url
* @param paramsMap:map集合,封装键值对参数
* @param headerMap:map集合,封装请求头键值对
* @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用,这两个方法都执行在UI线程。
*/
public static void okHttpDelete(String url, Map<String, String> paramsMap, Map<String, String> headerMap, CallBackUtil callBack) {
new RequestUtil(METHOD_DELETE, url, paramsMap, headerMap, callBack).execute();
}
/**
* post请求,可以传递参数
*
* @param url:url
* @param jsonStr:json格式的键值对参数
* @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用,这两个方法都执行在UI线程。
*/
public static void okHttpPostJson(String url, String jsonStr, CallBackUtil callBack) {
okHttpPostJson(url, jsonStr, null, callBack);
}
/**
* post请求,可以传递参数
*
* @param url:url
* @param jsonStr:json格式的键值对参数
* @param headerMap:map集合,封装请求头键值对
* @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用,这两个方法都执行在UI线程。
*/
public static void okHttpPostJson(String url, String jsonStr, Map<String, String> headerMap, CallBackUtil callBack) {
new RequestUtil(METHOD_POST, url, jsonStr, headerMap, callBack).execute();
}
/**
* post请求,上传单个文件
*
* @param url:url
* @param file:File对象
* @param fileKey:上传参数时file对应的键
* @param fileType:File类型,是image,video,audio,file
* @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用,这两个方法都执行在UI线程。还可以重写onProgress方法,得到上传进度
*/
public static void okHttpUploadFile(String url, File file, String fileKey, String fileType, CallBackUtil callBack) {
okHttpUploadFile(url, file, fileKey, fileType, null, callBack);
}
/**
* post请求,上传单个文件
*
* @param url:url
* @param file:File对象
* @param fileKey:上传参数时file对应的键
* @param fileType:File类型,是image,video,audio,file
* @param paramsMap:map集合,封装键值对参数
* @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用,这两个方法都执行在UI线程。还可以重写onProgress方法,得到上传进度
*/
public static void okHttpUploadFile(String url, File file, String fileKey, String fileType, Map<String, String> paramsMap, CallBackUtil callBack) {
okHttpUploadFile(url, file, fileKey, fileType, paramsMap, null, callBack);
}
/**
* post请求,上传单个文件
*
* @param url:url
* @param file:File对象
* @param fileKey:上传参数时file对应的键
* @param fileType:File类型,是image,video,audio,file
* @param paramsMap:map集合,封装键值对参数
* @param headerMap:map集合,封装请求头键值对
* @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用,这两个方法都执行在UI线程。还可以重写onProgress方法,得到上传进度
*/
public static void okHttpUploadFile(String url, File file, String fileKey, String fileType, Map<String, String> paramsMap, Map<String, String> headerMap, CallBackUtil callBack) {
new RequestUtil(METHOD_POST, url, paramsMap, file, fileKey, fileType, headerMap, callBack).execute();
}
/**
* post请求,上传多个文件,以list集合的形式
*
* @param url:url
* @param fileList:集合元素是File对象
* @param fileKey:上传参数时fileList对应的键
* @param fileType:File类型,是image,video,audio,file
* @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用,这两个方法都执行在UI线程。
*/
public static void okHttpUploadListFile(String url, List<File> fileList, String fileKey, String fileType, CallBackUtil callBack) {
okHttpUploadListFile(url, null, fileList, fileKey, fileType, callBack);
}
/**
* post请求,上传多个文件,以list集合的形式
*
* @param url:url
* @param fileList:集合元素是File对象
* @param fileKey:上传参数时fileList对应的键
* @param fileType:File类型,是image,video,audio,file
* @param paramsMap:map集合,封装键值对参数
* @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用,这两个方法都执行在UI线程。
*/
public static void okHttpUploadListFile(String url, Map<String, String> paramsMap, List<File> fileList, String fileKey, String fileType, CallBackUtil callBack) {
okHttpUploadListFile(url, paramsMap, fileList, fileKey, fileType, null, callBack);
}
/**
* post请求,上传多个文件,以list集合的形式
*
* @param url:url
* @param fileList:集合元素是File对象
* @param fileKey:上传参数时fileList对应的键
* @param fileType:File类型,是image,video,audio,file
* @param paramsMap:map集合,封装键值对参数
* @param headerMap:map集合,封装请求头键值对
* @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用,这两个方法都执行在UI线程。
*/
public static void okHttpUploadListFile(String url, Map<String, String> paramsMap, List<File> fileList, String fileKey, String fileType, Map<String, String> headerMap, CallBackUtil callBack) {
new RequestUtil(METHOD_POST, url, paramsMap, fileList, fileKey, fileType, headerMap, callBack).execute();
}
/**
* post请求,上传多个文件,以map集合的形式
*
* @param url:url
* @param fileMap:集合key是File对象对应的键,集合value是File对象
* @param fileType:File类型,是image,video,audio,file
* @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用,这两个方法都执行在UI线程。
*/
public static void okHttpUploadMapFile(String url, Map<String, File> fileMap, String fileType, CallBackUtil callBack) {
okHttpUploadMapFile(url, fileMap, fileType, null, callBack);
}
/**
* post请求,上传多个文件,以map集合的形式
*
* @param url:url
* @param fileMap:集合key是File对象对应的键,集合value是File对象
* @param fileType:File类型,是image,video,audio,file
* @param paramsMap:map集合,封装键值对参数
* @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用,这两个方法都执行在UI线程。
*/
public static void okHttpUploadMapFile(String url, Map<String, File> fileMap, String fileType, Map<String, String> paramsMap, CallBackUtil callBack) {
okHttpUploadMapFile(url, fileMap, fileType, paramsMap, null, callBack);
}
/**
* post请求,上传多个文件,以map集合的形式
*
* @param url:url
* @param fileMap:集合key是File对象对应的键,集合value是File对象
* @param fileType:File类型,是image,video,audio,file
* @param paramsMap:map集合,封装键值对参数
* @param headerMap:map集合,封装请求头键值对
* @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用,这两个方法都执行在UI线程。
*/
public static void okHttpUploadMapFile(String url, Map<String, File> fileMap, String fileType, Map<String, String> paramsMap, Map<String, String> headerMap, CallBackUtil callBack) {
new RequestUtil(METHOD_POST, url, paramsMap, fileMap, fileType, headerMap, callBack).execute();
}
/**
* 下载文件,不带参数
*/
public static void okHttpDownloadFile(String url, CallBackUtil.CallBackFile callBack) {
okHttpDownloadFile(url, null, callBack);
}
/**
* 下载文件,带参数
*/
public static void okHttpDownloadFile(String url, Map<String, String> paramsMap, CallBackUtil.CallBackFile callBack) {
okHttpGet(url, paramsMap, null, callBack);
}
/**
* 加载图片
*/
public static void okHttpGetBitmap(String url, CallBackUtil.CallBackBitmap callBack) {
okHttpGetBitmap(url, null, callBack);
}
/**
* 加载图片,带参数
*/
public static void okHttpGetBitmap(String url, Map<String, String> paramsMap, CallBackUtil.CallBackBitmap callBack) {
okHttpGet(url, paramsMap, null, callBack);
}
}
package com.sinotcc.www.zhonghuakaoqintv.util;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Looper;
import android.widget.ImageView;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import okhttp3.Call;
import okhttp3.Response;
public abstract class CallBackUtil<T> {
public static Handler mMainHandler = new Handler(Looper.getMainLooper());
public void onProgress(float progress, long total ){};
public void onError(final Call call, final Exception e){
mMainHandler.post(new Runnable() {
@Override
public void run() {
onFailure(call,e);
}
});
};
public void onSeccess(Call call, Response response){
final T obj = onParseResponse(call, response);
mMainHandler.post(new Runnable() {
@Override
public void run() {
onResponse(obj);
}
});
};
/**
* 解析response,执行在子线程
*/
public abstract T onParseResponse(Call call, Response response);
/**
* 访问网络失败后被调用,执行在UI线程
*/
public abstract void onFailure(Call call, Exception e);
/**
*
* 访问网络成功后被调用,执行在UI线程
*/
public abstract void onResponse(T response);
public static abstract class CallBackDefault extends CallBackUtil<Response>{
@Override
public Response onParseResponse(Call call, Response response) {
return response;
}
}
public static abstract class CallBackString extends CallBackUtil<String>{
@Override
public String onParseResponse(Call call, Response response) {
try {
return response.body().string();
} catch (IOException e) {
new RuntimeException("failure");
return "";
}
}
}
public static abstract class CallBackBitmap extends CallBackUtil<Bitmap>{
private int mTargetWidth;
private int mTargetHeight;
public CallBackBitmap(){};
public CallBackBitmap(int targetWidth,int targetHeight){
mTargetWidth = targetWidth;
mTargetHeight = targetHeight;
};
public CallBackBitmap(ImageView imageView){
int width = imageView.getWidth();
int height = imageView.getHeight();
if(width <=0 || height <=0){
throw new RuntimeException("无法获取ImageView的width或height");
}
mTargetWidth = width;
mTargetHeight = height;
};
@Override
public Bitmap onParseResponse(Call call, Response response) {
if(mTargetWidth ==0 || mTargetHeight == 0){
return BitmapFactory.decodeStream(response.body().byteStream());
}else {
return getZoomBitmap(response);
}
}
/**
* 压缩图片,避免OOM异常
*/
private Bitmap getZoomBitmap(Response response) {
byte[] data = null;
try {
data = response.body().bytes();
} catch (IOException e) {
e.printStackTrace();
}
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(data,0,data.length,options);
int picWidth = options.outWidth;
int picHeight = options.outHeight;
int sampleSize = 1;
int heightRatio = (int) Math.floor((float) picWidth / (float) mTargetWidth);
int widthRatio = (int) Math.floor((float) picHeight / (float) mTargetHeight);
if (heightRatio > 1 || widthRatio > 1){
sampleSize = Math.max(heightRatio,widthRatio);
}
options.inSampleSize = sampleSize;
options.inJustDecodeBounds = false;
Bitmap bitmap = BitmapFactory.decodeByteArray(data,0,data.length,options);
if(bitmap == null){
throw new RuntimeException("Failed to decode stream.");
}
return bitmap;
}
}
/**
* 下载文件时的回调类
*/
public static abstract class CallBackFile extends CallBackUtil<File>{
private final String mDestFileDir;
private final String mdestFileName;
/**
*
* @param destFileDir:文件目录
* @param destFileName:文件名
*/
public CallBackFile(String destFileDir, String destFileName){
mDestFileDir = destFileDir;
mdestFileName = destFileName;
}
@Override
public File onParseResponse(Call call, Response response) {
InputStream is = null;
byte[] buf = new byte[1024*8];
int len = 0;
FileOutputStream fos = null;
try{
is = response.body().byteStream();
final long total = response.body().contentLength();
long sum = 0;
File dir = new File(mDestFileDir);
if (!dir.exists()){
dir.mkdirs();
}
File file = new File(dir, mdestFileName);
fos = new FileOutputStream(file);
while ((len = is.read(buf)) != -1){
sum += len;
fos.write(buf, 0, len);
final long finalSum = sum;
mMainHandler.post(new Runnable() {
@Override
public void run() {
onProgress(finalSum * 100.0f / total,total);
}
});
}
fos.flush();
return file;
} catch (Exception e) {
e.printStackTrace();
} finally{
try{
response.body().close();
if (is != null) is.close();
} catch (IOException e){
}
try{
if (fos != null) fos.close();
} catch (IOException e){
}
}
return null;
}
}
}
package com.sinotcc.www.zhonghuakaoqintv.util;
import android.text.TextUtils;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okio.Buffer;
import okio.BufferedSink;
import okio.ForwardingSink;
import okio.Okio;
import okio.Sink;
class RequestUtil {
private String mMetyodType;//请求方式,目前只支持get和post
private String mUrl;//接口
private Map<String, String> mParamsMap;//键值对类型的参数,只有这一种情况下区分post和get。
private String mJsonStr;//json类型的参数,post方式
private File mFile;//文件的参数,post方式,只有一个文件
private List<File> mfileList;//文件集合,这个集合对应一个key,即mfileKey
private String mfileKey;//上传服务器的文件对应的key
private Map<String, File> mfileMap;//文件集合,每个文件对应一个key
private String mFileType;//文件类型的参数,与file同时存在
private Map<String, String> mHeaderMap;//头参数
private CallBackUtil mCallBack;//回调接口
private OkHttpClient mOkHttpClient;//OKhttpClient对象
private Request mOkHttpRequest;//请求对象
private Request.Builder mRequestBuilder;//请求对象的构建者
RequestUtil(String methodType, String url, Map<String, String> paramsMap, Map<String, String> headerMap, CallBackUtil callBack) {
this(methodType, url, null, null, null, null, null, null, paramsMap, headerMap, callBack);
}
RequestUtil(String methodType, String url, String jsonStr, Map<String, String> headerMap, CallBackUtil callBack) {
this(methodType, url, jsonStr, null, null, null, null, null, null, headerMap, callBack);
}
RequestUtil(String methodType, String url, Map<String, String> paramsMap, File file, String fileKey, String fileType, Map<String, String> headerMap, CallBackUtil callBack) {
this(methodType, url, null, file, null, fileKey, null, fileType, paramsMap, headerMap, callBack);
}
RequestUtil(String methodType, String url, Map<String, String> paramsMap, List<File> fileList, String fileKey, String fileType, Map<String, String> headerMap, CallBackUtil callBack) {
this(methodType, url, null, null, fileList, fileKey, null, fileType, paramsMap, headerMap, callBack);
}
RequestUtil(String methodType, String url, Map<String, String> paramsMap, Map<String, File> fileMap, String fileType, Map<String, String> headerMap, CallBackUtil callBack) {
this(methodType, url, null, null, null, null, fileMap, fileType, paramsMap, headerMap, callBack);
}
private RequestUtil(String methodType, String url, String jsonStr, File file, List<File> fileList, String fileKey, Map<String, File> fileMap, String fileType, Map<String, String> paramsMap, Map<String, String> headerMap, CallBackUtil callBack) {
mMetyodType = methodType;
mUrl = url;
mJsonStr = jsonStr;
mFile = file;
mfileList = fileList;
mfileKey = fileKey;
mfileMap = fileMap;
mFileType = fileType;
mParamsMap = paramsMap;
mHeaderMap = headerMap;
mCallBack = callBack;
getInstance();
}
/**
* 创建OKhttpClient实例。
*/
private void getInstance() {
mOkHttpClient = new OkHttpClient();
mRequestBuilder = new Request.Builder();
if (mFile != null || mfileList != null || mfileMap != null) {//先判断是否有文件,
setFile();
} else {
//设置参数
switch (mMetyodType) {
case OkhttpUtil.METHOD_GET:
setGetParams();
break;
case OkhttpUtil.METHOD_POST:
mRequestBuilder.post(getRequestBody());
break;
case OkhttpUtil.METHOD_PUT:
mRequestBuilder.put(getRequestBody());
break;
case OkhttpUtil.METHOD_DELETE:
mRequestBuilder.delete(getRequestBody());
break;
}
}
mRequestBuilder.url(mUrl);
if (mHeaderMap != null) {
setHeader();
}
//mRequestBuilder.addHeader("Authorization","Bearer "+"token");可以把token添加到这儿
mOkHttpRequest = mRequestBuilder.build();
}
/**
* 得到body对象
*/
private RequestBody getRequestBody() {
/**
* 首先判断mJsonStr是否为空,由于mJsonStr与mParamsMap不可能同时存在,所以先判断mJsonStr
*/
if (!TextUtils.isEmpty(mJsonStr)) {
MediaType JSON = MediaType.parse("application/json; charset=utf-8");//数据类型为json格式,
return RequestBody.create(JSON, mJsonStr);//json数据,
}
/**
* post,put,delete都需要body,但也都有body等于空的情况,此时也应该有body对象,但body中的内容为空
*/
FormBody.Builder formBody = new FormBody.Builder();
if (mParamsMap != null) {
for (String key : mParamsMap.keySet()) {
formBody.add(key, mParamsMap.get(key));
}
}
return formBody.build();
}
/**
* get请求,只有键值对参数
*/
private void setGetParams() {
if (mParamsMap != null) {
mUrl = mUrl + "?";
for (String key : mParamsMap.keySet()) {
mUrl = mUrl + key + "=" + mParamsMap.get(key) + "&";
}
mUrl = mUrl.substring(0, mUrl.length() - 1);
}
}
/**
* 设置上传文件
*/
private void setFile() {
if (mFile != null) {//只有一个文件,且没有文件名
if (mParamsMap == null) {
setPostFile();
} else {
setPostParameAndFile();
}
} else if (mfileList != null) {//文件集合,只有一个文件名。所以这个也支持单个有文件名的文件
setPostParameAndListFile();
} else if (mfileMap != null) {//多个文件,每个文件对应一个文件名
setPostParameAndMapFile();
}
}
/**
* 只有一个文件,且提交服务器时不用指定键,没有参数
*/
private void setPostFile() {
if (mFile != null && mFile.exists()) {
MediaType fileType = MediaType.parse(mFileType);
RequestBody body = RequestBody.create(fileType, mFile);//json数据,
mRequestBuilder.post(new ProgressRequestBody(body, mCallBack));
}
}
/**
* 只有一个文件,且提交服务器时不用指定键,带键值对参数
*/
private void setPostParameAndFile() {
if (mParamsMap != null && mFile != null) {
MultipartBody.Builder builder = new MultipartBody.Builder();
builder.setType(MultipartBody.FORM);
for (String key : mParamsMap.keySet()) {
builder.addFormDataPart(key, mParamsMap.get(key));
}
builder.addFormDataPart(mfileKey, mFile.getName(), RequestBody.create(MediaType.parse(mFileType), mFile));
mRequestBuilder.post(new ProgressRequestBody(builder.build(), mCallBack));
}
}
/**
* 文件集合,可能带有键值对参数
*/
private void setPostParameAndListFile() {
if (mfileList != null) {
MultipartBody.Builder builder = new MultipartBody.Builder();
builder.setType(MultipartBody.FORM);
if (mParamsMap != null) {
for (String key : mParamsMap.keySet()) {
builder.addFormDataPart(key, mParamsMap.get(key));
}
}
for (File f : mfileList) {
builder.addFormDataPart(mfileKey, f.getName(), RequestBody.create(MediaType.parse(mFileType), f));
}
mRequestBuilder.post(builder.build());
}
}
/**
* 文件Map,可能带有键值对参数
*/
private void setPostParameAndMapFile() {
if (mfileMap != null) {
MultipartBody.Builder builder = new MultipartBody.Builder();
builder.setType(MultipartBody.FORM);
if (mParamsMap != null) {
for (String key : mParamsMap.keySet()) {
builder.addFormDataPart(key, mParamsMap.get(key));
}
}
for (String key : mfileMap.keySet()) {
builder.addFormDataPart(key, mfileMap.get(key).getName(), RequestBody.create(MediaType.parse(mFileType), mfileMap.get(key)));
}
mRequestBuilder.post(builder.build());
}
}
/**
* 设置头参数
*/
private void setHeader() {
if (mHeaderMap != null) {
for (String key : mHeaderMap.keySet()) {
mRequestBuilder.addHeader(key, mHeaderMap.get(key));
}
}
}
void execute() {
mOkHttpClient.newCall(mOkHttpRequest).enqueue(new Callback() {
@Override
public void onFailure(final Call call, final IOException e) {
if (mCallBack != null) {
mCallBack.onError(call, e);
}
}
@Override
public void onResponse(final Call call, final Response response) throws IOException {
if (mCallBack != null) {
mCallBack.onSeccess(call, response);
}
}
});
}
/**
* 自定义RequestBody类,得到文件上传的进度
*/
private static class ProgressRequestBody extends RequestBody {
//实际的待包装请求体
private final RequestBody requestBody;
//包装完成的BufferedSink
private BufferedSink bufferedSink;
private CallBackUtil callBack;
ProgressRequestBody(RequestBody requestBody, CallBackUtil callBack) {
this.requestBody = requestBody;
this.callBack = callBack;
}
/**
* 重写调用实际的响应体的contentType
*/
@Override
public MediaType contentType() {
return requestBody.contentType();
}
/**
* 重写调用实际的响应体的contentLength ,这个是文件的总字节数
*/
@Override
public long contentLength() throws IOException {
return requestBody.contentLength();
}
/**
* 重写进行写入
*/
@Override
public void writeTo(BufferedSink sink) throws IOException {
if (bufferedSink == null) {
bufferedSink = Okio.buffer(sink(sink));
}
requestBody.writeTo(bufferedSink);
//必须调用flush,否则最后一部分数据可能不会被写入
bufferedSink.flush();
}
/**
* 写入,回调进度接口
*/
private Sink sink(BufferedSink sink) {
return new ForwardingSink(sink) {
//当前写入字节数
long bytesWritten = 0L;
//总字节长度,避免多次调用contentLength()方法
long contentLength = 0L;
@Override
public void write(Buffer source, long byteCount) throws IOException {
super.write(source, byteCount);//这个方法会循环调用,byteCount是每次调用上传的字节数。
if (contentLength == 0) {
//获得总字节长度
contentLength = contentLength();
}
//增加当前写入的字节数
bytesWritten += byteCount;
final float progress = bytesWritten * 1.0f / contentLength;
CallBackUtil.mMainHandler.post(new Runnable() {
@Override
public void run() {
callBack.onProgress(progress, contentLength);
}
});
}
};
}
}
}