OKHttpUtil.java 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724
  1. package com.edufound.android.xyyf.util;
  2. import android.os.Handler;
  3. import android.os.Looper;
  4. import com.alibaba.fastjson.JSONObject;
  5. import com.edufound.android.xyyf.application.EApplication;
  6. import java.io.File;
  7. import java.io.FileOutputStream;
  8. import java.io.IOException;
  9. import java.io.InputStream;
  10. import java.net.FileNameMap;
  11. import java.net.URLConnection;
  12. import java.util.ArrayList;
  13. import java.util.HashMap;
  14. import java.util.List;
  15. import java.util.Map;
  16. import java.util.Set;
  17. import okhttp3.Call;
  18. import okhttp3.Callback;
  19. import okhttp3.Cookie;
  20. import okhttp3.CookieJar;
  21. import okhttp3.FormBody;
  22. import okhttp3.Headers;
  23. import okhttp3.HttpUrl;
  24. import okhttp3.Interceptor;
  25. import okhttp3.MediaType;
  26. import okhttp3.MultipartBody;
  27. import okhttp3.OkHttpClient;
  28. import okhttp3.Request;
  29. import okhttp3.RequestBody;
  30. import okhttp3.Response;
  31. import okhttp3.ResponseBody;
  32. import okio.Buffer;
  33. import okio.BufferedSource;
  34. import okio.ForwardingSource;
  35. import okio.Okio;
  36. public class OKHttpUtil {
  37. private OkHttpClient okHttpClient;
  38. private Handler handler;
  39. private static OKHttpUtil mInstance;
  40. private final HashMap<String, List<Cookie>> cookieStore = new HashMap<>();
  41. private OKHttpUtil() {
  42. //添加cookie
  43. okHttpClient = new OkHttpClient.Builder().cookieJar(new CookieJar() {
  44. @Override
  45. public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
  46. cookieStore.put(url.host(), cookies);
  47. }
  48. @Override
  49. public List<Cookie> loadForRequest(HttpUrl url) {
  50. List<Cookie> cookies = cookieStore.get(url.host());
  51. return cookies != null ? cookies : new ArrayList<Cookie>();
  52. }
  53. }).build();
  54. handler = new Handler(Looper.getMainLooper());
  55. }
  56. /**
  57. * 单例模式创建OkHttpUtil
  58. *
  59. * @return mInstance
  60. */
  61. public static OKHttpUtil getInstance() {
  62. if (mInstance == null) {
  63. synchronized (OKHttpUtil.class) {
  64. mInstance = new OKHttpUtil();
  65. }
  66. }
  67. return mInstance;
  68. }
  69. /**
  70. * get 同步请求
  71. *
  72. * @return response
  73. */
  74. private Response _getDataSync(String url) {
  75. Request request = new Request.Builder()
  76. .get()//默认get,可省略
  77. .url(url)
  78. .build();
  79. Response response = null;
  80. try {
  81. response = okHttpClient.newCall(request).execute();
  82. } catch (IOException e) {
  83. e.printStackTrace();
  84. }
  85. return response;
  86. }
  87. /**
  88. * get 同步请求
  89. *
  90. * @return 字符串
  91. */
  92. private String _getDataString(String url) throws IOException {
  93. Response response = _getDataSync(url);
  94. if (response.body() != null) {
  95. return response.body().string();
  96. }
  97. return null;
  98. }
  99. /**
  100. * get 异步请求
  101. */
  102. private void _getDataAsync(String url, final ResultCallback callback) {
  103. final Request request = new Request.Builder()
  104. .url(url)
  105. .build();
  106. deliveryResult(callback, request);
  107. }
  108. /**
  109. * post 同步请求
  110. *
  111. * @return response
  112. */
  113. private Response _postDataSync(String url, Param... params) throws IOException {
  114. Request request = buildPostRequest(url, params);
  115. return okHttpClient.newCall(request).execute();
  116. }
  117. /**
  118. * post 同步请求
  119. *
  120. * @return 字符串
  121. */
  122. private String _postDataString(String url, Param... params) throws IOException {
  123. Response response = _postDataSync(url, params);
  124. return response.body().string();
  125. }
  126. /**
  127. * post 异步请求
  128. */
  129. private void _postDataAsync(String url, final ResultCallback callback, Param... params) {
  130. Request request = buildPostRequest(url, params);
  131. deliveryResult(callback, request);
  132. }
  133. /**
  134. * post 异步请求
  135. */
  136. private void _postDataAsync(String url, final ResultCallback callback, Map<String, String> params) {
  137. Param[] paramsArr = map2Params(params);
  138. Request request = buildPostRequest(url, paramsArr);
  139. deliveryResult(callback, request);
  140. }
  141. /**
  142. * post 同步文件上传
  143. */
  144. private Response _postDataFileSync(String url, File[] files, String[] fileKeys, Param... params) throws IOException {
  145. Request request = buildMultipartFormRequest(url, files, fileKeys, params);
  146. return okHttpClient.newCall(request).execute();
  147. }
  148. private Response _postDataFileSync(String url, File file, String fileKey) throws IOException {
  149. Request request = buildMultipartFormRequest(url, new File[]{file}, new String[]{fileKey}, null);
  150. return okHttpClient.newCall(request).execute();
  151. }
  152. private Response _postDataFileSync(String url, File file, String fileKey, Param... params) throws IOException {
  153. Request request = buildMultipartFormRequest(url, new File[]{file}, new String[]{fileKey}, params);
  154. return okHttpClient.newCall(request).execute();
  155. }
  156. /**
  157. * 异步基于post的多文件上传
  158. */
  159. private void _postDataFileAsync(String url, final ResultCallback callback, File[] files, String[] fileKeys, Param... params) {
  160. Request request = buildMultipartFormRequest(url, files, fileKeys, params);
  161. deliveryResult(callback, request);
  162. }
  163. /**
  164. * 异步基于post的文件上传,单文件不带参数上传
  165. *
  166. * @param url
  167. * @param callback
  168. * @param file
  169. * @param fileKey
  170. */
  171. private void _postDataFileAsync(String url, ResultCallback callback, File file, String fileKey) {
  172. Request request = buildMultipartFormRequest(url, new File[]{file}, new String[]{fileKey}, null);
  173. deliveryResult(callback, request);
  174. }
  175. /**
  176. * 异步基于post的文件上传,单文件且携带其他form参数上传
  177. *
  178. * @param url 接口地址
  179. * @param callback callback
  180. * @param file file
  181. * @param fileKey fileKey
  182. * @param params params
  183. */
  184. private void _postDataFileAsync(String url, ResultCallback callback, File file, String fileKey, Param... params) {
  185. Request request = buildMultipartFormRequest(url, new File[]{file}, new String[]{fileKey}, params);
  186. deliveryResult(callback, request);
  187. }
  188. /**
  189. * 同步 post上传json对象
  190. *
  191. * @param url url;
  192. * @param jsonStr json 字符串
  193. * @return 字符串
  194. * @throws IOException
  195. */
  196. private String _postJsonDataSync(String url, String jsonStr) throws IOException {
  197. String result = null;
  198. MediaType JSON = MediaType.parse("text/html;charset=utf-8");
  199. RequestBody requestBody = RequestBody.create(JSON, jsonStr);
  200. Request request = new Request.Builder().url(url).post(requestBody).build();
  201. Response response = okHttpClient.newCall(request).execute();
  202. result = response.body().string();
  203. return result;
  204. }
  205. /**
  206. * 异步 post上传json对象
  207. *
  208. * @param url url
  209. * @param jsonStr json数据字符串
  210. * @param callback callback
  211. */
  212. private void _postJsonDataAsync(String url, String jsonStr, final ResultCallback callback) {
  213. MediaType JSON = MediaType.parse("text/html;charset=utf-8");
  214. RequestBody requestBody = RequestBody.create(JSON, jsonStr);
  215. Request request = new Request.Builder().url(url).post(requestBody).build();
  216. deliveryResult(callback, request);
  217. }
  218. /**
  219. * post 异步上传图片
  220. *
  221. * @param url url
  222. * @param callback callback
  223. * @param file file
  224. * @param fileKey fileKey
  225. * @param map map
  226. */
  227. private void _upLoadImg(String url, final ResultCallback callback, File file, String fileKey, Map<String, String> map) {
  228. Param[] params = map2Params(map);
  229. getInstance()._postDataFileAsync(url, callback, file, fileKey, params);
  230. }
  231. /**
  232. * 创建 MultipartFormRequest
  233. *
  234. * @param url 接口地址
  235. * @param files files
  236. * @param fileKeys file keys
  237. * @param params params
  238. * @return MultipartFormRequest
  239. */
  240. private Request buildMultipartFormRequest(String url, File[] files,
  241. String[] fileKeys, Param[] params) {
  242. params = validateParam(params);
  243. MultipartBody.Builder builder = new MultipartBody.Builder();
  244. for (Param param : params) {
  245. builder.addPart(Headers.of("Content-Disposition", "form-data; name=\"" + param.key + "\""),
  246. RequestBody.create(null, param.value));
  247. }
  248. if (files != null) {
  249. RequestBody fileBody;
  250. for (int i = 0; i < files.length; i++) {
  251. File file = files[i];
  252. String fileName = file.getName();
  253. fileBody = RequestBody.create(MediaType.parse(guessMimeType(fileName)), file);
  254. //TODO 根据文件名设置contentType
  255. builder.addPart(Headers.of("Content-Disposition",
  256. "form-data; name=\"" + fileKeys[i] + "\"; filename=\"" + fileName + "\""),
  257. fileBody);
  258. }
  259. }
  260. RequestBody requestBody = builder.build();
  261. return new Request.Builder()
  262. .url(url)
  263. .post(requestBody)
  264. .build();
  265. }
  266. private Param[] validateParam(Param[] params) {
  267. if (params == null)
  268. return new Param[0];
  269. else
  270. return params;
  271. }
  272. private String guessMimeType(String path) {
  273. FileNameMap fileNameMap = URLConnection.getFileNameMap();
  274. String contentTypeFor = fileNameMap.getContentTypeFor(path);
  275. if (contentTypeFor == null) {
  276. contentTypeFor = "application/octet-stream";
  277. }
  278. return contentTypeFor;
  279. }
  280. /**
  281. * 异步下载文件
  282. */
  283. private void _downloadFileAsync(final String url, final String destFileDir,
  284. final DownloadListener downloadListener) {
  285. final Request request = new Request.Builder().url(url).build();
  286. // 重写ResponseBody监听请求
  287. Interceptor interceptor = new Interceptor() {
  288. @Override
  289. public Response intercept(Chain chain) throws IOException {
  290. Response originalResponse = chain.proceed(chain.request());
  291. return originalResponse.newBuilder()
  292. .body(new DownloadResponseBody(originalResponse, 0, downloadListener))
  293. .build();
  294. }
  295. };
  296. OkHttpClient.Builder dlOkhttp = new OkHttpClient.Builder()
  297. .addNetworkInterceptor(interceptor);
  298. final Call call = dlOkhttp.build().newCall(request);
  299. call.enqueue(new Callback() {
  300. @Override
  301. public void onFailure(Call call, IOException e) {
  302. downloadListener.fail(e.getMessage());
  303. }
  304. @Override
  305. public void onResponse(Call call, Response response) throws IOException {
  306. long length = response.body().contentLength();
  307. downloadListener.start(length);
  308. InputStream is = null;
  309. byte[] b = new byte[2048];
  310. int len;
  311. FileOutputStream fos = null;
  312. try {
  313. is = response.body().byteStream();
  314. File file = new File(destFileDir, getFileName(url));
  315. fos = new FileOutputStream(file);
  316. while ((len = is.read(b)) != -1) {
  317. fos.write(b, 0, len);
  318. }
  319. fos.flush();
  320. // 如果下载文件成功,第一个参数为文件的绝对路径
  321. downloadListener.complete(file.getAbsolutePath());
  322. } catch (Exception e) {
  323. downloadListener.loadfail(e.getMessage());
  324. } finally {
  325. if (is != null) {
  326. is.close();
  327. }
  328. if (fos != null) {
  329. fos.close();
  330. }
  331. }
  332. }
  333. });
  334. }
  335. private String getFileName(String path) {
  336. int separatorIndex = path.lastIndexOf("/");
  337. return (separatorIndex < 0) ? path : path.substring(separatorIndex + 1,
  338. path.length());
  339. }
  340. /***************************************************************** 公共方法***************************************************/
  341. /**
  342. * get 同步请求
  343. *
  344. * @param url 接口地址
  345. * @return response
  346. */
  347. public static Response getDataSync(String url) {
  348. return getInstance()._getDataSync(url);
  349. }
  350. /**
  351. * get 同步请求
  352. *
  353. * @param url 接口地址
  354. * @return 字符串
  355. * @throws IOException
  356. */
  357. public static String getDataString(String url) throws IOException {
  358. return getInstance()._getDataString(url);
  359. }
  360. /**
  361. * get 异步请求
  362. *
  363. * @param url 接口地址
  364. */
  365. public static void getDataAsync(String url, final ResultCallback callback) {
  366. getInstance()._getDataAsync(url, callback);
  367. }
  368. /**
  369. * post 同步请求
  370. *
  371. * @param url url
  372. * @param param param
  373. * @return response
  374. * @throws IOException
  375. */
  376. public static Response postDataSync(String url, Param... param) throws IOException {
  377. return getInstance()._postDataSync(url, param);
  378. }
  379. /**
  380. * post 同步请求
  381. *
  382. * @param url url
  383. * @param params param
  384. * @return 字符串
  385. * @throws IOException
  386. */
  387. public static String postDataString(String url, Param... params) throws IOException {
  388. return getInstance()._postDataString(url, params);
  389. }
  390. /**
  391. * post 异步请求
  392. *
  393. * @param url url
  394. * @param callback 异步回调
  395. * @param params params
  396. */
  397. public static void postDataAsync(String url, final ResultCallback callback, Param... params) {
  398. getInstance()._postDataAsync(url, callback, params);
  399. }
  400. /**
  401. * post map集合 异步请求
  402. *
  403. * @param url url
  404. * @param callback callback
  405. * @param params params
  406. */
  407. public static void postDataAsync(String url, final ResultCallback callback, Map<String, String> params) {
  408. getInstance()._postDataAsync(url, callback, params);
  409. }
  410. /**
  411. * post 异步上传图片
  412. *
  413. * @param url url
  414. * @param callback callback
  415. * @param file file
  416. * @param fileKey fileKey
  417. * @param map map
  418. */
  419. public static void upLoadImg(String url, final ResultCallback callback, File file, String fileKey, Map<String, String> map) {
  420. getInstance()._upLoadImg(url, callback, file, fileKey, map);
  421. }
  422. /**
  423. * @param url 下载地址
  424. * @param destFileDir 保存地址
  425. * @param downloadListener downloadListener
  426. */
  427. public static void downloadFileAsync(String url, String destFileDir, DownloadListener downloadListener) {
  428. getInstance()._downloadFileAsync(url, destFileDir, downloadListener);
  429. }
  430. public static void postUserTime(ResultCallback resultCallback) {
  431. // JSONObject obj = new JSONObject();
  432. // obj.put("channel", EApplication.getAppCode());
  433. // long runtime = System.currentTimeMillis() - ContextUtil.getAppStartTime();
  434. // obj.put("timeAcc", String.valueOf(runtime));
  435. // obj.put("deviceCode", ContextUtil.getUserUuid());
  436. // String json = obj.toJSONString();
  437. // Logger.e("post user time json:" + json);
  438. // getInstance()._postJsonDataAsync(ContextUtil.getPostUserTimeUrl(), json, resultCallback);
  439. }
  440. public void postPhoneLogin(String url, String json, ResultCallback resultCallback) {
  441. MediaType JSON = MediaType.parse("application/json;charset=utf-8");
  442. RequestBody requestBody = RequestBody.create(JSON, json);
  443. Request request = new Request.Builder().url(url).post(requestBody).build();
  444. deliveryResult(resultCallback, request);
  445. }
  446. public void doGetSync(String url, Callback callback) throws IOException {
  447. // 创建一个Request
  448. Request request = new Request.Builder()
  449. .url(url)
  450. .build();
  451. doAsync(request, callback);
  452. }
  453. /**
  454. * 异步请求
  455. */
  456. public void doAsync(Request request, Callback callback) throws IOException {
  457. //创建请求会话
  458. Call call = okHttpClient.newCall(request);
  459. //同步执行会话请求
  460. call.enqueue(callback);
  461. }
  462. /**
  463. * map 转换为 Param
  464. *
  465. * @param params map
  466. * @return params
  467. */
  468. private Param[] map2Params(Map<String, String> params) {
  469. if (params == null) {
  470. return new Param[0];
  471. }
  472. int size = params.size();
  473. Param[] res = new Param[size];
  474. Set<Map.Entry<String, String>> entries = params.entrySet();
  475. int i = 0;
  476. for (Map.Entry<String, String> entry : entries) {
  477. res[i++] = new Param(entry.getKey(), entry.getValue());
  478. }
  479. return res;
  480. }
  481. /**
  482. * 创建 PostRequest
  483. *
  484. * @param url url
  485. * @param params params
  486. * @return request
  487. */
  488. private Request buildPostRequest(String url, Param[] params) {
  489. if (params == null) {
  490. params = new Param[0];
  491. }
  492. FormBody.Builder builder = new FormBody.Builder();
  493. for (Param param : params) {
  494. builder.add(param.key, param.value);
  495. }
  496. RequestBody requestBody = builder.build();
  497. return new Request.Builder()
  498. .url(url)
  499. .post(requestBody)
  500. .build();
  501. }
  502. /**
  503. * 抽象类,用于请求成功后的回调
  504. *
  505. * @param <T>
  506. */
  507. public static abstract class ResultCallback<T> {
  508. //这是请求数据的返回类型,包含常见的(Bean,List等)
  509. //失败回调
  510. public abstract void onError(Request request, Exception e);
  511. //成功的回调
  512. public abstract void onResponse(T response);
  513. }
  514. private Map<String, String> mSessions = new HashMap<>();
  515. /**
  516. * 请求回调处理方法并传递返回值
  517. *
  518. * @param callback Map类型请求参数
  519. * @param request Request请求
  520. */
  521. private void deliveryResult(final ResultCallback callback, final Request request) {
  522. okHttpClient.newCall(request).enqueue(new Callback() {
  523. @Override
  524. public void onFailure(Call call, IOException e) {
  525. sendFailedStringCallback(request, e, callback);
  526. }
  527. @Override
  528. public void onResponse(Call call, Response response) throws IOException {
  529. try {
  530. final String string = response.body().string();
  531. sendSuccessResultCallback(string, callback);
  532. } catch (IOException e) {
  533. sendFailedStringCallback(response.request(), e, callback);
  534. }
  535. }
  536. });
  537. }
  538. /**
  539. * 处理请求失败的回调信息方法
  540. *
  541. * @param e 错误信息
  542. * @param callback 回调类
  543. */
  544. private void sendFailedStringCallback(final Request request, final Exception e, final ResultCallback callback) {
  545. handler.post(new Runnable() {
  546. @Override
  547. public void run() {
  548. if (callback != null)
  549. callback.onError(request, e);
  550. }
  551. });
  552. }
  553. /**
  554. * 处理请求成功的回调信息方法
  555. *
  556. * @param object 服务器响应信息
  557. * @param callback 回调类
  558. */
  559. private void sendSuccessResultCallback(final Object object, final ResultCallback callback) {
  560. handler.post(new Runnable() {
  561. @Override
  562. public void run() {
  563. if (callback != null) {
  564. callback.onResponse(object);
  565. }
  566. }
  567. });
  568. }
  569. public static class Param {
  570. public Param() {
  571. }
  572. public Param(String key, String value) {
  573. this.key = key;
  574. this.value = value;
  575. }
  576. String key;
  577. String value;
  578. }
  579. public class DownloadResponseBody extends ResponseBody {
  580. private Response originalResponse;
  581. private DownloadListener downloadListener;
  582. private long oldPoint = 0;
  583. public DownloadResponseBody(Response originalResponse, long startsPoint, DownloadListener downloadListener) {
  584. this.originalResponse = originalResponse;
  585. this.downloadListener = downloadListener;
  586. this.oldPoint = startsPoint;
  587. Logger.e("DownloadResponseBody");
  588. }
  589. @Override
  590. public MediaType contentType() {
  591. return originalResponse.body().contentType();
  592. }
  593. @Override
  594. public long contentLength() {
  595. return originalResponse.body().contentLength();
  596. }
  597. @Override
  598. public BufferedSource source() {
  599. return Okio.buffer(new ForwardingSource(originalResponse.body().source()) {
  600. private long bytesReaded = 0;
  601. @Override
  602. public long read(Buffer sink, long byteCount) throws IOException {
  603. long bytesRead = super.read(sink, byteCount);
  604. bytesReaded += bytesRead == -1 ? 0 : bytesRead;
  605. if (downloadListener != null) {
  606. downloadListener.loading((int) ((bytesReaded + oldPoint)));
  607. }
  608. return bytesRead;
  609. }
  610. });
  611. }
  612. }
  613. public interface DownloadListener {
  614. /**
  615. * 开始下载
  616. */
  617. void start(long max);
  618. /**
  619. * 正在下载
  620. */
  621. void loading(int progress);
  622. /**
  623. * 下载完成
  624. */
  625. void complete(String path);
  626. /**
  627. * 请求失败
  628. */
  629. void fail(String message);
  630. /**
  631. * 下载过程中失败
  632. */
  633. void loadfail(String message);
  634. }
  635. }