package com.anthony.library.data; import android.content.Context; import android.util.Log; import com.anthony.library.BaseDataRepository; import com.anthony.library.data.net.TrustManager; import com.anthony.library.utils.AppUtils; import java.io.File; import java.io.IOException; import java.lang.reflect.Field; import java.util.HashMap; import java.util.concurrent.TimeUnit; import okhttp3.Cache; import okhttp3.CacheControl; import okhttp3.Interceptor; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; import retrofit2.Retrofit; import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory; import retrofit2.converter.gson.GsonConverterFactory; /** * Created by Anthony on 2016/7/8. * Class Note: * entrance class to access network with {@link Retrofit} * used only by{@link BaseDataRepository} is recommended * <p> * 使用retrofit进行网络访问的入口类,推荐只在{@link BaseDataRepository}中使用 */ public class HttpHelper { private static final int DEFAULT_TIMEOUT = 30; private HashMap<String, Object> mServiceMap; private Context mContext; // private Gson gson = new GsonBuilder().setLenient().create(); public HttpHelper(Context context) { //Map used to store RetrofitService mServiceMap = new HashMap<>(); this.mContext = context; } @SuppressWarnings("unchecked") public <S> S getApi(Class<S> serviceClass) { if (mServiceMap.containsKey(serviceClass.getName())) { return (S) mServiceMap.get(serviceClass.getName()); } else { Object obj = createApi(serviceClass); mServiceMap.put(serviceClass.getName(), obj); return (S) obj; } } @SuppressWarnings("unchecked") public <S> S getApi(Class<S> serviceClass, OkHttpClient client) { if (mServiceMap.containsKey(serviceClass.getName())) { return (S) mServiceMap.get(serviceClass.getName()); } else { Object obj = createApi(serviceClass, client); mServiceMap.put(serviceClass.getName(), obj); return (S) obj; } } private <S> S createApi(Class<S> serviceClass) { // private static final HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY); //custom OkHttp OkHttpClient.Builder httpClient = new OkHttpClient.Builder(); //time our httpClient.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS); httpClient.writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS); httpClient.readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS); //cache File httpCacheDirectory = new File(mContext.getCacheDir(), "OkHttpCache"); httpClient.cache(new Cache(httpCacheDirectory, 50 * 1024 * 1024)); //Interceptor httpClient.addNetworkInterceptor(new LogInterceptor()); httpClient.addInterceptor(new CacheControlInterceptor()); //retry when fail httpClient.retryOnConnectionFailure(true); //todo SSL证书 httpClient.sslSocketFactory(TrustManager.getUnsafeOkHttpClient()); httpClient.hostnameVerifier(org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); return createApi(serviceClass, httpClient.build()); } private <S> S createApi(Class<S> serviceClass, OkHttpClient client) { String end_point = ""; try { Field field1 = serviceClass.getField("end_point"); end_point = (String) field1.get(serviceClass); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.getMessage(); e.printStackTrace(); } Retrofit retrofit = new Retrofit.Builder() .baseUrl(end_point) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .client(client) .build(); return retrofit.create(serviceClass); } private class LogInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); long t1 = System.nanoTime(); Log.i("HttpHelper", String.format("Sending request %s on %s%n%s", request.url(), chain.connection(), request.headers())); Response response = chain.proceed(request); long t2 = System.nanoTime(); Log.i("HttpHelper", String.format("Received response for %s in %.1fms%n%s", response.request().url(), (t2 - t1) / 1e6d, response.headers())); return response; // log Response Body // if(BuildConfig.DEBUG) { // String responseBody = response.body().string(); // Log.v("HttpHelper", String.format("Received response for %s in %.1fms%n%s%n%s", // response.request().url(), (t2 - t1) / 1e6d, response.headers(), responseBody)); // return response.newBuilder() // .body(ResponseBody.create(response.body().contentType(), responseBody)) // .build(); // } else { // Log.v("HttpHelper", String.format("Received response for %s in %.1fms%n%s", // response.request().url(), (t2 - t1) / 1e6d, response.headers())); // return response; // } } } private class CacheControlInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); if (!AppUtils.isNetworkConnected(mContext)) { request = request.newBuilder() .cacheControl(CacheControl.FORCE_CACHE) .build(); } Response response = chain.proceed(request); if (AppUtils.isNetworkConnected(mContext)) { int maxAge = 60 * 60; // read from cache for 1 minute response.newBuilder() .removeHeader("Pragma") .header("Cache-Control", "public, max-age=" + maxAge) .build(); } else { int maxStale = 60 * 60 * 24 * 28; // tolerate 4-weeks stale response.newBuilder() .removeHeader("Pragma") .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale) .build(); } return response; } } }