OkHttp升级记录

作者: 美乃滋酱啊 | 来源:发表于2016-07-28 19:11 被阅读3843次

    一直以来并没有升级项目的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.
        *
        * <p>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.
        *
        * <p>If necessary, you can create and configure the defaults yourself with the following code:
        *
        * <pre>   {@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();
        * }</pre>
        */
       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升级记录

        本文链接:https://www.haomeiwen.com/subject/vswajttx.html