在Android中,加载图片最好用的就是Glide了,至于为什么呢,不多说,Google都推荐了,Google的很多官方Demo都是用Glide加载网络图片的。
Glide使用步骤如下:
implementation 'com.github.bumptech.glide:glide:4.11.0'
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Glide.with(this)
.load("http://192.168.1.250:8080/cat.jpg")
.centerCrop()
.placeholder(R.mipmap.ic_launcher)
.into(imageView)
}
}
OK,就是这么简单就完成了图片的加载,上面Glide中各函数的功能大家如果不懂的话去官网看一下就知道了,这里不多解释。本篇文章主要是讲加载https的图片。
使用上面的代码去加载一些网络上的https图片一般是没有问题的,没问题是因为网络上的https使用的证书一般是权威机构颁发的证书,而这些权威机构的根证书在手机出厂时就已经预装在手机里面了,所以我们加载https图片时会自动完成认证,但是突然有一天,我们公司的网络请求也改成了Https了,用的是自定义证书,并不是权威机构颁发的,所以这个时候加载公司的https的图片时就加载失败了,异常如下:
Glide: Load failed for https://192.168.1.250:8080/cat.jpg with size [1080x162]
class com.bumptech.glide.load.engine.GlideException: Failed to load resource
There was 1 cause:
javax.net.ssl.SSLHandshakeException(java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.)
看到CertPathValidatorException(证书路径验证器异常)不用我多说应该也知道是什么原理导致的了。
在服务器改成https请求的时候,我是先处理的普通请求,比如登录请求,这些请求都是使用OkHttp实现的,所以我开始时找OkHttp配置自定义证书的实现,而且也实现了,所以这里只讲怎么设置让Glide使用OkHttp来下载图片,而且是使用我们配置过的(即设置好自定证书的)OkHttp对象来下载图片。当然,如果你用的是其它的网络请求框架,如果该网络请求框架也被Glide支持的话,则也可以参考我这个文章来集成的。
刚开始我百度找答案,答案是有,但是写的很不清楚,于是只能靠自己了,去Glide官网找答案,这里记录一下,希望对大家有所帮助,集成OkHttp步骤如下:
// OkHttp网络请求库
implementation 'com.squareup.okhttp3:okhttp:4.8.1'
// Glide图片加载库
implementation 'com.github.bumptech.glide:glide:4.11.0'
// Glide集成OkHttp时需要使用的库
implementation "com.github.bumptech.glide:okhttp3-integration:4.11.0"
// Glide需要处理注解时的依赖库,用于处理注解并生成java类
kapt 'com.github.bumptech.glide:compiler:4.11.0'
上面的依赖中使用到了注解处理,所以还需要添加注解处理器插件,添加在gradle文件的最前面的位置:
apply plugin: 'kotlin-kapt'
@GlideModule
class OkHttpGlideModule : AppGlideModule() {
override fun registerComponents(context: Context, glide: Glide, registry: Registry) {
val okHttpClient = OkHttpClient.Builder().build()
registry.replace(GlideUrl::class.java, InputStream::class.java, OkHttpUrlLoader.Factory(okHttpClient))
}
}
网络百度的那些答案这一步是各种覆盖各种类,其实根本就不用,我们自己创建一个OkHttp对象传给Glide即可,这样Glide就会使用我们创建的OkHttp对象来下载图片了,对于具体怎么配置OkHttp可以接受自定义证书,请看这篇文章,为了完整性,这里简单实现一个忽略所有证书的实现代码如下:
@GlideModule
class OkHttpGlideModule : AppGlideModule() {
override fun registerComponents(context: Context, glide: Glide, registry: Registry) {
val builder = OkHttpClient.Builder()
builder.sslSocketFactory(sSLSocketFactory, trustManager)
val okHttpClient = builder.build()
registry.replace(GlideUrl::class.java, InputStream::class.java, OkHttpUrlLoader.Factory(okHttpClient))
}
/** 获取一个SSLSocketFactory */
val sSLSocketFactory: SSLSocketFactory
get() = try {
val sslContext = SSLContext.getInstance("SSL")
sslContext.init(null, arrayOf(trustManager), SecureRandom())
sslContext.socketFactory
} catch (e: Exception) {
throw RuntimeException(e)
}
/** 获取一个忽略证书的X509TrustManager */
val trustManager: X509TrustManager
get() = object : X509TrustManager {
override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) { }
override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) { }
override fun getAcceptedIssuers(): Array<X509Certificate> { return arrayOf() }
}
}
最后还有一步,第2步创建的类中使用了注解,Glide会自动生成一个GlideApp的类,这个类就是使用了我们配置的OkHttp的,所以在下载图片时,我们要使用GlideApp来代替之前的Glide类,如下:
GlideApp.with(this)
.load("https://192.168.1.250:8080/cat.jpg")
.centerCrop()
.placeholder(R.mipmap.ic_launcher)
.into(imageView)