7

I want to load image from URL with picasso android library and show it to view but I get an error only in android 7.0 Nougat.

The URL of the image uses HTTPS. In my other project with the same image URL I didn't get the error if I run in real device 7.0 nougat, but it still error if I run in emulator 7.0 Nougat.

I try to other URL image from different domain and I didn't get the error too.

how do I fix it?

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)
Rizal Fahlepi
  • 61
  • 1
  • 4

5 Answers5

11

You will have to set a networkSecurityConfig in your AndroidManifest.xml file like this:

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




    </application>
</manifest>

After that in your xml folder you will create new file as per above code mention name network_security_config to enable all request without encryptions:

<?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>

Now your app will make all requests for any kind of connections. For more information read this.

I hope it'll help you....!

Viral Patel
  • 1,196
  • 1
  • 9
  • 24
  • 1
    for me it doesnt help – r1299597 Jan 31 '20 at 19:47
  • This was the solution that worked for me. Thanks! (I would only use it for my experimental project though) – Benny Feb 15 '21 at 19:13
  • @Benny, why would you only use it for your experimental project? Does this method have a downside? – austinw Sep 04 '21 at 03:58
  • @austinw I would use it for my experimental project only for now because I haven't spent time investigating the security risks involved in allowing any type of connections without encryptions. – Benny Sep 05 '21 at 05:10
3

Maintaining an old application with a low minSdkVersion, I was also unsure of how deep the clear text could impact the rest of the API of my app, so I preferred an approach with a custom OkHttpClient just for Picasso.

Versions:

  • OkHttp: 3.10.0
  • Picasso: 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);
        }
    }
user1556814
  • 557
  • 4
  • 18
  • Good solution!! It helped me to send request with ("Accept", "image/jpg") and ("Content-Type", "image/jpg") headers. How to set Client with headers: https://stackoverflow.com/questions/35728484/how-to-add-multiple-headers-with-ok-http#answer-55923927 – chatlanin Jun 06 '20 at 21:45
1

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

=> Try to check your internet connection over emulator

Humxa Moghal
  • 94
  • 11
  • My internet connection working fine, because my application use internet connection for request to server – Rizal Fahlepi Oct 17 '19 at 10:54
  • But the code you are getting shows connection time out which means your internet or server is down or not responding in time limit – Humxa Moghal Oct 17 '19 at 11:10
0

I changed code above to this code because when I copied it to my android studio it has several error and I had to change some parts of code and it works me well .

also I'm using the "zampp" server

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);
    }
}

then you should add it to onCreate method in android studio:

  getUnsafeOkHttpClient();
  loadLogo(imageUri);
hamid
  • 41
  • 5
-5

Thanks for help me guys, I found my solution for this case, I delete FirebaseFirestore.getInstance() on my home activity because I no longer use firebase at home page. I'm not sure why but if I not delete that code in my home page, application running normal in real device android 7.0 Nougat but still error in emulator 7.0 Nougat.

Rizal Fahlepi
  • 61
  • 1
  • 4