解決Glide加載自簽名的https圖片時(shí)失敗問(wèn)題

前言


在android應(yīng)用中,Glide這個(gè)工具庫(kù)想必大家已經(jīng)很熟悉了,它主要是用來(lái)加載和顯示圖片的篙螟。最近項(xiàng)目服務(wù)器url由http切換到https众旗,所有使用Glide加載網(wǎng)絡(luò)圖片的地方都失敗听皿,原因是Glide默認(rèn)是http請(qǐng)求查辩。

也就是說(shuō)羔挡,想用Gilde加載自簽名的https圖片买优,必須修改Glide加載圖片的方法券犁。本文通過(guò)使用okhttp信任自簽名證書(shū)的方法來(lái)修改GlideModule來(lái)實(shí)現(xiàn)轮锥。

1.下載com.github.bumptech.glide:okhttp.integration:1.4.0@aar

可以通過(guò)在buile.gradle中添加依賴com.github.bumptech.glide:okhttp-integration:1.4.0@aar下載,下載后的文件在 “C盤(pán)/用戶/用戶名/.gradle/caches/modules-2/files-2.1下面”(下載完后記得把依賴刪掉)

2.拷貝其中三個(gè)類OkHttpGlideModule击蹲,OkHttpUrlLoader纽绍,OkHttpStreamFetcher到工程中


OkHttpGlideModule.class


import android.content.Context;
import com.bumptech.glide.Glide;
import com.bumptech.glide.GlideBuilder;
import com.bumptech.glide.load.model.GlideUrl;
import com.bumptech.glide.module.GlideModule;
import com.changhong.park.pda.utils.HTTPSUtils;

import java.io.InputStream;

/**
* A {@link GlideModule} implementation to replace Glide's default
* {@link java.net.HttpURLConnection} based {@link com.bumptech.glide.load.model.ModelLoader} with an OkHttp based
* {@link com.bumptech.glide.load.model.ModelLoader}.
*
* <p>
*     If you're using gradle, you can include this module simply by depending on the aar, the module will be merged
*     in by manifest merger. For other build systems or for more more information, see
*     {@link GlideModule}.
* </p>
*/
public class OkHttpGlideModule implements GlideModule {
  @Override
  public void applyOptions(Context context, GlideBuilder builder) {
      // Do nothing.
  }

  @Override
  public void registerComponents(Context context, Glide glide) {
      glide.register(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(new OKHttpUtils(context).getHttpClient()));
  }
}

OkHttpStreamFetcher.class


import com.bumptech.glide.Priority;
import com.bumptech.glide.load.data.DataFetcher;
import com.bumptech.glide.load.model.GlideUrl;
import com.bumptech.glide.util.ContentLengthInputStream;

import java.io.IOException;
import java.io.InputStream;
import java.util.Map;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;


/**
 * Fetches an {@link InputStream} using the okhttp library.
 */
public class OkHttpStreamFetcher implements DataFetcher<InputStream> {
    private final OkHttpClient client;
    private final GlideUrl url;
    private InputStream stream;
    private ResponseBody responseBody;

    public OkHttpStreamFetcher(OkHttpClient client, GlideUrl url) {
        this.client = client;
        this.url = url;
    }

    @Override
    public InputStream loadData(Priority priority) throws Exception {
        Request.Builder requestBuilder = new Request.Builder()
                .url(url.toStringUrl());

        for (Map.Entry<String, String> headerEntry : url.getHeaders().entrySet()) {
            String key = headerEntry.getKey();
            requestBuilder.addHeader(key, headerEntry.getValue());
        }

        Request request = requestBuilder.build();

        Response response = client.newCall(request).execute();
        responseBody = response.body();
        if (!response.isSuccessful()) {
            throw new IOException("Request failed with code: " + response.code());
        }

        long contentLength = responseBody.contentLength();
        stream = ContentLengthInputStream.obtain(responseBody.byteStream(), contentLength);
        return stream;
    }

    @Override
    public void cleanup() {
        if (stream != null) {
            try {
                stream.close();
            } catch (IOException e) {
                // Ignored
            }
        }
        if (responseBody != null) {
            responseBody.close();
        }
    }

    @Override
    public String getId() {
        return url.getCacheKey();
    }

    @Override
    public void cancel() {
        // TODO: call cancel on the client when this method is called on a background thread. See #257
    }
}

OkHttpUrlLoader.class


import com.bumptech.glide.Priority;
import com.bumptech.glide.load.data.DataFetcher;
import com.bumptech.glide.load.model.GlideUrl;
import com.bumptech.glide.util.ContentLengthInputStream;

import java.io.IOException;
import java.io.InputStream;
import java.util.Map;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;


/**
 * Fetches an {@link InputStream} using the okhttp library.
 */
public class OkHttpStreamFetcher implements DataFetcher<InputStream> {
    private final OkHttpClient client;
    private final GlideUrl url;
    private InputStream stream;
    private ResponseBody responseBody;

    public OkHttpStreamFetcher(OkHttpClient client, GlideUrl url) {
        this.client = client;
        this.url = url;
    }

    @Override
    public InputStream loadData(Priority priority) throws Exception {
        Request.Builder requestBuilder = new Request.Builder()
                .url(url.toStringUrl());

        for (Map.Entry<String, String> headerEntry : url.getHeaders().entrySet()) {
            String key = headerEntry.getKey();
            requestBuilder.addHeader(key, headerEntry.getValue());
        }

        Request request = requestBuilder.build();

        Response response = client.newCall(request).execute();
        responseBody = response.body();
        if (!response.isSuccessful()) {
            throw new IOException("Request failed with code: " + response.code());
        }

        long contentLength = responseBody.contentLength();
        stream = ContentLengthInputStream.obtain(responseBody.byteStream(), contentLength);
        return stream;
    }

    @Override
    public void cleanup() {
        if (stream != null) {
            try {
                stream.close();
            } catch (IOException e) {
                // Ignored
            }
        }
        if (responseBody != null) {
            responseBody.close();
        }
    }

    @Override
    public String getId() {
        return url.getCacheKey();
    }

    @Override
    public void cancel() {
        // TODO: call cancel on the client when this method is called on a background thread. See #257
    }
}

3.添加信任自定義證書(shū)工具類蕾久,下面貼出重要方法


    public SSLSocketFactory getSSLSocketFactory(X509TrustManager trustManager) {
        SSLSocketFactory sslSocketFactory;
        try {

            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, new TrustManager[]{trustManager}, null);
            sslSocketFactory = sslContext.getSocketFactory();

        } catch (GeneralSecurityException e) {
            throw new RuntimeException(e);
        }
        return sslSocketFactory;

    }
   private X509TrustManager getX509TrustManager()
            throws GeneralSecurityException {
        InputStream inputStream = null;
        try {
            inputStream = mContext.getAssets().open("server.cer"); 
        }catch (IOException e){
            e.printStackTrace();
        }

        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
        Collection<? extends Certificate> certificates = certificateFactory.generateCertificates(inputStream);
        if (certificates.isEmpty()) {
            throw new IllegalArgumentException("expected non-empty set of trusted certificates");
        }

        // Put the certificates a key store.
        char[] password = "test".toCharArray(); // Any password will work.
        KeyStore keyStore = newEmptyKeyStore(password);
        int index = 0;
        for (Certificate certificate : certificates) {
            String certificateAlias = Integer.toString(index++);
            keyStore.setCertificateEntry(certificateAlias, certificate);
        }

        // Use it to build an X509 trust manager.
        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(
                KeyManagerFactory.getDefaultAlgorithm());
        keyManagerFactory.init(keyStore, password);
        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
                TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init(keyStore);
        TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
        if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
            throw new IllegalStateException("Unexpected default trust managers:"
                    + Arrays.toString(trustManagers));
        }
        return (X509TrustManager) trustManagers[0];
    }

4.builde.gradule 添加依賴 com.github.bumptech.glide:glide:3.7.0,在Androidmanifest中配置GlideModule(用自定義的替換默認(rèn)的)


 compile 'com.github.bumptech.glide:glide:3.7.0'
 <meta-data
            android:name="com.test.http.OkHttpGlideModule"
            android:value="GlideModule"/>

5.加載圖片(加載失敗時(shí)重試)


 Glide.with(PhotoActivity.this)
                .load(url)
                .asBitmap()
                .listener(new RequestListener<String, Bitmap>() {
                    @Override
                    public boolean onException(Exception e, String model, Target<Bitmap> target, boolean isFirstResource) {
                       //加載失敗時(shí)重試
                        handler.postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                loadPhoto(photoView,url);
                            }
                        }, 5000);
                        return false;
                    }

                    @Override
                    public boolean onResourceReady(Bitmap resource, String model, Target<Bitmap> target, boolean isFromMemoryCache, boolean isFirstResource) {
                        return false;
                    }
                })
                .into(photoView);

最近項(xiàng)目中正好遇到這個(gè)問(wèn)題拌夏,記錄下來(lái)跟大家分享僧著,歡迎交流履因!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市盹愚,隨后出現(xiàn)的幾起案子栅迄,更是在濱河造成了極大的恐慌,老刑警劉巖皆怕,帶你破解...
    沈念sama閱讀 212,029評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件毅舆,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡愈腾,警方通過(guò)查閱死者的電腦和手機(jī)朗兵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,395評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)顶滩,“玉大人余掖,你說(shuō)我怎么就攤上這事〗嘎常” “怎么了盐欺?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,570評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)仅醇。 經(jīng)常有香客問(wèn)我冗美,道長(zhǎng),這世上最難降的妖魔是什么析二? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,535評(píng)論 1 284
  • 正文 為了忘掉前任粉洼,我火速辦了婚禮,結(jié)果婚禮上叶摄,老公的妹妹穿的比我還像新娘属韧。我一直安慰自己,他們只是感情好蛤吓,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,650評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布宵喂。 她就那樣靜靜地躺著,像睡著了一般会傲。 火紅的嫁衣襯著肌膚如雪锅棕。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,850評(píng)論 1 290
  • 那天淌山,我揣著相機(jī)與錄音裸燎,去河邊找鬼。 笑死泼疑,一個(gè)胖子當(dāng)著我的面吹牛德绿,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 39,006評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼脆炎,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼梅猿!你這毒婦竟也來(lái)了氓辣?” 一聲冷哼從身側(cè)響起秒裕,我...
    開(kāi)封第一講書(shū)人閱讀 37,747評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎钞啸,沒(méi)想到半個(gè)月后几蜻,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,207評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡体斩,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,536評(píng)論 2 327
  • 正文 我和宋清朗相戀三年梭稚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片絮吵。...
    茶點(diǎn)故事閱讀 38,683評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡弧烤,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蹬敲,到底是詐尸還是另有隱情暇昂,我是刑警寧澤,帶...
    沈念sama閱讀 34,342評(píng)論 4 330
  • 正文 年R本政府宣布伴嗡,位于F島的核電站急波,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏瘪校。R本人自食惡果不足惜澄暮,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,964評(píng)論 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望阱扬。 院中可真熱鬧泣懊,春花似錦、人聲如沸麻惶。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,772評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)用踩。三九已至渠退,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間脐彩,已是汗流浹背碎乃。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,004評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留惠奸,地道東北人梅誓。 一個(gè)月前我還...
    沈念sama閱讀 46,401評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親梗掰。 傳聞我的和親對(duì)象是個(gè)殘疾皇子嵌言,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,566評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容

  • 一、簡(jiǎn)介 在泰國(guó)舉行的谷歌開(kāi)發(fā)者論壇上及穗,谷歌為我們介紹了一個(gè)名叫Glide的圖片加載庫(kù)摧茴,作者是bumptech。這...
    天天大保建閱讀 7,459評(píng)論 2 28
  • Glide筆記 一埂陆、簡(jiǎn)介 在泰國(guó)舉行的谷歌開(kāi)發(fā)者論壇上苛白,谷歌為我們介紹了一個(gè)名叫Glide的圖片加載庫(kù),作者是bu...
    AndroidMaster閱讀 3,883評(píng)論 0 27
  • 7.1 壓縮圖片 一焚虱、基礎(chǔ)知識(shí) 1购裙、圖片的格式 jpg:最常見(jiàn)的圖片格式。色彩還原度比較好鹃栽,可以支持適當(dāng)壓縮后保持...
    AndroidMaster閱讀 2,496評(píng)論 0 13
  • 學(xué)習(xí)來(lái)源:郭霖大師博客地址 1躏率、圖片加載框架挺多,如Volley民鼓、Glide薇芝、Picasso、Fresco摹察、本次是...
    子謙寶寶閱讀 1,749評(píng)論 0 6
  • 第一次見(jiàn)他是18年前的深秋恩掷,他穿著黃色的夾克,和當(dāng)時(shí)的季節(jié)很配供嚎』颇铮可那時(shí)候的他眼里只有她...... “...
    瘋子707閱讀 566評(píng)論 0 0