Java tutorial
/******************************************************************************* * * Copyright (c) 2016 Mickael Gizthon . All rights reserved. Email:2013mzhou@gmail.com * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package com.commonslibrary.commons.net; import android.text.TextUtils; import com.commonslibrary.commons.config.SystemConfig; import com.commonslibrary.commons.handler.WeakHandlerNew; import com.commonslibrary.commons.utils.EncryptionUtils; import com.commonslibrary.commons.utils.LogUtils; import com.commonslibrary.commons.utils.StringUtils; import com.google.gson.Gson; import com.google.gson.JsonSyntaxException; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.net.FileNameMap; import java.net.URLConnection; import java.util.HashMap; import java.util.Locale; import java.util.Map; import java.util.concurrent.TimeUnit; import java.util.zip.GZIPOutputStream; import okhttp3.Cache; import okhttp3.Call; import okhttp3.Callback; import okhttp3.FormBody; import okhttp3.Interceptor; import okhttp3.MediaType; import okhttp3.MultipartBody; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; /** * date : 2015-11-30 10:41 * author : Mickaecle gizthon * description : http ,??json ?? */ public class DefaultOkHttpIml implements IRequestRemote { private WeakHandlerNew mHandler; private Object tag = DefaultOkHttpIml.class; private static DefaultOkHttpIml mInstance; private OkHttpClient mOkHttpClient; private DefaultOkHttpIml() { mHandler = new WeakHandlerNew(); File file = new File(SystemConfig.getSystemCacheDir()); Cache cache = new Cache(file, 10 * 1024 * 1024); mOkHttpClient = new OkHttpClient.Builder().connectTimeout(15, TimeUnit.SECONDS) .readTimeout(15, TimeUnit.SECONDS).writeTimeout(30, TimeUnit.SECONDS).cache(cache) // .addInterceptor(new GzipRequestInterceptor()) .addInterceptor(new LoggingInterceptor()).build(); } public static DefaultOkHttpIml getInstance() { if (null == mInstance) { synchronized (DefaultOkHttpIml.class) { if (null == mInstance) { mInstance = new DefaultOkHttpIml(); } } } return mInstance; } class LoggingInterceptor implements Interceptor { @Override public Response intercept(Interceptor.Chain chain) throws IOException { Request request = chain.request(); long t1 = System.nanoTime(); Response response = chain.proceed(request); long t2 = System.nanoTime(); LogUtils.i(String.format(Locale.getDefault(), "%s take %.1fms%s", response.request().url(), (t2 - t1) / 1e6d, ""/*response.headers()*/)); return response; } } @Override public <T> void doGet(String url, Map<String, Object> parameters, RequestCallBack<T> callBack) { if (callBack != null) { callBack.onStart(); } if (parameters == null) { parameters = new HashMap<>(); } String requestUrl = url + "?" + StringUtils.formatUrl(parameters); printLog(requestUrl, null); Request request = new Request.Builder().url(requestUrl).tag(tag).get().build(); execute(mOkHttpClient.newCall(request), null, callBack); } @Override public <T> void doPost(String url, Map<String, Object> parameters, RequestCallBack<T> callBack) { if (callBack != null) { callBack.onStart(); } FormBody.Builder builder = new FormBody.Builder(); addParams(url, parameters, builder); RequestBody body = builder.build(); Request request = new Request.Builder().url(url).post(body).tag(tag).build(); execute(mOkHttpClient.newCall(request), null, callBack); } @Deprecated public <T> void doPost(String url, String json, final RequestCallBack<T> callBack) { if (callBack != null) { callBack.onStart(); } final MediaType JSON = MediaType.parse("application/json; charset=utf-8"); RequestBody body = RequestBody.create(JSON, json); Request request = new Request.Builder().url(url).post(body).tag(tag).build(); OkHttpClient mOkHttpClient = new OkHttpClient.Builder().connectTimeout(15, TimeUnit.SECONDS) .readTimeout(15, TimeUnit.SECONDS).writeTimeout(30, TimeUnit.SECONDS).socketFactory(null).build(); execute(mOkHttpClient.newCall(request), null, callBack); } @Override public <T> void doUpload(String url, Map<String, Object> parameters, Map<String, File> files, final RequestCallBack<T> callBack) { if (callBack != null) { callBack.onStart(); } MultipartBody.Builder builder = new MultipartBody.Builder(); addParams(url, parameters, files, builder); RequestBody requestBody = builder.build(); Request request = new Request.Builder().url(url).post(new ProgressRequestBody(requestBody, callBack)) .tag(tag).build(); mOkHttpClient.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { sendFailResultCallback(null, ",???!", new Exception(""), callBack); } @Override public void onResponse(Call call, Response response) throws IOException { if (response == null || !response.isSuccessful()) { sendFailResultCallback(response, ",???!", new Exception(""), callBack); return; } sendSuccessResultCallback(response, response.body().string(), callBack); } }); } @Override public <T> void doDownLoad(String url, Map<String, Object> parameters, final RequestCallBack<T> callBack) { if (callBack != null) { callBack.onStart(); } if (parameters == null) { parameters = new HashMap<>(); } if (!parameters.containsKey("fileName")) { if (callBack != null) { callBack.onFailure("??", new IllegalArgumentException("")); } LogUtils.e("??"); return; } String md5 = ""; if (parameters.containsKey("md5")) { md5 = (String) parameters.get("md5"); if (md5.equals("null") || md5.trim().equals("")) { md5 = ""; LogUtils.e("md5???md5"); } } else { LogUtils.e("md5???md5"); } final String fileMd5 = md5; final String destFileName = StringUtils.optionValue(parameters, "fileName"); //clear ? parameters.remove("fileName"); String downLoadUrl = url + "?" + StringUtils.formatUrl(parameters); Request request = new Request.Builder().url(downLoadUrl).tag(tag).build(); final String errorMessage = ",?!"; mOkHttpClient.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { sendFailResultCallback(null, errorMessage, e, callBack); } @Override public void onResponse(Call call, Response response) throws IOException { if (response == null || !response.isSuccessful()) { sendFailResultCallback(response, errorMessage, new Exception(""), callBack); return; } saveFile(response, destFileName, callBack, fileMd5); } }); } /** * ?? * * @param callBack ? */ private <T> void execute(Call call, String errorMessage, final RequestCallBack<T> callBack) { if (TextUtils.isEmpty(errorMessage)) { errorMessage = "??,???!"; } try { final String finalErrorMessage = errorMessage; call.enqueue(new Callback() { @Override public void onFailure(Call call, final IOException e) { sendFailResultCallback(null, finalErrorMessage, e, callBack); } @Override public void onResponse(Call call, Response response) throws IOException { if (response == null || !response.isSuccessful()) { sendFailResultCallback(response, finalErrorMessage, new Exception(finalErrorMessage), callBack); return; } sendSuccessResultCallback(response, response.body().string(), callBack); } }); } catch (Exception e) { e.printStackTrace(); sendFailResultCallback(null, errorMessage, new Exception(errorMessage), callBack); } } /** * * * @param error ? * @param e * @param callBack ? */ public <T> void sendFailResultCallback(Response response, final String error, final Exception e, final RequestCallBack<T> callBack) { try { if (response == null) { LogUtils.i(e.toString()); } else { LogUtils.i(response.body().string()); } } catch (Exception e1) { e1.printStackTrace(); if (response != null) LogUtils.i(response.message()); } if (callBack == null) return; mHandler.post(new Runnable() { @Override public void run() { failed(error, e, callBack); } }); } private <T> void failed(String error, Exception e, RequestCallBack<T> callBack) { if (TextUtils.isEmpty(error)) { callBack.onFailure(",???!", new Exception("Unexpected code " + e)); } else { callBack.onFailure(error, new Exception("Unexpected code " + e)); } } /** * ? * * @param response ? * @param result * @param callBack ? */ public <T> void sendSuccessResultCallback(final Response response, final String result, final RequestCallBack<T> callBack) { LogUtils.i(result); if (callBack == null) return; mHandler.post(new Runnable() { @Override public void run() { success(response, result, callBack); } }); } @SuppressWarnings("unchecked") private <T> void success(Response response, String result, RequestCallBack<T> callBack) { callBack.onSuccess(response.body().charStream()); Type type = getSuperClassGenricType(callBack.getClass(), 0); if (type == String.class) { callBack.onSuccess((T) result); } else { try { T t = fromJson(result, type); if (t != null) { callBack.onSuccess(t); } else { callBack.onFailure("??", new JsonSyntaxException("??")); } } catch (Exception e) { e.printStackTrace(); callBack.onFailure("??", e); } } } @SuppressWarnings("unchecked") public <T> T fromJson(String json, Type typeOfT) throws JsonSyntaxException { T t; try { if (typeOfT == String.class) {//string return (T) json; } t = new Gson().fromJson(json, typeOfT); } catch (Exception e) { return null; } return t; } @SuppressWarnings("unchecked") public <T> T fromJson(Reader json, Type typeOfT) throws JsonSyntaxException { T t; try { if (typeOfT == String.class) {//string return (T) json; } t = new Gson().fromJson(json, typeOfT); } catch (Exception e) { return null; } return t; } /** * ? * * @param response ? * @param destFileName ?? * @param callBack * @throws IOException */ public <T> void saveFile(final Response response, String destFileName, final RequestCallBack<T> callBack, final String fileMd5) throws IOException { String destFileDir = SystemConfig.getSystemFileDir(); InputStream is = null; byte[] buf = new byte[2048]; int len; FileOutputStream fos = null; File file = null; long total = 0; try { is = response.body().byteStream(); total = response.body().contentLength(); long sum = 0; LogUtils.e("?:" + total); File dir = new File(destFileDir); if (!dir.exists()) { boolean createSuccess = dir.mkdirs(); LogUtils.i("?," + (createSuccess ? "?" : "")); } file = new File(dir, destFileName); if (file.exists()) { boolean deleteSuccess = file.delete(); LogUtils.i("?," + (deleteSuccess ? "?" : "")); } fos = new FileOutputStream(file); final long finalTotal = total; while ((len = is.read(buf)) != -1) { sum += len; fos.write(buf, 0, len); final long finalSum = sum; mHandler.post(new Runnable() { @Override public void run() { callBack.onProgress(finalSum, finalTotal, finalTotal == finalSum); } }); } fos.flush(); } catch (Exception e) { if (file != null) { boolean deleteSuccess = file.delete(); LogUtils.i("," + (deleteSuccess ? "?" : "")); } } finally { try { if (is != null) is.close(); } catch (Exception e) { e.printStackTrace(); } try { if (fos != null) fos.close(); } catch (Exception e) { e.printStackTrace(); } if (checkFileIsDownloadSuccess(fileMd5, file, total)) { sendSuccessResultCallback(response, file.getAbsolutePath(), callBack); } else { if (file != null) { boolean deleteSuccess = file.delete(); LogUtils.i("," + (deleteSuccess ? "?" : "")); } sendFailResultCallback(response, "!", new Exception(""), callBack); } } } private boolean checkFileIsDownloadSuccess(String fileMd5, File file, long total) throws IOException { return (file != null && file.exists()) && (total == file.length()) && (TextUtils.isEmpty(fileMd5) || (!TextUtils.isEmpty(fileMd5) && TextUtils.equals(EncryptionUtils.encryptMD5File2String(file), fileMd5))); } /** * ? * * @param url url * @param parameters ? */ private void printLog(String url, Map<String, Object> parameters) { if (parameters == null) { LogUtils.i(url); } else { String requestUrl = url + "?" + StringUtils.formatUrl(parameters); LogUtils.i(requestUrl); } } /** * * * @param path * @return */ private String guessMimeType(String path) { FileNameMap fileNameMap = URLConnection.getFileNameMap(); String contentTypeFor = fileNameMap.getContentTypeFor(path); if (contentTypeFor == null) { contentTypeFor = "application/octet-stream"; } return contentTypeFor; } /** * ? fileKey ?? * * @param url url * @param params ? * @param files * @param builder ? */ private void addParams(String url, Map<String, Object> params, Map<String, File> files, MultipartBody.Builder builder) { if (params == null || params.isEmpty()) { params = new HashMap<>(); } printLog(url, params);//?url for (Map.Entry<String, Object> entry : params.entrySet()) { builder.addFormDataPart(entry.getKey(), String.valueOf(entry.getValue())); } for (Map.Entry<String, File> entry : files.entrySet()) { File file = entry.getValue(); if (file.exists()) { builder.addFormDataPart(entry.getKey(), file.getName(), RequestBody.create(MediaType.parse(guessMimeType(file.getName())), file)); } } } /** * ? * * @param url url * @param params ? * @param builder ? */ private void addParams(String url, Map<String, Object> params, FormBody.Builder builder) { if (params == null || params.isEmpty()) { params = new HashMap<>(); } printLog(url, params);//?url for (String key : params.keySet()) { builder.add(key, String.valueOf(params.get(key))); } } /** * ?tag * * @param tag tagactivity? tag,activity?? */ public DefaultOkHttpIml setTag(Object tag) { this.tag = tag; return this; } /** * ?? * * @param tag ?tagactivity */ public void cancelTag(Object tag) { if (mOkHttpClient == null) { return; } for (Call call : mOkHttpClient.dispatcher().queuedCalls()) { if (tag.equals(call.request().tag())) { call.cancel(); } } for (Call call : mOkHttpClient.dispatcher().runningCalls()) { if (tag.equals(call.request().tag())) { call.cancel(); } } } public void cancelAllTag() { if (mOkHttpClient == null) { return; } for (Call call : mOkHttpClient.dispatcher().queuedCalls()) { call.cancel(); } for (Call call : mOkHttpClient.dispatcher().runningCalls()) { call.cancel(); } } /** * gzip; * gzip way to compress data; * * @param val ? * @return ?bytes? * @throws IOException */ private static byte[] gzip(byte[] val) throws IOException { ByteArrayOutputStream bos = new ByteArrayOutputStream(val.length); GZIPOutputStream gos = null; try { gos = new GZIPOutputStream(bos); gos.write(val, 0, val.length); gos.finish(); val = bos.toByteArray(); bos.flush(); } finally { if (gos != null) { //gos?finish??? } if (bos != null) { bos.close(); } } return val; } public static Type getSuperClassGenricType(final Class clazz, final int index) { // Class ??? void Type Type genType = clazz.getGenericSuperclass(); if (!(genType instanceof ParameterizedType)) { return Object.class; } //? Type Type[] params = ((ParameterizedType) genType).getActualTypeArguments(); if (index >= params.length || index < 0) { return Object.class; } if (!(params[index] instanceof Class)) { return Object.class; } return params[index]; } }