{
+
+ @Override
+ public String parseNetworkResponse(Response response) throws IOException {
+ return response.body().string();
+ }
+}
diff --git a/library_okhttputils/src/main/java/com/lzy/okhttputils/cookie/PersistentCookieStore.java b/library_okhttputils/src/main/java/com/lzy/okhttputils/cookie/PersistentCookieStore.java
new file mode 100644
index 00000000..6e362066
--- /dev/null
+++ b/library_okhttputils/src/main/java/com/lzy/okhttputils/cookie/PersistentCookieStore.java
@@ -0,0 +1,235 @@
+package com.lzy.okhttputils.cookie;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.net.CookieStore;
+import java.net.HttpCookie;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ *
+ * OkHttpClient client = new OkHttpClient.Builder()
+ * .cookieJar(new JavaNetCookieJar(new CookieManager(
+ * new PersistentCookieStore(getApplicationContext()),
+ * CookiePolicy.ACCEPT_ALL))
+ * .build();
+ *
+ * from http://stackoverflow.com/questions/25461792/persistent-cookie-store-using-okhttp-2-on-android
+ *
+ * A persistent cookie store which implements the Apache HttpClient CookieStore interface.
+ * Cookies are stored and will persist on the user's device between application sessions since they
+ * are serialized and stored in SharedPreferences. Instances of this class are
+ * designed to be used with AsyncHttpClient#setCookieStore, but can also be used with a
+ * regular old apache HttpClient/HttpContext if you prefer.
+ */
+public class PersistentCookieStore implements CookieStore {
+
+ private static final String LOG_TAG = "PersistentCookieStore";
+ private static final String COOKIE_PREFS = "CookiePrefsFile";
+ private static final String COOKIE_NAME_PREFIX = "cookie_";
+
+ private final HashMap> cookies;
+ private final SharedPreferences cookiePrefs;
+
+ /**
+ * Construct a persistent cookie store.
+ *
+ * @param context Context to attach cookie store to
+ */
+ public PersistentCookieStore(Context context) {
+ cookiePrefs = context.getSharedPreferences(COOKIE_PREFS, 0);
+ cookies = new HashMap>();
+
+ // Load any previously stored cookies into the store
+ Map prefsMap = cookiePrefs.getAll();
+ for (Map.Entry entry : prefsMap.entrySet()) {
+ if (((String) entry.getValue()) != null && !((String) entry.getValue()).startsWith(COOKIE_NAME_PREFIX)) {
+ String[] cookieNames = TextUtils.split((String) entry.getValue(), ",");
+ for (String name : cookieNames) {
+ String encodedCookie = cookiePrefs.getString(COOKIE_NAME_PREFIX + name, null);
+ if (encodedCookie != null) {
+ HttpCookie decodedCookie = decodeCookie(encodedCookie);
+ if (decodedCookie != null) {
+ if (!cookies.containsKey(entry.getKey()))
+ cookies.put(entry.getKey(), new ConcurrentHashMap());
+ cookies.get(entry.getKey()).put(name, decodedCookie);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public void add(URI uri, HttpCookie cookie) {
+ String name = getCookieToken(uri, cookie);
+
+ // Save cookie into local store, or remove if expired
+ if (!cookie.hasExpired()) {
+ if (!cookies.containsKey(uri.getHost()))
+ cookies.put(uri.getHost(), new ConcurrentHashMap());
+ cookies.get(uri.getHost()).put(name, cookie);
+ } else {
+ if (cookies.containsKey(uri.toString())) cookies.get(uri.getHost()).remove(name);
+ }
+
+ // Save cookie into persistent store
+ SharedPreferences.Editor prefsWriter = cookiePrefs.edit();
+ prefsWriter.putString(uri.getHost(), TextUtils.join(",", cookies.get(uri.getHost()).keySet()));
+ prefsWriter.putString(COOKIE_NAME_PREFIX + name, encodeCookie(new SerializableHttpCookie(cookie)));
+ prefsWriter.commit();
+ }
+
+ protected String getCookieToken(URI uri, HttpCookie cookie) {
+ return cookie.getName() + cookie.getDomain();
+ }
+
+ @Override
+ public List get(URI uri) {
+ ArrayList ret = new ArrayList();
+ if (cookies.containsKey(uri.getHost())) ret.addAll(cookies.get(uri.getHost()).values());
+ return ret;
+ }
+
+ @Override
+ public boolean removeAll() {
+ SharedPreferences.Editor prefsWriter = cookiePrefs.edit();
+ prefsWriter.clear();
+ prefsWriter.commit();
+ cookies.clear();
+ return true;
+ }
+
+ @Override
+ public boolean remove(URI uri, HttpCookie cookie) {
+ String name = getCookieToken(uri, cookie);
+
+ if (cookies.containsKey(uri.getHost()) && cookies.get(uri.getHost()).containsKey(name)) {
+ cookies.get(uri.getHost()).remove(name);
+
+ SharedPreferences.Editor prefsWriter = cookiePrefs.edit();
+ if (cookiePrefs.contains(COOKIE_NAME_PREFIX + name)) {
+ prefsWriter.remove(COOKIE_NAME_PREFIX + name);
+ }
+ prefsWriter.putString(uri.getHost(), TextUtils.join(",", cookies.get(uri.getHost()).keySet()));
+ prefsWriter.commit();
+
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public List getCookies() {
+ ArrayList ret = new ArrayList();
+ for (String key : cookies.keySet())
+ ret.addAll(cookies.get(key).values());
+
+ return ret;
+ }
+
+ @Override
+ public List getURIs() {
+ ArrayList ret = new ArrayList();
+ for (String key : cookies.keySet())
+ try {
+ ret.add(new URI(key));
+ } catch (URISyntaxException e) {
+ e.printStackTrace();
+ }
+
+ return ret;
+ }
+
+ /**
+ * Serializes Cookie object into String
+ *
+ * @param cookie cookie to be encoded, can be null
+ * @return cookie encoded as String
+ */
+ protected String encodeCookie(SerializableHttpCookie cookie) {
+ if (cookie == null) return null;
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ try {
+ ObjectOutputStream outputStream = new ObjectOutputStream(os);
+ outputStream.writeObject(cookie);
+ } catch (IOException e) {
+ Log.d(LOG_TAG, "IOException in encodeCookie", e);
+ return null;
+ }
+
+ return byteArrayToHexString(os.toByteArray());
+ }
+
+ /**
+ * Returns cookie decoded from cookie string
+ *
+ * @param cookieString string of cookie as returned from http request
+ * @return decoded cookie or null if exception occured
+ */
+ protected HttpCookie decodeCookie(String cookieString) {
+ byte[] bytes = hexStringToByteArray(cookieString);
+ ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
+ HttpCookie cookie = null;
+ try {
+ ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
+ cookie = ((SerializableHttpCookie) objectInputStream.readObject()).getCookie();
+ } catch (IOException e) {
+ Log.d(LOG_TAG, "IOException in decodeCookie", e);
+ } catch (ClassNotFoundException e) {
+ Log.d(LOG_TAG, "ClassNotFoundException in decodeCookie", e);
+ }
+
+ return cookie;
+ }
+
+ /**
+ * Using some super basic byte array <-> hex conversions so we don't have to rely on any
+ * large Base64 libraries. Can be overridden if you like!
+ *
+ * @param bytes byte array to be converted
+ * @return string containing hex values
+ */
+ protected String byteArrayToHexString(byte[] bytes) {
+ StringBuilder sb = new StringBuilder(bytes.length * 2);
+ for (byte element : bytes) {
+ int v = element & 0xff;
+ if (v < 16) {
+ sb.append('0');
+ }
+ sb.append(Integer.toHexString(v));
+ }
+ return sb.toString().toUpperCase(Locale.US);
+ }
+
+ /**
+ * Converts hex values from strings to byte arra
+ *
+ * @param hexString string of hex-encoded values
+ * @return decoded byte array
+ */
+ protected byte[] hexStringToByteArray(String hexString) {
+ int len = hexString.length();
+ byte[] data = new byte[len / 2];
+ for (int i = 0; i < len; i += 2) {
+ data[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4) + Character.digit(hexString.charAt(i + 1), 16));
+ }
+ return data;
+ }
+}
\ No newline at end of file
diff --git a/library_okhttputils/src/main/java/com/lzy/okhttputils/cookie/SerializableHttpCookie.java b/library_okhttputils/src/main/java/com/lzy/okhttputils/cookie/SerializableHttpCookie.java
new file mode 100644
index 00000000..a6a82e25
--- /dev/null
+++ b/library_okhttputils/src/main/java/com/lzy/okhttputils/cookie/SerializableHttpCookie.java
@@ -0,0 +1,56 @@
+package com.lzy.okhttputils.cookie;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.net.HttpCookie;
+
+/** from http://stackoverflow.com/questions/25461792/persistent-cookie-store-using-okhttp-2-on-android */
+public class SerializableHttpCookie implements Serializable {
+ private static final long serialVersionUID = 6374381323722046732L;
+
+ private transient final HttpCookie cookie;
+ private transient HttpCookie clientCookie;
+
+ public SerializableHttpCookie(HttpCookie cookie) {
+ this.cookie = cookie;
+ }
+
+ public HttpCookie getCookie() {
+ HttpCookie bestCookie = cookie;
+ if (clientCookie != null) {
+ bestCookie = clientCookie;
+ }
+ return bestCookie;
+ }
+
+ private void writeObject(ObjectOutputStream out) throws IOException {
+ out.writeObject(cookie.getName());
+ out.writeObject(cookie.getValue());
+ out.writeObject(cookie.getComment());
+ out.writeObject(cookie.getCommentURL());
+ out.writeObject(cookie.getDomain());
+ out.writeLong(cookie.getMaxAge());
+ out.writeObject(cookie.getPath());
+ out.writeObject(cookie.getPortlist());
+ out.writeInt(cookie.getVersion());
+ out.writeBoolean(cookie.getSecure());
+ out.writeBoolean(cookie.getDiscard());
+ }
+
+ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
+ String name = (String) in.readObject();
+ String value = (String) in.readObject();
+ clientCookie = new HttpCookie(name, value);
+ clientCookie.setComment((String) in.readObject());
+ clientCookie.setCommentURL((String) in.readObject());
+ clientCookie.setDomain((String) in.readObject());
+ clientCookie.setMaxAge(in.readLong());
+ clientCookie.setPath((String) in.readObject());
+ clientCookie.setPortlist((String) in.readObject());
+ clientCookie.setVersion(in.readInt());
+ clientCookie.setSecure(in.readBoolean());
+ clientCookie.setDiscard(in.readBoolean());
+ }
+}
\ No newline at end of file
diff --git a/library_okhttputils/src/main/java/com/lzy/okhttputils/cookie/SimpleCookieJar.java b/library_okhttputils/src/main/java/com/lzy/okhttputils/cookie/SimpleCookieJar.java
new file mode 100644
index 00000000..1381d60c
--- /dev/null
+++ b/library_okhttputils/src/main/java/com/lzy/okhttputils/cookie/SimpleCookieJar.java
@@ -0,0 +1,30 @@
+package com.lzy.okhttputils.cookie;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import okhttp3.Cookie;
+import okhttp3.CookieJar;
+import okhttp3.HttpUrl;
+
+/** cookie的自动化管理 */
+public final class SimpleCookieJar implements CookieJar {
+
+ private final List allCookies = new ArrayList<>();
+
+ @Override
+ public synchronized void saveFromResponse(HttpUrl url, List cookies) {
+ allCookies.addAll(cookies);
+ }
+
+ @Override
+ public synchronized List loadForRequest(HttpUrl url) {
+ List result = new ArrayList<>();
+ for (Cookie cookie : allCookies) {
+ if (cookie.matches(url)) {
+ result.add(cookie);
+ }
+ }
+ return result;
+ }
+}
diff --git a/library_okhttputils/src/main/java/com/lzy/okhttputils/https/HttpsUtils.java b/library_okhttputils/src/main/java/com/lzy/okhttputils/https/HttpsUtils.java
new file mode 100644
index 00000000..07069e3b
--- /dev/null
+++ b/library_okhttputils/src/main/java/com/lzy/okhttputils/https/HttpsUtils.java
@@ -0,0 +1,136 @@
+package com.lzy.okhttputils.https;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509TrustManager;
+
+/** Https相关的工具类 */
+public class HttpsUtils {
+ public static SSLSocketFactory getSslSocketFactory(InputStream[] certificates, InputStream bksFile, String password) {
+ try {
+ TrustManager[] trustManagers = prepareTrustManager(certificates);
+ KeyManager[] keyManagers = prepareKeyManager(bksFile, password);
+ SSLContext sslContext = SSLContext.getInstance("TLS");
+ sslContext.init(keyManagers, new TrustManager[]{new MyTrustManager(chooseTrustManager(trustManagers))}, new SecureRandom());
+ return sslContext.getSocketFactory();
+ } catch (NoSuchAlgorithmException e) {
+ throw new AssertionError(e);
+ } catch (KeyManagementException e) {
+ throw new AssertionError(e);
+ } catch (KeyStoreException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ private static TrustManager[] prepareTrustManager(InputStream... certificates) {
+ if (certificates == null || certificates.length <= 0) return null;
+ try {
+ CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
+ KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
+ keyStore.load(null);
+ int index = 0;
+ for (InputStream certificate : certificates) {
+ String certificateAlias = Integer.toString(index++);
+ keyStore.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate));
+ try {
+ if (certificate != null) certificate.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ TrustManagerFactory trustManagerFactory;
+ trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+ trustManagerFactory.init(keyStore);
+ return trustManagerFactory.getTrustManagers();
+ } catch (NoSuchAlgorithmException e) {
+ e.printStackTrace();
+ } catch (CertificateException e) {
+ e.printStackTrace();
+ } catch (KeyStoreException e) {
+ e.printStackTrace();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ private static KeyManager[] prepareKeyManager(InputStream bksFile, String password) {
+ try {
+ if (bksFile == null || password == null) return null;
+ KeyStore clientKeyStore = KeyStore.getInstance("BKS");
+ clientKeyStore.load(bksFile, password.toCharArray());
+ KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
+ keyManagerFactory.init(clientKeyStore, password.toCharArray());
+ return keyManagerFactory.getKeyManagers();
+ } catch (KeyStoreException e) {
+ e.printStackTrace();
+ } catch (NoSuchAlgorithmException e) {
+ e.printStackTrace();
+ } catch (UnrecoverableKeyException e) {
+ e.printStackTrace();
+ } catch (CertificateException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ private static X509TrustManager chooseTrustManager(TrustManager[] trustManagers) {
+ for (TrustManager trustManager : trustManagers) {
+ if (trustManager instanceof X509TrustManager) {
+ return (X509TrustManager) trustManager;
+ }
+ }
+ return null;
+ }
+
+ private static class MyTrustManager implements X509TrustManager {
+ private X509TrustManager defaultTrustManager;
+ private X509TrustManager localTrustManager;
+
+ public MyTrustManager(X509TrustManager localTrustManager) throws NoSuchAlgorithmException, KeyStoreException {
+ TrustManagerFactory var4 = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+ var4.init((KeyStore) null);
+ defaultTrustManager = chooseTrustManager(var4.getTrustManagers());
+ this.localTrustManager = localTrustManager;
+ }
+
+ @Override
+ public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
+
+ }
+
+ @Override
+ public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
+ try {
+ defaultTrustManager.checkServerTrusted(chain, authType);
+ } catch (CertificateException ce) {
+ localTrustManager.checkServerTrusted(chain, authType);
+ }
+ }
+
+ @Override
+ public X509Certificate[] getAcceptedIssuers() {
+ return new X509Certificate[0];
+ }
+ }
+}
diff --git a/library_okhttputils/src/main/java/com/lzy/okhttputils/model/RequestHeaders.java b/library_okhttputils/src/main/java/com/lzy/okhttputils/model/RequestHeaders.java
new file mode 100644
index 00000000..0b906493
--- /dev/null
+++ b/library_okhttputils/src/main/java/com/lzy/okhttputils/model/RequestHeaders.java
@@ -0,0 +1,43 @@
+package com.lzy.okhttputils.model;
+
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * ================================================
+ * 作 者:廖子尧
+ * 版 本:1.0
+ * 创建日期:2015/10/10
+ * 描 述:请求头的包装类
+ * 修订历史:
+ * ================================================
+ */
+public class RequestHeaders {
+
+ public ConcurrentHashMap headersMap;
+
+ private void init() {
+ headersMap = new ConcurrentHashMap<>();
+ }
+
+ public RequestHeaders() {
+ init();
+ }
+
+ public RequestHeaders(String key, String value) {
+ init();
+ put(key, value);
+ }
+
+ public void put(String key, String value) {
+ if (key != null && value != null) {
+ headersMap.put(key, value);
+ }
+ }
+
+ public void put(RequestHeaders headers) {
+ if (headers != null) {
+ if (headers.headersMap != null && !headers.headersMap.isEmpty())
+ headersMap.putAll(headers.headersMap);
+ }
+ }
+}
diff --git a/library_okhttputils/src/main/java/com/lzy/okhttputils/model/RequestParams.java b/library_okhttputils/src/main/java/com/lzy/okhttputils/model/RequestParams.java
new file mode 100644
index 00000000..c980d8f3
--- /dev/null
+++ b/library_okhttputils/src/main/java/com/lzy/okhttputils/model/RequestParams.java
@@ -0,0 +1,104 @@
+package com.lzy.okhttputils.model;
+
+import java.io.File;
+import java.net.FileNameMap;
+import java.net.URLConnection;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * ================================================
+ * 作 者:廖子尧
+ * 版 本:1.0
+ * 创建日期:2015/10/9
+ * 描 述:请求参数的包装类
+ * 修订历史:
+ * ================================================
+ */
+public class RequestParams {
+
+ /** 普通的键值对参数 */
+ public ConcurrentHashMap urlParamsMap;
+
+ /** 文件的键值对参数 */
+ public ConcurrentHashMap fileParamsMap;
+
+ private void init() {
+ urlParamsMap = new ConcurrentHashMap<>();
+ fileParamsMap = new ConcurrentHashMap<>();
+ }
+
+ public RequestParams() {
+ init();
+ }
+
+ public RequestParams(String key, String value) {
+ init();
+ put(key, value);
+ }
+
+ public RequestParams(String key, File file) {
+ init();
+ put(key, file);
+ }
+
+ public void put(RequestParams params) {
+ if (params != null) {
+ if (params.urlParamsMap != null && !params.urlParamsMap.isEmpty())
+ urlParamsMap.putAll(params.urlParamsMap);
+ if (params.fileParamsMap != null && !params.fileParamsMap.isEmpty())
+ fileParamsMap.putAll(params.fileParamsMap);
+ }
+ }
+
+ public void put(String key, String value) {
+ if (key != null && value != null) {
+ urlParamsMap.put(key, value);
+ }
+ }
+
+ public void put(String key, File file) {
+ put(key, file, file.getName());
+ }
+
+ public void put(String key, File file, String fileName) {
+ put(key, file, fileName, guessMimeType(fileName));
+ }
+
+ public void put(String key, File file, String fileName, String contentType) {
+ if (key != null) {
+ fileParamsMap.put(key, new FileWrapper(file, fileName, contentType));
+ }
+ }
+
+ private String guessMimeType(String path) {
+ FileNameMap fileNameMap = URLConnection.getFileNameMap();
+ String contentType = fileNameMap.getContentTypeFor(path);
+ if (contentType == null) {
+ contentType = "application/octet-stream";
+ }
+ return contentType;
+ }
+
+ /**
+ * 文件类型的包装类
+ */
+ public static class FileWrapper {
+ public File file;
+ public String fileName;
+ public String contentType;
+
+ public FileWrapper(File file, String fileName, String contentType) {
+ this.file = file;
+ this.fileName = fileName;
+ this.contentType = contentType;
+ }
+
+ public String getFileName() {
+ if (fileName != null) {
+ return fileName;
+ } else {
+ return "nofilename";
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/library_okhttputils/src/main/java/com/lzy/okhttputils/request/BaseRequest.java b/library_okhttputils/src/main/java/com/lzy/okhttputils/request/BaseRequest.java
new file mode 100644
index 00000000..b75cdc68
--- /dev/null
+++ b/library_okhttputils/src/main/java/com/lzy/okhttputils/request/BaseRequest.java
@@ -0,0 +1,232 @@
+package com.lzy.okhttputils.request;
+
+import android.support.annotation.NonNull;
+
+import com.lzy.okhttputils.OkHttpUtils;
+import com.lzy.okhttputils.callback.AbsCallback;
+import com.lzy.okhttputils.https.HttpsUtils;
+import com.lzy.okhttputils.model.RequestHeaders;
+import com.lzy.okhttputils.model.RequestParams;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeUnit;
+
+import okhttp3.Call;
+import okhttp3.Headers;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.RequestBody;
+import okhttp3.Response;
+
+/**
+ * ================================================
+ * 作 者:廖子尧
+ * 版 本:1.0
+ * 创建日期:2016/1/12
+ * 描 述:所有请求的基类,其中泛型 R 主要用于属性设置方法后,返回对应的子类型,以便于实现链式调用
+ * 修订历史:
+ * ================================================
+ */
+public abstract class BaseRequest {
+ protected String url;
+ protected Object tag;
+ protected long readTimeOut;
+ protected long writeTimeOut;
+ protected long connectTimeout;
+ protected InputStream[] certificates;
+ protected RequestParams params = new RequestParams();
+ protected RequestHeaders headers = new RequestHeaders();
+
+ public BaseRequest(String url){
+ this.url = url;
+ }
+
+ public R url(@NonNull String url) {
+ this.url = url;
+ return (R) this;
+ }
+
+ public R tag(Object tag) {
+ this.tag = tag;
+ return (R) this;
+ }
+
+ public R readTimeOut(long readTimeOut) {
+ this.readTimeOut = readTimeOut;
+ return (R) this;
+ }
+
+ public R writeTimeOut(long writeTimeOut) {
+ this.writeTimeOut = writeTimeOut;
+ return (R) this;
+ }
+
+ public R connTimeOut(long connTimeOut) {
+ this.connectTimeout = connTimeOut;
+ return (R) this;
+ }
+
+ public R setCertificates(@NonNull InputStream... certificates) {
+ this.certificates = certificates;
+ return (R) this;
+ }
+
+ public R headers(RequestHeaders headers) {
+ this.headers.put(headers);
+ return (R) this;
+ }
+
+ public R headers(String key, String value) {
+ headers.put(key, value);
+ return (R) this;
+ }
+
+ public R params(RequestParams params) {
+ this.params.put(params);
+ return (R) this;
+ }
+
+ public R params(String key, String value) {
+ params.put(key, value);
+ return (R) this;
+ }
+
+ public R params(String key, File file) {
+ params.put(key, file);
+ return (R) this;
+ }
+
+ public R params(String key, File file, String fileName) {
+ params.put(key, file, fileName);
+ return (R) this;
+ }
+
+ public R params(String key, File file, String fileName, String contentType) {
+ params.put(key, file, fileName, contentType);
+ return (R) this;
+ }
+
+ /** 通用的拼接请求头 */
+ protected Request.Builder appendHeaders(Request.Builder requestBuilder) {
+ Headers.Builder headerBuilder = new Headers.Builder();
+ ConcurrentHashMap headerMap = headers.headersMap;
+ if (headerMap.isEmpty()) return requestBuilder;
+ for (String key : headerMap.keySet()) {
+ headerBuilder.add(key, headerMap.get(key));
+ }
+ requestBuilder.headers(headerBuilder.build());
+ return requestBuilder;
+ }
+
+ /** 根据不同的请求方式和参数,生成不同的RequestBody */
+ public abstract RequestBody generateRequestBody();
+
+ /** 对请求body进行包装,用于回调上传进度 */
+ public RequestBody wrapRequestBody(RequestBody requestBody, final AbsCallback callback) {
+ return new CountingRequestBody(requestBody, new CountingRequestBody.Listener() {
+ @Override
+ public void onRequestProgress(final long bytesWritten, final long contentLength) {
+ OkHttpUtils.getInstance().getDelivery().post(new Runnable() {
+ @Override
+ public void run() {
+ if (callback != null)
+ callback.upProgress(bytesWritten, contentLength, bytesWritten * 1.0f / contentLength);
+ }
+ });
+ }
+ });
+ }
+
+ /** 根据不同的请求方式,将RequestBody转换成Request对象 */
+ public abstract Request generateRequest(RequestBody requestBody);
+
+ /** 根据当前的请求参数,生成对应的 Call 任务 */
+ public Call generateCall(Request request) {
+ if (readTimeOut <= 0 && writeTimeOut <= 0 && connectTimeout <= 0 && certificates == null) {
+ return OkHttpUtils.getInstance().getOkHttpClient().newCall(request);
+ } else {
+ OkHttpClient.Builder newClientBuilder = OkHttpUtils.getInstance().getOkHttpClient().newBuilder();
+ if (readTimeOut > 0) newClientBuilder.readTimeout(readTimeOut, TimeUnit.MILLISECONDS);
+ if (writeTimeOut > 0)
+ newClientBuilder.writeTimeout(writeTimeOut, TimeUnit.MILLISECONDS);
+ if (connectTimeout > 0)
+ newClientBuilder.connectTimeout(connectTimeout, TimeUnit.MILLISECONDS);
+ if (certificates != null)
+ newClientBuilder.sslSocketFactory(HttpsUtils.getSslSocketFactory(certificates, null, null));
+ return newClientBuilder.build().newCall(request);
+ }
+ }
+
+ /** 阻塞方法,同步请求执行 */
+ public Response execute() {
+ try {
+ RequestBody requestBody = generateRequestBody();
+ final Request request = generateRequest(wrapRequestBody(requestBody, null));
+ Call call = generateCall(request);
+ return call.execute();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ /** 非阻塞方法,异步请求,但是回调在子线程中执行 */
+ public void execute(AbsCallback callback) {
+ if (callback == null) callback = AbsCallback.CALLBACK_DEFAULT;
+
+ final AbsCallback finalCallback = callback;
+ finalCallback.onBefore(this); //请求执行前调用 (UI线程)
+ RequestBody requestBody = generateRequestBody();
+ Request request = generateRequest(wrapRequestBody(requestBody, finalCallback));
+ Call call = generateCall(request);
+ call.enqueue(new okhttp3.Callback() {
+ @Override
+ public void onFailure(Request request, IOException e) {
+ //请求失败,一般为url地址错误,网络错误等
+ sendFailResultCallback(request, null, e, finalCallback);
+ }
+
+ @Override
+ public void onResponse(Response response) throws IOException {
+ //响应失败,一般为服务器内部错误,或者找不到页面等
+ if (response.code() >= 400 && response.code() <= 599) {
+ sendFailResultCallback(response.request(), response, null, finalCallback);
+ return;
+ }
+
+ try {
+ //解析过程中抛出异常,一般为 json 格式错误,或者数据解析异常
+ T t = (T) finalCallback.parseNetworkResponse(response);
+ sendSuccessResultCallback(t, response.request(), response, finalCallback);
+ } catch (Exception e) {
+ sendFailResultCallback(response.request(), response, e, finalCallback);
+ }
+ }
+ });
+ }
+
+ /** 失败回调,发送到主线程 */
+ public void sendFailResultCallback(final Request request, final Response response, final Exception e, final AbsCallback callback) {
+ OkHttpUtils.getInstance().getDelivery().post(new Runnable() {
+ @Override
+ public void run() {
+ callback.onError(request, response, e); //请求失败回调 (UI线程)
+ callback.onAfter(null, request, response, e); //请求结束回调 (UI线程)
+ }
+ });
+ }
+
+ /** 成功回调,发送到主线程 */
+ public void sendSuccessResultCallback(final T t, final Request request, final Response response, final AbsCallback callback) {
+ OkHttpUtils.getInstance().getDelivery().post(new Runnable() {
+ @Override
+ public void run() {
+ callback.onResponse(t); //请求成功回调 (UI线程)
+ callback.onAfter(t, request, response, null); //请求结束回调 (UI线程)
+ }
+ });
+ }
+}
\ No newline at end of file
diff --git a/library_okhttputils/src/main/java/com/lzy/okhttputils/request/CountingRequestBody.java b/library_okhttputils/src/main/java/com/lzy/okhttputils/request/CountingRequestBody.java
new file mode 100644
index 00000000..89960320
--- /dev/null
+++ b/library_okhttputils/src/main/java/com/lzy/okhttputils/request/CountingRequestBody.java
@@ -0,0 +1,74 @@
+package com.lzy.okhttputils.request;
+
+import java.io.IOException;
+
+import okhttp3.MediaType;
+import okhttp3.RequestBody;
+import okio.Buffer;
+import okio.BufferedSink;
+import okio.ForwardingSink;
+import okio.Okio;
+import okio.Sink;
+
+/**
+ * Decorates an OkHttp request body to count the number of bytes written when writing it. Can
+ * decorate any request body, but is most useful for tracking the upload progress of large
+ * multipart requests.
+ *
+ * @author Leo Nikkilä
+ */
+public class CountingRequestBody extends RequestBody {
+
+ protected RequestBody delegate;
+ protected Listener listener;
+
+ protected CountingSink countingSink;
+
+ public CountingRequestBody(RequestBody delegate, Listener listener) {
+ this.delegate = delegate;
+ this.listener = listener;
+ }
+
+ @Override
+ public MediaType contentType() {
+ return delegate.contentType();
+ }
+
+ @Override
+ public long contentLength() {
+ try {
+ return delegate.contentLength();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return -1;
+ }
+
+ @Override
+ public void writeTo(BufferedSink sink) throws IOException {
+ countingSink = new CountingSink(sink);
+ BufferedSink bufferedSink = Okio.buffer(countingSink);
+ delegate.writeTo(bufferedSink);
+ bufferedSink.flush();
+ }
+
+ protected final class CountingSink extends ForwardingSink {
+ private long bytesWritten = 0;
+
+ public CountingSink(Sink delegate) {
+ super(delegate);
+ }
+
+ @Override
+ public void write(Buffer source, long byteCount) throws IOException {
+ super.write(source, byteCount);
+ bytesWritten += byteCount;
+ listener.onRequestProgress(bytesWritten, contentLength());
+ }
+
+ }
+
+ public interface Listener {
+ void onRequestProgress(long bytesWritten, long contentLength);
+ }
+}
\ No newline at end of file
diff --git a/library_okhttputils/src/main/java/com/lzy/okhttputils/request/GetRequest.java b/library_okhttputils/src/main/java/com/lzy/okhttputils/request/GetRequest.java
new file mode 100644
index 00000000..06895701
--- /dev/null
+++ b/library_okhttputils/src/main/java/com/lzy/okhttputils/request/GetRequest.java
@@ -0,0 +1,56 @@
+package com.lzy.okhttputils.request;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.util.Map;
+
+import okhttp3.Request;
+import okhttp3.RequestBody;
+
+/**
+ * ================================================
+ * 作 者:廖子尧
+ * 版 本:1.0
+ * 创建日期:2016/1/12
+ * 描 述:Get请求的实现类,注意需要传入本类的泛型
+ * 修订历史:
+ * ================================================
+ */
+public class GetRequest extends BaseRequest {
+
+ public GetRequest(String url) {
+ super(url);
+ }
+
+ @Override
+ public RequestBody generateRequestBody() {
+ return null;
+ }
+
+ @Override
+ public Request generateRequest(RequestBody requestBody) {
+ Request.Builder requestBuilder = new Request.Builder();
+ appendHeaders(requestBuilder);
+ url = createUrlFromParams(url, params.urlParamsMap);
+ return requestBuilder.get().url(url).tag(tag).build();
+ }
+
+ /** 将传递进来的参数拼接成 url */
+ private String createUrlFromParams(String url, Map params) {
+ try {
+ StringBuilder sb = new StringBuilder();
+ sb.append(url);
+ if (url.indexOf('&') > 0 || url.indexOf('?') > 0) sb.append("&");
+ else sb.append("?");
+ for (Map.Entry urlParams : params.entrySet()) {
+ String urlValue = URLEncoder.encode(urlParams.getValue(), "UTF-8");
+ sb.append(urlParams.getKey()).append("=").append(urlValue).append("&");
+ }
+ sb.deleteCharAt(sb.length() - 1);
+ return sb.toString();
+ } catch (UnsupportedEncodingException e) {
+ e.printStackTrace();
+ }
+ return url;
+ }
+}
\ No newline at end of file
diff --git a/library_okhttputils/src/main/java/com/lzy/okhttputils/request/PostRequest.java b/library_okhttputils/src/main/java/com/lzy/okhttputils/request/PostRequest.java
new file mode 100644
index 00000000..4e32b877
--- /dev/null
+++ b/library_okhttputils/src/main/java/com/lzy/okhttputils/request/PostRequest.java
@@ -0,0 +1,88 @@
+package com.lzy.okhttputils.request;
+
+import com.lzy.okhttputils.model.RequestParams;
+
+import java.io.File;
+import java.util.Map;
+
+import okhttp3.FormBody;
+import okhttp3.MediaType;
+import okhttp3.MultipartBody;
+import okhttp3.Request;
+import okhttp3.RequestBody;
+
+/**
+ * ================================================
+ * 作 者:廖子尧
+ * 版 本:1.0
+ * 创建日期:2016/1/12
+ * 描 述:Post请求的实现类,注意需要传入本类的泛型
+ * 修订历史:
+ * ================================================
+ */
+public class PostRequest extends BaseRequest {
+
+ public static final MediaType MEDIA_TYPE_PLAIN = MediaType.parse("text/plain;charset=utf-8");
+ public static final MediaType MEDIA_TYPE_JSON = MediaType.parse("application/json;charset=utf-8");
+ public static final MediaType MEDIA_TYPE_STREAM = MediaType.parse("application/octet-stream");
+
+ private String content;
+ private MediaType mediaType;
+
+ public PostRequest(String url) {
+ super(url);
+ }
+
+ /** 注意使用该方法上传字符串会清空实体中其他所有的参数,头信息不清除 */
+ public PostRequest content(String content) {
+ this.content = content;
+ return this;
+ }
+
+ public PostRequest mediaType(MediaType mediaType) {
+ this.mediaType = mediaType;
+ return this;
+ }
+
+ @Override
+ public RequestBody generateRequestBody() {
+ RequestBody requestBody;
+ if (content != null && mediaType != null) {
+ //post上传字符串数据
+ requestBody = RequestBody.create(mediaType, content);
+ } else {
+ if (params.fileParamsMap.isEmpty()) {
+ //表单提交,没有文件
+ FormBody.Builder bodyBuilder = new FormBody.Builder();
+ for (String key : params.urlParamsMap.keySet()) {
+ bodyBuilder.add(key, params.urlParamsMap.get(key));
+ }
+ requestBody = bodyBuilder.build();
+ } else {
+ //表单提交,有文件
+ MultipartBody.Builder multipartBodybuilder = new MultipartBody.Builder().setType(MultipartBody.FORM);
+ //拼接键值对
+ if (!params.urlParamsMap.isEmpty()) {
+ for (String key : params.urlParamsMap.keySet()) {
+ multipartBodybuilder.addFormDataPart(key, params.urlParamsMap.get(key));
+ }
+ }
+ //拼接文件
+ for (Map.Entry entry : params.fileParamsMap.entrySet()) {
+ String contentType = entry.getValue().contentType;
+ RequestBody fileBody = RequestBody.create(MediaType.parse(contentType), entry.getValue().file);
+ multipartBodybuilder.addFormDataPart(entry.getKey(), entry.getValue().fileName, fileBody);
+ }
+ requestBody = multipartBodybuilder.build();
+ }
+ }
+ return requestBody;
+ }
+
+ @Override
+ public Request generateRequest(RequestBody requestBody) {
+ Request.Builder requestBuilder = new Request.Builder();
+ appendHeaders(requestBuilder);
+ return requestBuilder.post(requestBody).url(url).tag(tag).build();
+ }
+}
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 00000000..a45efbd5
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1 @@
+include ':app', ':library_okhttputils'