Android使用Glide加载https链接的图片不显示的原因
平时我们使用glide加载http网址的图片的时候,图片可以正常加载出来,但是如果服务器端加上了安全认证,当加载自签名的https图片的时候就会报如下错误(证书路径验证异常)。
我们如果不修改glide的代码的话,是会出现
javax.net.ssl.sslhandshakeexception: java.security.cert.certpathvalidatorexception: trust anchor for certification path not found.这个异常,导致图片加载不出来。
okhttp我们使用ssl来信任的所有证书,但是glide使用的自己的网络请求来加载的图片,也就是说,想要用glide访问https图片,就必须替换掉glide原始加载图片的方法,使其同样做到信任所有证书。
所以需要修改glide的okhttpglidemodule.class okhttpstreamfetcher.class okhttpurlloader.class这三个类,
okhttpglidemodule.java
package com.example.androidtest.https;
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.example.androidtest.sslsocketclient;
import java.io.inputstream;
import okhttp3.okhttpclient;
public class okhttpglidemodule implements glidemodule {
@override
public void applyoptions(context context, glidebuilder builder) {
}
@override
public void registercomponents(context context, glide glide) {
okhttpclient mhttpclient = new okhttpclient().newbuilder()
.sslsocketfactory(sslsocketclient.getsslsocketfactory())
.hostnameverifier(sslsocketclient.gethostnameverifier())
.build();
glide.register(glideurl.class, inputstream.class, new okhttpurlloader.factory(mhttpclient));
}
}
okhttpstreamfetcher.java
/**
* <p>title: okhttpstreamfetcher.java</p>
* <p>description: </p>
* <p>copyright: copyright (c) 2017</p>
* <p>company: www.baidudu.com</p>
* @author tsj
* @date 2018 10 18
* @version 1.0
*/
package com.example.androidtest.https;
/**
* <p>title: okhttpstreamfetcher</p>
* <p>description: </p>
* @author tsj
* @date 2018 10 18
*/
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;
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) {
}
}
if (responsebody != null) {
responsebody.close();
}
}
@override
public string getid() {
return url.getcachekey();
}
@override
public void cancel() {
}
}
okhttpurlloader.java
/**
* <p>title: okhttpurlloader.java</p>
* <p>description: </p>
* <p>copyright: copyright (c) 2017</p>
* <p>company: www.baidudu.com</p>
* @author tsj
* @date 2018 10 18
* @version 1.0
*/
package com.example.androidtest.https;
import android.content.context;
import com.bumptech.glide.load.data.datafetcher;
import com.bumptech.glide.load.model.genericloaderfactory;
import com.bumptech.glide.load.model.glideurl;
import com.bumptech.glide.load.model.modelloader;
import com.bumptech.glide.load.model.modelloaderfactory;
import java.io.inputstream;
import okhttp3.okhttpclient;
public class okhttpurlloader implements modelloader<glideurl, inputstream> {
public static class factory implements modelloaderfactory<glideurl, inputstream> {
private static volatile okhttpclient internalclient;
private okhttpclient client;
private static okhttpclient getinternalclient() {
if (internalclient == null) {
synchronized (factory.class) {
if (internalclient == null) {
internalclient = new okhttpclient();
}
}
}
return internalclient;
}
public factory() {
this(getinternalclient());
}
public factory(okhttpclient client) {
this.client = client;
}
@override
public modelloader<glideurl, inputstream> build(context context, genericloaderfactory factories) {
return new okhttpurlloader(client);
}
@override
public void teardown() {
}
}
private final okhttpclient client;
public okhttpurlloader(okhttpclient client) {
this.client = client;
}
@override
public datafetcher<inputstream> getresourcefetcher(glideurl model, int width, int height) {
return new okhttpstreamfetcher(client, model);
}
}
还有一个是okhttp信任证书。
sslsocketclient.java
/**
* <p>title: sslsocketclient.java</p>
* <p>description: </p>
* <p>copyright: copyright (c) 2017</p>
* <p>company: www.baidudu.com</p>
* @author tsj
* @date 2018 10 18
* @version 1.0
*/
package com.example.androidtest;
import java.security.securerandom;
import java.security.cert.certificateexception;
import java.security.cert.x509certificate;
import javax.net.ssl.hostnameverifier;
import javax.net.ssl.sslcontext;
import javax.net.ssl.sslsession;
import javax.net.ssl.sslsocketfactory;
import javax.net.ssl.trustmanager;
import javax.net.ssl.x509trustmanager;
import android.util.log;
/**
* <p>title: sslsocketclient</p>
* <p>description: </p>
* @author tsj
* @date 2018 10 18
*/
public class sslsocketclient {
//获取这个sslsocketfactory
public static sslsocketfactory getsslsocketfactory() {
try {
sslcontext sslcontext = sslcontext.getinstance("ssl");
sslcontext.init(null, gettrustmanager(), new securerandom());
return sslcontext.getsocketfactory();
} catch (exception e) {
throw new runtimeexception(e);
}
}
//获取trustmanager
private static trustmanager[] gettrustmanager() {
trustmanager[] trustallcerts = new trustmanager[]{
new x509trustmanager() {
@override
public x509certificate[] getacceptedissuers() {
return new x509certificate[]{};
}
@override
public void checkclienttrusted(x509certificate[] chain,
string authtype) throws certificateexception {
}
@override
public void checkservertrusted(x509certificate[] chain,
string authtype) throws certificateexception {
}
}
};
return trustallcerts;
}
//获取hostnameverifier
public static hostnameverifier gethostnameverifier() {
hostnameverifier hostnameverifier = new hostnameverifier() {
@override
public boolean verify(string hostname, sslsession session) {
// todo auto-generated method stub
return true;
}
};
return hostnameverifier;
}
}
在androidmanifest.xml里面配置
<meta-data
android:name="com.example.androidtest.https.okhttpglidemodule"
android:value="glidemodule" />
然后activity是这样调用的
package com.example.androidtest;
import android.app.activity;
import android.os.bundle;
import android.view.view;
import android.view.view.onclicklistener;
import android.widget.button;
import android.widget.imageview;
import com.bumptech.glide.glide;
public class mainactivity extends activity {
private imageview imageview;
private button mbutton;
private string url="https://image.baidu.com/search/detail?ct=503316480&z=0&ipn=d&word=%e7%99%be%e5%ba%a6%e5%9b%be%e7%89%87&step_word=&hs=0&pn=5&spn=0&di=94952282390&pi=0&rn=1&tn=baiduimagedetail&is=0%2c0&istype=0&ie=utf-8&oe=utf-8&in=&cl=2&lm=-1&st=undefined&cs=99355280%2c609648180&os=1002106675%2c4110592367&simid=2009090768%2c841445828&adpicid=0&lpn=0&ln=1902&fr=&fmq=1539876892817_r&fm=&ic=undefined&s=undefined&se=&sme=&tab=0&width=undefined&height=undefined&face=undefined&ist=&jit=&cg=&bdtype=13&oriquery=&objurl=http%3a%2f%2fimgsrc.baidu.com%2fimgad%2fpic%2fitem%2fd01373f082025aaf5d53a7e3f0edab64034f1ab1.jpg&fromurl=ippr_z2c%24qazdh3fazdh3frwtxtg_z%26e3bv54azdh3fri5p5v5ry6t2ipazdh3f8nl9cmma9&gsm=0&rpstart=0&rpnum=0&islist=&querylist=";
@override
protected void oncreate(bundle savedinstancestate) {
super.oncreate(savedinstancestate);
setcontentview(r.layout.activity_main);
imageview = (imageview) findviewbyid(r.id.image);
mbutton = (button) findviewbyid(r.id.button);
mbutton.setonclicklistener(new onclicklistener() {
@override
public void onclick(view v) {
glide.with(getapplicationcontext()).load(url)
.placeholder(r.drawable.ic_launcher)
.error(r.drawable.ic_launcher)
.into(imageview);
}
});
}
}
这里的url是测试用的,建议将url换成你们自己的。
最后附上一张图片
参考文章:https://blog.csdn.net/u014752325/article/details/73217577
https://blog.csdn.net/u014752325/article/details/73185351
上一篇: 中娅之光什么手机能玩 适配手机型号一览表
下一篇: 下拉框连动的小例子(.htm版)