OkHttp升级记录

一直以来并没有升级项目的OkHttp版本,直到昨天上线遇到一个bug:http://stackoverflow.com/questions/27687907/android-os-networkonmainthreadexception-using-rxjava-on-android

按照stackOverflow的方法,可以在unsubscribe的时候可以这样:

subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread()).subscribe()

但是仍旧觉得不够优雅,于是继续探踪寻迹:

https://github.com/square/retrofit/issues/1328

最后大神说,已经在最新的okhttp中解决了,于是决定升级项目的okhttp版本。

okhttp3.x****和****okhttp2.x****的****api不同

  • okhttp3.x在架构上转换为使用Builder模式进行相关配置。

  • 好处:

可以在任何地方对OkHttpClient进行配置

mOkHttpClient = RetrofitUtil.setSSL().newBuilder()

上面setSSL中生成了一个OkhttpClient对象,而newBuilder()

public Builder newBuilder() {
   return new Builder(this);
 }

能直接获取到一个新的Builder对象,以方便进行配置的继续。

使用https进行访问时,默认信任所有的证书的书写方式

  • okHttp2.x:
/**
    * 设置https 访问的时候对所有证书都进行信任
    *
    * @throws Exception
    */
   protected void setSSL() throws Exception {
       SSLContext sc = SSLContext.getInstance("SSL");
       sc.init(null, new 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 null;
           }
       }}, new SecureRandom());
       mOkHttpClient.setSslSocketFactory(sc.getSocketFactory());
       mOkHttpClient.setHostnameVerifier(new HostnameVerifier() {
           @Override
           public boolean verify(String hostname, SSLSession session) {
               return true;
           }
       });
   }

  • okHttp3.x
/**
    * 设置https 访问的时候对所有证书都进行信任
    *
    * @throws Exception
    */
   public static OkHttpClient setSSL() throws Exception {
       final X509TrustManager 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 sslContext = SSLContext.getInstance("SSL");
       sslContext.init(null, new TrustManager[]{trustManager}, new SecureRandom());
       SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

       return new OkHttpClient.Builder()
               .sslSocketFactory(sslSocketFactory, trustManager)
               .hostnameVerifier(new HostnameVerifier() {
                   @Override
                   public boolean verify(String hostname, SSLSession session) {
                       return true;
                   }
               })
               .build();

   }

这里需要注意的是,okHttp中关于sslSocketFactory()有两个重载方法:

/**
    * Sets the socket factory used to secure HTTPS connections. If unset, the system default will
    * be used.
    *
    * @deprecated {@code SSLSocketFactory} does not expose its {@link X509TrustManager}, which is
    *     a field that OkHttp needs to build a clean certificate chain. This method instead must
    *     use reflection to extract the trust manager. Applications should prefer to call {@link
    *     #sslSocketFactory(SSLSocketFactory, X509TrustManager)}, which avoids such reflection.
    */
   public Builder sslSocketFactory(SSLSocketFactory sslSocketFactory) {
     if (sslSocketFactory == null) throw new NullPointerException("sslSocketFactory == null");
     X509TrustManager trustManager = Platform.get().trustManager(sslSocketFactory);
     if (trustManager == null) {
       throw new IllegalStateException("Unable to extract the trust manager on " + Platform.get()
           + ", sslSocketFactory is " + sslSocketFactory.getClass());
     }
     this.sslSocketFactory = sslSocketFactory;
     this.certificateChainCleaner = CertificateChainCleaner.get(trustManager);
     return this;
   }

但是该方法已经被官方deprecated了,原因在其推荐的重载方法中写的明白:

/**
    * Sets the socket factory and trust manager used to secure HTTPS connections. If unset, the
    * system defaults will be used.
    *
    * 

Most applications should not call this method, and instead use the system defaults. Those * classes include special optimizations that can be lost if the implementations are decorated. * *

If necessary, you can create and configure the defaults yourself with the following code: * *

   {@code
    *
    *   TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
    *       TrustManagerFactory.getDefaultAlgorithm());
    *   trustManagerFactory.init((KeyStore) null);
    *   TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
    *   if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
    *     throw new IllegalStateException("Unexpected default trust managers:"
    *         + Arrays.toString(trustManagers));
    *   }
    *   X509TrustManager trustManager = (X509TrustManager) trustManagers[0];
    *
    *   SSLContext sslContext = SSLContext.getInstance("TLS");
    *   sslContext.init(null, new TrustManager[] { trustManager }, null);
    *   SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
    *
    *   OkHttpClient client = new OkHttpClient.Builder()
    *       .sslSocketFactory(sslSocketFactory, trustManager);
    *       .build();
    * }
*/ public Builder sslSocketFactory( SSLSocketFactory sslSocketFactory, X509TrustManager trustManager) { if (sslSocketFactory == null) throw new NullPointerException("sslSocketFactory == null"); if (trustManager == null) throw new NullPointerException("trustManager == null"); this.sslSocketFactory = sslSocketFactory; this.certificateChainCleaner = CertificateChainCleaner.get(trustManager); return this; }

混淆

1、okhttp3.x相较于okhttp2.x,proguard需要作出相应的修改:

https://github.com/square/okhttp/issues/2230

这里大神给了如何对okhttp3.x进行混淆

2、这里出现了一下小插曲,项目中更新proguard时,将com.squareup.okhttp.**这段也删了,但是项目中有用到picasso,而picasso用到了okhttp,所以需要保持其中的okhttp不被混淆。

你可能感兴趣的:(OkHttp升级记录)