package com.novelbook.android.netutils; import android.content.Context; import android.util.Log; import com.novelbook.android.MyApp; import com.novelbook.android.netapi.HttpApi; import com.novelbook.android.netapi.RandomHost; import com.novelbook.android.netapi.URLConstant; import com.novelbook.android.utils.CommonUtil; import com.novelbook.android.utils.FileUtils; import org.json.JSONException; import org.json.JSONObject; import java.io.File; import java.io.IOException; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.util.Locale; import java.util.concurrent.TimeUnit; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import io.reactivex.Observable; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.observers.DisposableObserver; import io.reactivex.schedulers.Schedulers; import okhttp3.Cache; import okhttp3.CacheControl; import okhttp3.Interceptor; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; import okhttp3.logging.HttpLoggingInterceptor; import retrofit2.Retrofit; import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; import retrofit2.converter.gson.GsonConverterFactory; import static com.novelbook.android.netapi.URLConstant.getRootUrl; //import static com.novelbook.android.netapi.URLConstant.newRootUrl; //import static com.novelbook.android.netutils.NetUtil.getHost; public class HttpMethods { public String TAG = "HttpMethods"; public static final String CACHE_NAME = "ZHUIKE"; //public static String BASE_URL = getBaseUrl(); private static final int DEFAULT_CONNECT_TIMEOUT = 10; private static final int DEFAULT_WRITE_TIMEOUT = 10; private static final int DEFAULT_READ_TIMEOUT = 10; public static String USERAGENT=""; public static String LOCALUSERAGENT=""; private Retrofit retrofit; private HttpApi httpApi; /** * 请求失败重连次数 */ private int RETRY_COUNT = 3; private OkHttpClient.Builder okHttpBuilder; private OkHttpClient okHttpClient; //构造方法私有 private HttpMethods() { okHttpClient = getClient(); retrofit = new Retrofit.Builder() .client(okHttpClient) .addConverterFactory(GsonConverterFactory.create())//json转换成JavaBean .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .baseUrl(getRootUrl()) .build(); httpApi = retrofit.create(HttpApi.class); } //在访问HttpMethods时创建单例 private static class SingletonHolder { private static final HttpMethods INSTANCE = new HttpMethods(); } //获取单例 public static HttpMethods getInstance(String keyUrl) { // SingletonHolder.INSTANCE.changeBaseUrl(NetUtil.getUrl(keyUrl)); try { SingletonHolder.INSTANCE.ChangeNoForward(keyUrl); } catch (JSONException e) { e.printStackTrace(); } return SingletonHolder.INSTANCE; } public void ChangeNoForward(String keyUrl) throws JSONException { // SingletonHolder.INSTANCE.changeBaseUrl(NetUtil.getUrl(keyUrl)); // RandomHost rh = new RandomHost( getHost() ,keyUrl); // okHttpBuilder.addInterceptor(new RetryInterceptor(rh)); // okHttpBuilder.addInterceptor(new RetryInterceptor()); okHttpBuilder.followRedirects(false); okHttpBuilder.retryOnConnectionFailure(false); retrofit = new Retrofit.Builder() .client(okHttpBuilder.build()) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .baseUrl(getRootUrl()) .build(); httpApi = retrofit.create(HttpApi.class); } //获取单例 public static HttpMethods getInstance() { return SingletonHolder.INSTANCE; } //获取单例 public static OkHttpClient getOkClient() { return SingletonHolder.INSTANCE.okHttpClient; } public static OkHttpClient getOkClient(int maxAge) { maxAgeForce =maxAge; return SingletonHolder.INSTANCE.okHttpClient; } /** * 获取retrofit * * @returnc */ public Retrofit getRetrofit() { return retrofit; } /*public void changeBaseUrl(String baseUrl) { okHttpBuilder.addInterceptor(new RetryInterceptor()); //okHttpBuilder.retryOnConnectionFailure(false); retrofit = new Retrofit.Builder() .client(okHttpBuilder.build()) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .baseUrl(baseUrl) .build(); httpApi = retrofit.create(HttpApi.class); }*/ /* public void changeBaseUrl() { changeBaseUrl(newBaseUrl()); }*/ /** * 获取httpService * * @return */ public HttpApi getHttpApi() { return httpApi; } public HttpApi getHttpApi(int maxAge) { maxAgeForce =maxAge; return httpApi; } private static final int maxAge = 60*60; //一小时; private static int maxAgeForce =0; //默认没有强制; private OkHttpClient getClient(){ //手动创建一个OkHttpClient并设置超时时间 okHttpBuilder = new OkHttpClient.Builder(); /** * 设置缓存 */ File cacheFile = new File(FileUtils.getDiskCacheDir(MyApp.applicationContext), CACHE_NAME); Cache cache = new Cache(cacheFile, 1024 * 1024 * 50); Log.d(TAG, "getClient: to set cach control"); // okHttpBuilder.cache(cache).addInterceptor(cacheInterceptor); okHttpBuilder.cache(cache) // .addNetworkInterceptor(REWRITE_RESPONSE_INTERCEPTOR) .addInterceptor(REWRITE_RESPONSE_INTERCEPTOR_OFFLINE); /** * 设置头信息 */ /* Interceptor headerInterceptor = new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Request originalRequest = chain.request(); *//* Request.Builder requestBuilder = originalRequest.newBuilder() .addHeader("Accept-Encoding", Locale.getDefault().toString()) // .addHeader("Host", "testapi.wujike.com.cn") .addHeader("Connection", "Keep-Alive") .addHeader("Device", "Android") .method(originalRequest.method(), originalRequest.body()); *//* Request.Builder requestBuilder = originalRequest.newBuilder() // .addHeader("Accept-Encoding", "gzip") // .addHeader("Accept-Encoding", Locale.getDefault().toString() ) // .addHeader("Accept", "application/json") // .addHeader("Content-Type", "application/json; charset=utf-8") // .addHeader("Device", "Android") .removeHeader("User-Agent").addHeader("User-Agent",USERAGENT) //加 随机agent .tag(NetUtil.currentRequestTag) .method(originalRequest.method(), originalRequest.body()); // requestBuilder.addHeader("Authorization", "Bearer" + BaseConstant.TOKEN);//添加请求头信息,服务器进行token有效性验证 Request request = requestBuilder.build(); return chain.proceed(request); } };*/ // okHttpBuilder.addInterceptor(headerInterceptor); // if (BuildConfig.DEBUG) { HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() { @Override public void log(String message) { Log.d(TAG, message); } }); loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); //设置 Debug Log 模式 okHttpBuilder.addInterceptor(loggingInterceptor); // okHttpBuilder.addInterceptor(new RetryInterceptor()); //设置编码 // EncodingInterceptor encodingInterceptor = new EncodingInterceptor("gbk"); // okHttpBuilder.addInterceptor(encodingInterceptor); // } /** * 设置超时和重新连接 */ okHttpBuilder.connectTimeout(DEFAULT_CONNECT_TIMEOUT, TimeUnit.SECONDS); okHttpBuilder.readTimeout(DEFAULT_WRITE_TIMEOUT, TimeUnit.SECONDS); okHttpBuilder.writeTimeout(DEFAULT_READ_TIMEOUT, TimeUnit.SECONDS); //错误重连 okHttpBuilder.retryOnConnectionFailure(true); okHttpBuilder.addInterceptor(new RetryInterceptor()); okHttpBuilder.hostnameVerifier(SSLSocketClient.getHostnameVerifier()); // Install the all-trusting trust manager final SSLContext sslContext; try { sslContext = SSLContext.getInstance("SSL"); sslContext.init(null, trustAllCerts, new java.security.SecureRandom()); // Create an ssl socket factory with our all-trusting manager final javax.net.ssl.SSLSocketFactory sslSocketFactory = sslContext .getSocketFactory(); // okHttpBuilder.sslSocketFactory(sslSocketFactory); /* okHttpBuilder.hostnameVerifier(new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { // TODO Auto-generated method stub return true; } });*/ } catch (NoSuchAlgorithmException | KeyManagementException e) { e.printStackTrace(); } return okHttpBuilder.build(); } /** * 设置订阅 和 所在的线程环境 */ public void toSubscribe(Observable o, DisposableObserver s) { o.subscribeOn(Schedulers.io()) .unsubscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .retry(RETRY_COUNT)//请求失败重连次数 .subscribe(s); } private final Interceptor REWRITE_RESPONSE_INTERCEPTOR = new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Response originalResponse = chain.proceed(chain.request()); String cacheControl = originalResponse.header("Cache-Control"); Log.d(TAG, String.format("intercept:url %s, get cache controle: %s, maxAgeForce %s",originalResponse.request().url(), cacheControl,maxAgeForce)); //int maxAge = 60*60; //一小时 if (maxAgeForce >0 ||cacheControl == null || cacheControl.contains("no-store") || cacheControl.contains("no-cache") || cacheControl.contains("must-revalidate") || cacheControl.contains("max-age=0")) { //目标网站禁用cache则设置为1小时 int age = maxAgeForce >0? maxAgeForce :maxAge; Log.d(TAG, "intercept: add maxAge: "+ age); return originalResponse.newBuilder() .removeHeader("Pragma") .header("Cache-Control", "public, max-age=" + age) .build(); } else { /* return originalResponse.newBuilder() .removeHeader("Pragma") .header("Cache-Control", "public, max-age=" + maxAge) .build();*/ return originalResponse; } } }; private final Interceptor REWRITE_RESPONSE_INTERCEPTOR_OFFLINE = new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); if (!NetUtil.isNetworkConnected()) { int maxStale = 60 * 60 * 24 * 28; request = request.newBuilder() .removeHeader("Pragma") .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale) .build(); } return chain.proceed(request); } }; final TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() { @Override public void checkClientTrusted( java.security.cert.X509Certificate[] chain, String authType) throws CertificateException { } @Override public void checkServerTrusted( java.security.cert.X509Certificate[] chain, String authType) throws CertificateException { } @Override public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } }}; }