package com.major.com.api;
import android.util.Log;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.charset.Charset;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import okhttp3.ConnectionSpec;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okhttp3.TlsVersion;
import okio.Buffer;
import okio.BufferedSource;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
/**
* Created by QuietLake on 2017/11/3.
*/
public class LocalClient {
? ? private static String BASE_URL= "";
? ? private static Retrofit retrofit= null;
? ? private static OkHttpClient okHttpClient= null;
? ? private static LocalClient localCilent= null;
? ? private LocalClient() {
}
? ? // 單例獲取
? ? public static LocalClient getInstance(){
? ? ? ? if (localCilent== null){
? ? ? ? ? ? synchronized (LocalClient.class){
? ? ? ? ? ? ? ? if (localCilent==null){
? ? ? ? ? ? ? ? ? ? localCilent= new LocalClient();
? ? ? ? ? ? ? ? }
}
}
? ? ? ? return localCilent;
? ? }
? ? /**
? ? * 重新設(shè)置baseUrl
? ? * @parambaseUrl 需要在調(diào)用create之前調(diào)用
? ? * @return當(dāng)前對象
? ? */
? ? public LocalClient setBaseUrl(String baseUrl) {
? ? ? ? if (baseUrl.endsWith(File.separator)) {
? ? ? ? ? ? BASE_URL= baseUrl;
? ? ? ? } else {
? ? ? ? ? ? BASE_URL= baseUrl + File.separator;
? ? ? ? }
? ? ? ? return localCilent;
? ? }
? ? //創(chuàng)建服務(wù)接口,不綁定生命周期
? ? public T create(Class cla){
? ? ? ? retrofit= getRetrofit();
? ? ? ? return retrofit.create(cla);
? ? }
? ? private static final int READ_TIMEOUT = 60;
? ? private static final int WRITE_TIMEOUT = 60;
? ? private static final int CONNECT_TIMEOUT = 20;
? ? //設(shè)置okhttpclient
? ? private OkHttpClient initOkHttpClient(){
? ? ? ? OkHttpClient.Builder builder= new OkHttpClient.Builder();
? ? ? ? builder.readTimeout(READ_TIMEOUT, TimeUnit.SECONDS);? ? ? //全局的讀取超時時間
? ? ? ? builder.writeTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS);? ? //全局的寫入超時時間
? ? ? ? builder.connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS);? //全局的連接超時時間
? ? ? ? OkSSLSocketFactory okSSLSocketFactory= null;
? ? ? ? try {
? ? ? ? ? ? okSSLSocketFactory= new OkSSLSocketFactory();
? ? ? ? } catch (KeyManagementException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? } catch (NoSuchAlgorithmException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? } catch (IOException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }
? ? ? ? builder.followSslRedirects(true)
? ? ? ? ? ? ? ? .retryOnConnectionFailure(true);
? ? ? ? builder.sslSocketFactory(new Tls12SocketFactory(okSSLSocketFactory), okSSLSocketFactory.trustManager);
? ? ? ? //配置https的域名匹配規(guī)則,詳細看demo的初始化介紹雷则,不需要就不要加入,使用不當(dāng)會導(dǎo)致https握手失敗
? ? ? ? builder.hostnameVerifier(new SafeHostnameVerifier());
? ? ? ? ConnectionSpec cs= new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
? ? ? ? ? ? ? ? .tlsVersions(TlsVersion.TLS_1_2)
? ? ? ? ? ? ? ? .build();
? ? ? ? List specList= new ArrayList<>();
? ? ? ? specList.add(cs);
? ? ? ? specList.add(ConnectionSpec.COMPATIBLE_TLS);
? ? ? ? specList.add(ConnectionSpec.CLEARTEXT);
? ? ? ? Interceptor loggingIntercept= new Interceptor() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public Response intercept(Interceptor.Chain chain) throws IOException {
? ? ? ? ? ? ? ? Request request= chain.request();
? ? ? ? ? ? ? ? Response response= chain.proceed(request);
? ? ? ? ? ? ? ? ResponseBody responseBody= response.body();
? ? ? ? ? ? ? ? BufferedSource source= responseBody.source();
? ? ? ? ? ? ? ? source.request(Long.MAX_VALUE); // Buffer the entire body.
? ? ? ? ? ? ? ? Buffer buffer= source.buffer();
? ? ? ? ? ? ? ? Charset UTF8= Charset.forName("UTF-8");
? ? ? ? ? ? ? ? Log.w("日志", "intercept: "+buffer.clone().readString(UTF8));
? ? ? ? ? ? ? ? Log.w("日志", "intercept: "+request.toString());
? ? ? ? ? ? ? ? return response;
? ? ? ? ? ? }
? ? ? ? };
? ? ? ? builder.addInterceptor(loggingIntercept);
? ? ? ? OkHttpClient httpClient= builder.connectionSpecs(specList)
? ? ? ? ? ? ? ? .addInterceptor(new Interceptor() {
? ? ? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? ? ? public Response intercept(Chain chain) throws IOException {
? ? ? ? ? ? ? ? ? ? ? ? Request request= chain.request()//獲取請求
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? .newBuilder()
//? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? .header("Accept-Encoding", "gzip") //header不支持中文裸影,不允許有特殊字符
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? .header("Accept-Language", "zh-CN,zh;q=0.8")
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? .header("Accept-Charset", "GBK,utf-8;q=0.7,*;q=0.3")
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? .addHeader("Connection", "close")
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? .build();
? ? ? ? ? ? ? ? ? ? ? ? Log.d("request",request.toString());
? ? ? ? ? ? ? ? ? ? ? ? return chain.proceed(request);
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }).build();
? ? ? ? return httpClient;
? ? }
? ? //設(shè)置Retrofit,不帶生命周期綁定的
? ? private Retrofit getRetrofit(){
? ? ? ? if (retrofit== null){
? ? ? ? ? ? if (okHttpClient== null){
? ? ? ? ? ? ? ? okHttpClient= getOkHttpCilent();
? ? ? ? ? ? }
? ? ? ? ? ? Gson gson= new GsonBuilder()
? ? ? ? ? ? ? ? ? ? .setLenient()
? ? ? ? ? ? ? ? ? ? .create();
? ? ? ? ? ? retrofit= new Retrofit.Builder()
? ? ? ? ? ? ? ? ? ? .baseUrl(BASE_URL)
? ? ? ? ? ? ? ? ? ? .client(okHttpClient)
? ? ? ? ? ? ? ? ? ? .addConverterFactory(GsonConverterFactory.create(gson))//json轉(zhuǎn)換器支持
? ? ? ? ? ? ? ? ? ? .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
? ? ? ? ? ? ? ? ? ? .build();
? ? ? ? }
? ? ? ? return retrofit;
? ? }
? ? /**
? ? * 提供方法單獨獲取okhttpCilent
? ? * @returnokhttpCilent
*/
? ? public OkHttpClient getOkHttpCilent(){
? ? ? ? if(okHttpClient== null){
? ? ? ? ? ? okHttpClient= initOkHttpClient();
? ? ? ? }
? ? ? ? return okHttpClient;
? ? }
? ? // 主機校驗
? ? private class SafeHostnameVerifier implements HostnameVerifier {
? ? ? ? @Override
? ? ? ? public boolean verify(String hostname, SSLSession session) {
? ? ? ? ? ? //驗證主機名是否匹配
? ? ? ? ? ? return true;
? ? ? ? }
}
? ? // 信任證書
? ? private class OkSSLSocketFactory extends SSLSocketFactory {
? ? ? ? SSLContext sslContext= SSLContext.getInstance("TLSv1.2");
? ? ? ? public X509TrustManager trustManager;
? ? ? ? public OkSSLSocketFactory() throws KeyManagementException, NoSuchAlgorithmException, IOException {
? ? ? ? ? ? super();
? ? ? ? ? ? // 使用預(yù)埋證書,校驗服務(wù)端證書(自簽名證書)
//? ? ? ? ? ? TrustManager[] trustManagers = prepareTrustManager(MtsApp.getCtx().getAssets().open("www.major.com.cer"));
//? ? ? ? ? ? trustManager = chooseTrustManager(trustManagers);
? ? ? ? ? ? // 信任所有證書
? ? ? ? ? ? trustManager= new X509TrustManager() {
? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? public X509Certificate[] getAcceptedIssuers() {
? ? ? ? ? ? ? ? ? ? return new X509Certificate[0];
? ? ? ? ? ? ? ? }
? ? ? ? ? ? };
? ? ? ? ? ? sslContext.init(null, new TrustManager[]{trustManager}, new SecureRandom());
? ? ? ? }
? ? ? ? @Override
? ? ? ? public String[] getDefaultCipherSuites() {
? ? ? ? ? ? return new String[0];
? ? ? ? }
? ? ? ? @Override
? ? ? ? public String[] getSupportedCipherSuites() {
? ? ? ? ? ? return new String[0];
? ? ? ? }
? ? ? ? @Override
? ? ? ? public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
? ? ? ? ? ? return sslContext.getSocketFactory().createSocket(s, host, port, autoClose);
? ? ? ? }
? ? ? ? @Override
? ? ? ? public Socket createSocket(String host, int port) throws IOException {
? ? ? ? ? ? return sslContext.getSocketFactory().createSocket(host, port);
? ? ? ? }
? ? ? ? @Override
? ? ? ? public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
? ? ? ? ? ? return sslContext.getSocketFactory().createSocket(host, port, localHost, localPort);
? ? ? ? }
? ? ? ? @Override
? ? ? ? public Socket createSocket(InetAddress host, int port) throws IOException {
? ? ? ? ? ? return sslContext.getSocketFactory().createSocket(host, port);
? ? ? ? }
? ? ? ? @Override
? ? ? ? public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
? ? ? ? ? ? return sslContext.getSocketFactory().createSocket(address, port, localAddress, localPort);
? ? ? ? }
}
? ? // 支持TLSv1.2 ON Android4.x設(shè)備的https請求
? ? public class Tls12SocketFactory extends SSLSocketFactory {
? ? ? ? private final String[] TLS_V12_ONLY= {"TLSv1.2"};
? ? ? ? final SSLSocketFactory delegate;
? ? ? ? public Tls12SocketFactory(SSLSocketFactory base) {
? ? ? ? ? ? this.delegate= base;
? ? ? ? }
? ? ? ? @Override
? ? ? ? public String[] getDefaultCipherSuites() {
? ? ? ? ? ? return delegate.getDefaultCipherSuites();
? ? ? ? }
? ? ? ? @Override
? ? ? ? public String[] getSupportedCipherSuites() {
? ? ? ? ? ? return delegate.getSupportedCipherSuites();
? ? ? ? }
? ? ? ? @Override
? ? ? ? public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
? ? ? ? ? ? return patch(delegate.createSocket(s, host, port, autoClose));
? ? ? ? }
? ? ? ? @Override
? ? ? ? public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
? ? ? ? ? ? return patch(delegate.createSocket(host, port));
? ? ? ? }
? ? ? ? @Override
? ? ? ? public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
? ? ? ? ? ? return patch(delegate.createSocket(host, port, localHost, localPort));
? ? ? ? }
? ? ? ? @Override
? ? ? ? public Socket createSocket(InetAddress host, int port) throws IOException {
? ? ? ? ? ? return patch(delegate.createSocket(host, port));
? ? ? ? }
? ? ? ? @Override
? ? ? ? public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
? ? ? ? ? ? return patch(delegate.createSocket(address, port, localAddress, localPort));
? ? ? ? }
? ? ? ? private Socket patch(Socket s) {
? ? ? ? ? ? if (s instanceof SSLSocket) {
? ? ? ? ? ? ? ? ((SSLSocket) s).setEnabledProtocols(TLS_V12_ONLY);
? ? ? ? ? ? }
? ? ? ? ? ? return s;
? ? ? ? }
}
}