Okhttp是现在比较流行的请求框架,项目中也经常用到,所以就封装了工具类:
首先build gradle中进行配置:
compile 'com.squareup.okhttp3:okhttp:3.2.0'
下面是代码,已经封装好了。可以直接使用:
package czb.okhttputils; 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
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 paramsMap, Map 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 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 paramsMap, Map 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 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 paramsMap, Map 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 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 paramsMap, Map 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 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 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 paramsMap, Map 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 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 paramsMap, List 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 paramsMap, List fileList, String fileKey, String fileType, Map 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 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 fileMap, String fileType, Map 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 fileMap, String fileType, Map paramsMap, Map 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 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 paramsMap, CallBackUtil.CallBackBitmap callBack) { okHttpGet(url, paramsMap, null, callBack); } }
package czb.okhttputils; /** * Created by 宝 on 2019/7/3. */ 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 MapmParamsMap;//键值对类型的参数,只有这一种情况下区分post和get。 private String mJsonStr;//json类型的参数,post方式 private File mFile;//文件的参数,post方式,只有一个文件 private List mfileList;//文件集合,这个集合对应一个key,即mfileKey private String mfileKey;//上传服务器的文件对应的key private Map mfileMap;//文件集合,每个文件对应一个key private String mFileType;//文件类型的参数,与file同时存在 private Map mHeaderMap;//头参数 private CallBackUtil mCallBack;//回调接口 private OkHttpClient mOkHttpClient;//OKhttpClient对象 private Request mOkHttpRequest;//请求对象 private Request.Builder mRequestBuilder;//请求对象的构建者 RequestUtil(String methodType, String url, Map paramsMap, Map headerMap, CallBackUtil callBack) { this(methodType, url, null, null, null, null, null, null, paramsMap, headerMap, callBack); } RequestUtil(String methodType, String url, String jsonStr, Map headerMap, CallBackUtil callBack) { this(methodType, url, jsonStr, null, null, null, null, null, null, headerMap, callBack); } RequestUtil(String methodType, String url, Map paramsMap, File file, String fileKey, String fileType, Map headerMap, CallBackUtil callBack) { this(methodType, url, null, file, null, fileKey, null, fileType, paramsMap, headerMap, callBack); } RequestUtil(String methodType, String url, Map paramsMap, List fileList, String fileKey, String fileType, Map headerMap, CallBackUtil callBack) { this(methodType, url, null, null, fileList, fileKey, null, fileType, paramsMap, headerMap, callBack); } RequestUtil(String methodType, String url, Map paramsMap, Map fileMap, String fileType, Map 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 fileList, String fileKey, Map fileMap, String fileType, Map paramsMap, Map 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); } }); } }; } } }
package czb.okhttputils; /** * Created by 宝 on 2019/7/3. */ 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{ 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 { @Override public Response onParseResponse(Call call, Response response) { return response; } } public static abstract class CallBackString extends CallBackUtil { @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 { 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 { 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; } } }