1. 程式人生 > >android-Picasso請求https載入網路圖片不能顯示的解決方案

android-Picasso請求https載入網路圖片不能顯示的解決方案

Picasso載入https的圖片載入不出來的解決方案

  • 最近專案中有需求–要顯示https連結的圖片,但是配置好路徑後原生的Picasso死活沒法加載出圖片,最後在網上找到了如下的解決辦法

  • 確認依賴

    • compile 'com.squareup.okhttp3:okhttp:3.9.0'
    • compile 'com.squareup.picasso:picasso:2.5.2'
    1. 自定義類 ImageDownLoader 實現 com.squareup.picasso.Downloader 程式碼如下:

          package china.test.helper;
          import android.net.Uri;             
          import com.squareup.picasso.Downloader;
          import com.squareup.picasso.NetworkPolicy;  
          import java.io.IOException;             
          import okhttp3.Cache;
          import okhttp3.CacheControl;
          import okhttp3.OkHttpClient;
          import okhttp3.ResponseBody;
          import okhttp3.Request;
      
      
          /**
           * Created by benchengzhou on 2017/11/14  13:52 .
           * 作者郵箱: 
      [email protected]
      * 功能描述: 重寫picasso的下載器,修改使用okhttp3作為下載 * 類 名: ImageDownLoader * 備 注: */ public class ImageDownLoader implements Downloader { /* OkHttpClient client = new OkHttpClient.Builder() .protocols(Collections.singletonList(Protocol.HTTP_1_1)) .build();*/ private OkHttpClient client= null; public ImageDownLoader(OkHttpClient okHttpClient) { this.client = okHttpClient; } @Override public Response load(Uri uri, int networkPolicy) throws IOException { CacheControl cacheControl = null; if (networkPolicy != 0) { if (NetworkPolicy.isOfflineOnly(networkPolicy)) { cacheControl = CacheControl.FORCE_CACHE; } else { CacheControl.Builder builder = new CacheControl.Builder(); if (!NetworkPolicy.shouldReadFromDiskCache(networkPolicy)) { builder.noCache(); } if (!NetworkPolicy.shouldWriteToDiskCache(networkPolicy)) { builder.noStore(); } cacheControl = builder.build(); } } Request.Builder builder = new Request.Builder().url(uri.toString()); if (cacheControl != null) { builder.cacheControl(cacheControl); } okhttp3.Response response = client.newCall(builder.build()).execute(); int responseCode = response.code(); if (responseCode >= 300) { response.body().close(); throw new ResponseException(responseCode + " " + response.message(), networkPolicy, responseCode); } boolean fromCache = response.cacheResponse() != null; ResponseBody responseBody = response.body(); return new Response(responseBody.byteStream(), fromCache, responseBody.contentLength()); } @Override public void shutdown() { Cache cache = client.cache(); if (cache != null) { try { cache.close(); } catch (IOException ignored) { } } } }
      • 2.解決 Picasso 初始化配置使用我們自定義的 Downloader ,在application中新增初始化配置程式碼

        /**
         *  初始化picasso使用okhttp作為網路請求框架
         */
        private void initPicasso() {
        
            Picasso.setSingletonInstance(new Picasso.Builder(this).
            downloader(new ImageDownLoader(getSOkHttpClient())).loggingEnabled(true)
            .build());
        
        }
        
      • 3.getSOkHttpClient() 中的程式碼

        /**
         * 建立全域性OkHttpClient物件
         * <p>
         * OkHttpClient 用於管理所有的請求,內部支援併發,
         * 所以我們不必每次請求都建立一個 OkHttpClient 物件,這是非常耗費資源的。接下來就是建立一個 Request 物件了
         *
         * @return
         */
        public static OkHttpClient getSOkHttpClient() {
            //建立okhttp的請求物件 參考地址  http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0106/2275.html
        
            if (sOkHttpClient == null) {
                sOkHttpClient =
                        new OkHttpClient.Builder()
                                .readTimeout(20000, TimeUnit.SECONDS)//設定讀取超時時間
                                .writeTimeout(20000, TimeUnit.SECONDS)//設定寫的超時時間
                                .connectTimeout(20000, TimeUnit.SECONDS)//設定連線超時時間
                                .sslSocketFactory(createSSLSocketFactory())    //新增信任所有證書
                                .hostnameVerifier(new HostnameVerifier() {     //信任規則全部信任
                                    @Override
                                    public boolean verify(String hostname, SSLSession session) {
                                        return true;
                                    }
                                })
                                .build();
            }
            return sOkHttpClient;
        }
        
      • 3.1這裡的 OkHttpClient 物件全域性使用一個,同時可以作為專案的okhttp的網路請求的OkHttpClient的封裝,我的專案裡面的網路請求也是使用的這一個

      • 其中

            .sslSocketFactory(createSSLSocketFactory())    //新增信任所有證書
                                    .hostnameVerifier(new HostnameVerifier() {     //信任規則全部信任
                                        @Override
                                        public boolean verify(String hostname, SSLSession session) {
                                            return true;
                                        }
                                    })
        
      • 是增加的對https協議的支援

      • 4.createSSLSocketFactory 方法中增加 信任規則

           /**
             * 測試環境https新增全部信任
             * okhttp的配置
             *
             * @return
             */
            private static SSLSocketFactory createSSLSocketFactory() {
                SSLSocketFactory ssfFactory = null;
        
                try {
                    SSLContext sc = SSLContext.getInstance("TLS");
                    sc.init(null, new TrustManager[]{new TrustAllCerts()}, new SecureRandom());
        
                    ssfFactory = sc.getSocketFactory();
                } catch (Exception e) {
                }
        
                return ssfFactory;
            }
        
      • 5.建立一個行的檔案 TrustAllCerts.java 配置對應的信任規則

        package china.test.helper;
        
        import java.security.cert.X509Certificate;
        
        import javax.net.ssl.X509TrustManager;
        
        /**
         * Created by benchengzhou on 2017/11/13  10:09 .
         * 作者郵箱: [email protected]
         * 功能描述: 測試環境新增https全部信任
         * 類    名: TrustAllCerts
         * 備    注:
         */
        
        
        public class TrustAllCerts implements X509TrustManager {
            @Override
            public void checkClientTrusted(X509Certificate[] chain, String authType) {}
        
            @Override
            public void checkServerTrusted(X509Certificate[] chain, String authType) {}
        
            @Override
            public X509Certificate[] getAcceptedIssuers() {return new X509Certificate[0];}
        }
        
  • OK!剩下的就是慢慢的使用吧go

好了問題解決了放過來看一下原理:

查閱文件我們發現OKhttp是可以對下載器進行設定的,也就是提供給我們了指定或自定義下載器的可能,文件有這句話

downloader(Downloader downloader) :
容許使用自定義的下載器,可以用okhttp或者volley,必須實現Downloader介面。

正是因為如此,我們可以如下實現

    picassoBuilder.downloader(new ImageDownLoader(client));

指定使用OKhttp作為網路下載器,故而問題轉接成為只要可以實現okhttp可以實現 https的請求我們的Picasso就可以完成載入https的圖片了 如果想要看OKhttp實現https請求請移步我的部落格

  • 當然我現在專案的build配置如下,: compile ‘com.squareup.okhttp3:okhttp:3.5.0’ compile ‘com.squareup.picasso:picasso:2.3.2’