使用 picasso android 库加载图像形式 URL 时出现 HTTP 504 错误

Error HTTP 504 When load image form URL with picasso android library

我想使用 picasso android 库从 URL 加载图像并显示它以供查看,但我只在 android 7.0 Nougat 中遇到错误。

图片的URL使用HTTPS。在我的另一个具有相同图像 URL 的项目中,如果我在真实设备 7.0 牛轧糖中 运行 我没有收到错误,但如果我在模拟器 7.0 牛轧糖中 运行 仍然出错。

我尝试使用其他 URL 来自不同域的图像,但我也没有收到错误。

我该如何解决?

Picasso.get().load("My_URL_Image")
                .resize(200,200)
                .centerInside()
                .placeholder(R.drawable.ic_default)
                .error(R.drawable.ic_default)
                .into(holder.imageView, object : Callback{
                    override fun onSuccess() {}

                    override fun onError(e: Exception?) {
                        e?.printStackTrace()
                    }

                })
W/System.err: com.squareup.picasso.NetworkRequestHandler$ResponseException: HTTP 504
W/System.err:     at com.squareup.picasso.NetworkRequestHandler.load(NetworkRequestHandler.java:51)
W/System.err:     at com.squareup.picasso.BitmapHunter.hunt(BitmapHunter.java:219)
W/System.err:     at com.squareup.picasso.BitmapHunter.run(BitmapHunter.java:175)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:428)
        at java.util.concurrent.FutureTask.run(FutureTask.java:237)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
        at java.lang.Thread.run(Thread.java:761)
        at com.squareup.picasso.Utils$PicassoThread.run(Utils.java:354)

504 is Timeout Error code means that a server that is upstream to one that you (the client ) are connecting to did not receive a “timely” response from another server further along upstream

=> 尝试通过模拟器检查您的互联网连接

您必须像这样在 AndroidManifest.xml 文件中设置 networkSecurityConfig

<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
    <application android:networkSecurityConfig="@xml/network_security_config">




    </application>
</manifest>

之后,在您的 xml 文件夹中,您将按照上面的代码提及名称 network_security_config 创建新文件,以启用所有不加密的请求:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <base-config cleartextTrafficPermitted="true">
        <trust-anchors>
            <certificates src="system" />
        </trust-anchors>
    </base-config>
</network-security-config>

现在您的应用程序将为任何类型的连接发出所有请求。有关详细信息,请阅读 this

希望对您有所帮助....!

谢谢大家的帮助,我找到了这个案例的解决方案,我删除了我主页 activity 上的 FirebaseFirestore.getInstance(),因为我不再在主页上使用 firebase。我不确定为什么,但如果我不删除主页中的代码,应用程序 运行 在真实设备 android 7.0 Nougat 中正常,但在模拟器 7.0 Nougat 中仍然出错。

维护一个 minSdkVersion 较低的旧应用程序,我也不确定明文会对我的应用程序的其余部分产生多深的影响 API,所以我更喜欢使用自定义 OkHttpClient 的方法只是为了毕加索.

版本:

  • OkHttp: 3.10.0
  • 毕加索:2.71828
    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;
                }
            });

            OkHttpClient okHttpClient = builder.build();
            return okHttpClient;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public void loadLogo(String url) {
        if (url != null && !url.isEmpty()) {
            OkHttpClient picassoClient = getUnsafeOkHttpClient();
            Picasso picasso = new Picasso.Builder(this).downloader(new OkHttp3Downloader(picassoClient)).build();
            picasso.setLoggingEnabled(true);
            picasso.load(url)
                    .placeholder(R.drawable.default_logo)
                    .error(R.drawable.default_logo)
                    .into(titleIV);
        }
    }

我将上面的代码更改为这段代码,因为当我将它复制到我的 android 工作室时 它有几个错误,我不得不更改部分代码,但效果很好。

我也在使用“zampp”服务器

public  okhttp3.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();

        okhttp3.OkHttpClient.Builder builder = new okhttp3.OkHttpClient.Builder();
        builder.sslSocketFactory(sslSocketFactory, (X509TrustManager)trustAllCerts[0]);
        builder.hostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        });

        okhttp3.OkHttpClient okHttpClient = builder.build();
        return okHttpClient;
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

public void loadLogo(String url) {
    ImageView imageView = findViewById(R.id.imageView);
    if (url != null && !url.isEmpty()) {
        OkHttpClient picassoClient = getUnsafeOkHttpClient();
        Picasso picasso = new Picasso.Builder(this).downloader(new OkHttp3Downloader((Call.Factory) picassoClient)).build();
        picasso.setLoggingEnabled(true);
        picasso.load(url)
                .into(imageView);
    }
}

那么你应该将它添加到 android studio 的 onCreate 方法中:

  getUnsafeOkHttpClient();
  loadLogo(imageUri);