欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android使用Glide加载https链接的图片不显示的原因

程序员文章站 2022-08-09 11:34:54
平时我们使用Glide加载http网址的图片的时候,图片可以正常加载出来,但是如果服务器端加上了安全认证,当加载自签名的https图片的时候就会报如下错误(证书路径验证异常)。 我们如果不修改Glide的代码的话,是会出现 javax.net.ssl.SSLHandshakeException: j ......

平时我们使用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换成你们自己的。

最后附上一张图片

 Android使用Glide加载https链接的图片不显示的原因

Android使用Glide加载https链接的图片不显示的原因

参考文章:https://blog.csdn.net/u014752325/article/details/73217577

     https://blog.csdn.net/u014752325/article/details/73185351