Picasso加载https的图片加载不出来的解决方案
- 最近项目中有需求–要显示https链接的图片,但是配置好路径后原生的Picasso死活没法加载出图片,最后在网上找到了如下的解决办法
- 确认依赖
compile 'com.squareup.okhttp3:okhttp:3.9.0'
compile 'com.squareup.picasso:picasso:2.5.2'
- 自定义类
ImageDownLoader
实现com.squareup.picasso.Downloader
代码如下:
package china.test.helper;
import android.net.Uri;
import com.squareup.picasso.Downloader;
import com.squareup.picasso.NetworkPolicy;
import java.io.IOException;
import okhttp3.Cache;
import okhttp3.CacheControl;
import okhttp3.OkHttpClient;
import okhttp3.ResponseBody;
import okhttp3.Request;
/**
* Created by benchengzhou on 2017/11/14 13:52 .
* 作者邮箱: mappstore@163.com
* 功能描述: 重写picasso的下载器,修改使用okhttp3作为下载
* 类 名: ImageDownLoader
* 备 注:
*/
public class ImageDownLoader implements Downloader {
/* OkHttpClient client = new OkHttpClient.Builder()
.protocols(Collections.singletonList(Protocol.HTTP_1_1))
.build();*/
private OkHttpClient client= null;
public ImageDownLoader(OkHttpClient okHttpClient) {
this.client = okHttpClient;
}
@Override
public Response load(Uri uri, int networkPolicy) throws IOException {
CacheControl cacheControl = null;
if (networkPolicy != 0) {
if (NetworkPolicy.isOfflineOnly(networkPolicy)) {
cacheControl = CacheControl.FORCE_CACHE;
} else {
CacheControl.Builder builder = new CacheControl.Builder();
if (!NetworkPolicy.shouldReadFromDiskCache(networkPolicy)) {
builder.noCache();
}
if (!NetworkPolicy.shouldWriteToDiskCache(networkPolicy)) {
builder.noStore();
}
cacheControl = builder.build();
}
}
Request.Builder builder = new Request.Builder().url(uri.toString());
if (cacheControl != null) {
builder.cacheControl(cacheControl);
}
okhttp3.Response response = client.newCall(builder.build()).execute();
int responseCode = response.code();
if (responseCode >= 300) {
response.body().close();
throw new ResponseException(responseCode + " " + response.message(), networkPolicy,
responseCode);
}
boolean fromCache = response.cacheResponse() != null;
ResponseBody responseBody = response.body();
return new Response(responseBody.byteStream(), fromCache, responseBody.contentLength());
}
@Override
public void shutdown() {
Cache cache = client.cache();
if (cache != null) {
try {
cache.close();
} catch (IOException ignored) {
}
}
}
}
- 2.解决 Picasso 初始化配置使用我们自定义的 Downloader ,在application中添加初始化配置代码
/**
* 初始化picasso使用okhttp作为网络请求框架
*/
private void initPicasso() {
Picasso.setSingletonInstance(new Picasso.Builder(this).
downloader(new ImageDownLoader(getSOkHttpClient())).loggingEnabled(true)
.build());
}
- 3.
getSOkHttpClient()
中的代码
/**
* 创建全局OkHttpClient对象
* <p>
* OkHttpClient 用于管理所有的请求,内部支持并发,
* 所以我们不必每次请求都创建一个 OkHttpClient 对象,这是非常耗费资源的。接下来就是创建一个 Request 对象了
*
* @return
*/
public static OkHttpClient getSOkHttpClient() {
//创建okhttp的请求对象 参考地址 http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0106/2275.html
if (sOkHttpClient == null) {
sOkHttpClient =
new OkHttpClient.Builder()
.readTimeout(20000, TimeUnit.SECONDS)//设置读取超时时间
.writeTimeout(20000, TimeUnit.SECONDS)//设置写的超时时间
.connectTimeout(20000, TimeUnit.SECONDS)//设置连接超时时间
.sslSocketFactory(createSSLSocketFactory()) //添加信任所有证书
.hostnameVerifier(new HostnameVerifier() { //信任规则全部信任
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
})
.build();
}
return sOkHttpClient;
}
- 3.1这里的 OkHttpClient 对象全局使用一个,同时可以作为项目的okhttp的网络请求的OkHttpClient的封装,我的项目里面的网络请求也是使用的这一个
- 其中
.sslSocketFactory(createSSLSocketFactory()) //添加信任所有证书
.hostnameVerifier(new HostnameVerifier() { //信任规则全部信任
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
})
- 是增加的对https协议的支持
- 4.
createSSLSocketFactory
方法中增加 信任规则
/**
* 测试环境https添加全部信任
* okhttp的配置
*
* @return
*/
private static SSLSocketFactory createSSLSocketFactory() {
SSLSocketFactory ssfFactory = null;
try {
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, new TrustManager[]{new TrustAllCerts()}, new SecureRandom());
ssfFactory = sc.getSocketFactory();
} catch (Exception e) {
}
return ssfFactory;
}
- 5.创建一个行的文件 TrustAllCerts.java 配置对应的信任规则
package china.test.helper;
import java.security.cert.X509Certificate;
import javax.net.ssl.X509TrustManager;
/**
* Created by benchengzhou on 2017/11/13 10:09 .
* 作者邮箱: mappstore@163.com
* 功能描述: 测试环境添加https全部信任
* 类 名: TrustAllCerts
* 备 注:
*/
public class TrustAllCerts implements X509TrustManager {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) {}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {}
@Override
public X509Certificate[] getAcceptedIssuers() {return new X509Certificate[0];}
}
- OK!剩下的就是慢慢的使用吧go
好了问题解决了放过来看一下原理:
查阅文档我们发现OKhttp是可以对下载器进行设置的,也就是提供给我们了指定或自定义下载器的可能,文档有这句话
downloader(Downloader downloader) :
容许使用自定义的下载器,可以用okhttp或者volley,必须实现Downloader接口。
这是文章的链接 有兴趣的同学可以研究一下,这里不做深究
正是因为如此,我们可以如下实现
picassoBuilder.downloader(new ImageDownLoader(client));
指定使用OKhttp作为网络下载器,故而问题转接成为只要可以实现okhttp可以实现 https的请求我们的Picasso就可以完成加载https的图片了
如果想要看OKhttp实现https请求请移步我的博客
- 当然我现在项目的build配置如下,:
compile ‘com.squareup.okhttp3:okhttp:3.5.0’
compile ‘com.squareup.picasso:picasso:2.3.2’