OPPO R9s 无法加载https的图片

作者: 蝴蝶之梦天使 | 来源:发表于2018-06-08 12:57 被阅读51次
    OPPO手机

    OPPO 手机Android6.0系统
    Glide 4.0+ 版本
    加载HTTPS的图片显示空白

    图片显示空白

    图片是保存在阿里云服务上,所以图片提供的地址都是https://开头的。整个测试过程一切正常,也准备发版本。突然在OPPO手机上,图片不显示,空白一片。赶紧连接上手机进行DEBUG,可以看到一堆错误。有错误信息就好处理了。错误提示如下:


    证书错误
    javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
            at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:328)
            at com.android.okhttp.internal.http.SocketConnector.connectTls(SocketConnector.java:103)
            at com.android.okhttp.Connection.connect(Connection.java:143)
            ...
            at aoo.run(SourceFile:446)
         Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
            at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:324)
            at com.android.org.conscrypt.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:225)
            ...
    com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.connect(DelegatingHttpsURLConnection.java:89) 
            at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:25) 
            at alm.a(SourceFile:104) 
            ...
            at java.lang.Thread.run(Thread.java:818) 
            at aoo.run(SourceFile:446) 
         Caused by: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
            at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:324) 
            at 
    ...
    com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.connect(DelegatingHttpsURLConnection.java:89) 
            at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:25) 
    ...
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) 
            at java.lang.Thread.run(Thread.java:818) 
            at aoo.run(SourceFile:446) 
    

    然后进行google错误信息“Trust anchor for certification path not found.”,能够搜到的答案就是让你设置自定义证书。可我并不想设置证书。 再看时间都是2016年或2017年的,使用glide还在2.0+时代,将哪些解决方法用到工程里,都是报错的。

    解决

    1. 添加第三方库

    api "com.github.bumptech.glide:okhttp3-integration:4.7.1"
    annotationProcessor 'com.github.bumptech.glide:compiler:4.7.1'
    

    我使用的glide 4.7.1版本,所有添加这对应的版本也是4.7.1. 其中添加com.github.bumptech.glide:compiler是因为,不添加就会报错误

    Failed to find GeneratedAppGlideModule. You should include an annotationProcessor compile dependency on com.github.bumptech.glide:compiler in your application and a @GlideModule annotated AppGlideModule implementation or LibraryGlideModules will be silently ignored
    

    记得同步项目下。

    2. 添加OkHttpAppGlideModule类

    类的内容:

    import android.content.Context;
    
    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;
    
    import okhttp3.OkHttpClient;
    
    @GlideModule
    public class OkHttpAppGlideModule extends AppGlideModule {
    
        public void registerComponents(Context context, Registry registry) {
            OkHttpClient client = UnsafeOkHttpClient.getUnsafeOkHttpClient();
            registry.replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(client));
        }
    }
    
    

    3.添加UnsafeOkHttpClient类

    类的内容:

    import java.security.cert.CertificateException;
    import java.util.concurrent.TimeUnit;
    
    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 okhttp3.OkHttpClient;
    
    public class UnsafeOkHttpClient {
    
        public static OkHttpClient getUnsafeOkHttpClient() {
            try {
                // Create a trust manager that does not validate certificate chains
                final TrustManager[] trustAllCerts = new TrustManager[]{
                        new X509TrustManager() {
                            @Override
                            public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
                            }
    
                            @Override
                            public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
                            }
    
                            @Override
                            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                                return new java.security.cert.X509Certificate[]{};
                            }
                        }
                };
    
                // Install the all-trusting trust manager
                final SSLContext sslContext = SSLContext.getInstance("SSL");
                sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
    
                // Create an ssl socket factory with our all-trusting manager
                final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
    
                OkHttpClient.Builder builder = new OkHttpClient.Builder();
                builder.sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0]);
                builder.hostnameVerifier(new HostnameVerifier() {
                    @Override
                    public boolean verify(String hostname, SSLSession session) {
                        return true;
                    }
                });
    
                builder.connectTimeout(20, TimeUnit.SECONDS);
                builder.readTimeout(20,TimeUnit.SECONDS);
    
                OkHttpClient okHttpClient = builder.build();
                return okHttpClient;
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }
    
    

    4. 申明GlideMudle

    在AndroidManifest.xml中添加申明:

            <meta-data
                android:name="com.****.OkHttpAppGlideModule"
                android:value="AppGlideModule" />
    
    

    其中的路径需要修改为自己项目的路径。

    成功

    再次运行时,成功显示图片。

    小插曲

    1. 图片的缓存问题。

    当把图片的https://路径修改为http://进行访问成功,再次进行https://路径访问,尽然成功显示了。一开始以为是问题解决了,但是当手机重启后,https://路径还是无法显示图片。

    2. 一直是失败,显示图片空白。

    可在添加了一次重复的混淆-keep public class * implements com.bumptech.glide.module.GlideModule. 尽然可以了。 然后把这个混淆删除后,也是成功的。 那么原因只能是:glide的缓存问题。当多次访问同一个https://失败后,glide将此https://路径设置为无效路径,再次进行访问时直接就显示失败了。然后修改了下混淆,glide又进行访问了。(作者的猜测,没有进行源码阅读,有不对的地方请指正。)

    参考文章: https://blog.csdn.net/u010232308/article/details/78085057

    // END 2018-6-8 小小的开心吧

    相关文章

      网友评论

      本文标题:OPPO R9s 无法加载https的图片

      本文链接:https://www.haomeiwen.com/subject/eyvosftx.html