转眼间谷歌的Glide图片加载库都4.8.0了,时间过得真的太快。今天解决两个问题(第1个是独立问题,第2个依赖第1个): 1、Glide网络加载库(其默认为原生的API实现)集成为OkHttp,众所周知OkHttp可以帮助我们更方便地玩转网络请求; 2、让Glide可以加载https前缀的图片链接(如果你的域名证书是服务端自己瞎签的,没有认证,就过不了安全检查,表现为你用Chrome浏览器打开这个链接会提示不安全的红色警告)。
问题1:集成OkHttp 一般来说我们项目一开始会分别使用Glide和OkHttp库,没特殊需求时没想到过它们还要结合。 首先,假设我们已经有OkHttpClient的初始化逻辑了:
1 2 3 4 5 6 7 8 public static OkHttpClient getHttpClient () { OkHttpClient.Builder builder = new OkHttpClient .Builder() .connectTimeout(10 , TimeUnit.SECONDS) .addInterceptor(...) .cache(...); return builder.build(); }
然后我们配置一下必要的依赖库,在app的gradle文件中:
1 2 3 4 5 6 7 8 dependencies { implementation 'com.squareup.okhttp3:okhttp:3.11.0' ... implementation 'com.github.bumptech.glide:glide:4.8.0' implementation 'com.github.bumptech.glide:okhttp3-integration:4.8.0' // 新增 implementation 'com.github.bumptech.glide:annotations:4.8.0' // 新增 annotationProcessor 'com.github.bumptech.glide:compiler:4.8.0' }
由于我还使用了Retrofit配合OKHttp,这里就省略了哈,主要关注Glide相关的库(集成和注解 )。 如果用到了混淆,记得配置一下Proguard:
1 2 3 4 5 6 7 # For Glide ----> -keep public class * implements com.bumptech.glide.module.GlideModule -keep public class * extends com.bumptech.glide.module.AppGlideModule -keep public enum com.bumptech.glide.load.ImageHeaderParser$** { **[] $VALUES; public *; }
配置完了记得Sync一下项目,接着新建一个AppGlideModule的子类,用我们现有的HttpClient来替换Glide的,很简单,这里把import的包也指明,方便对照:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import android.content.Context;import android.support.annotation.NonNull;import com.bumptech.glide.Glide;import com.bumptech.glide.Registry;import com.bumptech.glide.annotation.GlideModule;import com.bumptech.glide.integration.okhttp3.OkHttpUrlLoader;import com.bumptech.glide.load.model.GlideUrl;import com.bumptech.glide.module .AppGlideModule;import java.io.InputStream;@GlideModule public final class HttpGlideModule extends AppGlideModule { @Override public void registerComponents (@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) { registry.replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader .Factory(XXX.getHttpClient())); } }
OK,现在再用Glide去加载图片,就是走的OkHttpClient了,可以添加log拦截器去看,这里就不赘述了。
问题2:忽略安全证书加载https图片 主要是通过给OkHttp增加SSL和验证器配置来实现忽略安全认证,即便是自己签名证书的https域名也可以加载了。 先定义好SSLSocketFactory和HostnameVerifier:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 private static SSLSocketFactory getSSLSocketFactory () { try { SSLContext sslContext = SSLContext.getInstance("SSL" ); sslContext.init(null , getTrustManagers(), new SecureRandom ()); return sslContext.getSocketFactory(); } catch (Exception e) { throw new RuntimeException (e); } } private static TrustManager[] getTrustManagers() { return new TrustManager []{new X509TrustManager () { @Override public void checkClientTrusted (X509Certificate[] chain, String authType) { } @Override public void checkServerTrusted (X509Certificate[] chain, String authType) { } @Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate []{}; } }}; } private static HostnameVerifier getHostnameVerifier () { return new HostnameVerifier () { @Override public boolean verify (String hostname, SSLSession session) { return true ; } }; }
最后回到最开始的初始化OkHttp代码,添加:
1 2 3 4 5 6 7 8 public static OkHttpClient getHttpClient () { OkHttpClient.Builder builder = new OkHttpClient .Builder() ... .sslSocketFactory(getSSLSocketFactory()) .hostnameVerifier(getHostnameVerifier()); return builder.build(); }
大功告成了,虽然这样不是很安全的做法,但对于一些小项目或者测试环境来说,这能避免证书带来的无法加载网络图片的额外问题。