16

Hello I am using the Picasso library to download the images from URL.

URL : https://fbcdn-profile-a.akamaihd.net/hprofile-ak-prn2/t1.0-1/s200x200/1472865_191408954385576_14109897_n.jpg

URL is using https protocol, here it is not working for me to download the images of https protocol using Picasso.

Doesn't it support to download the images which uses https protocol, it worked for me only if I use http proctocol ?

Here I am trying to get bitmap which is using https protocol

com.squareup.picasso.Target target = new com.squareup.picasso.Target() {

@Override
public void onBitmapLoaded(Bitmap bitmap, LoadedFrom loadedFrom) {
    userProfile.setBitmap(bitmap);
    // call the Web API to register the walker here
    new AudioStreetAsyncTask(getActivity(), userProfile, getString(R.string.registration_processing_message), new TaskCompleteListener() {
        @Override
        public void onTaskCompleted(String jsonResponse) {
           Log.d(TAG, jsonResponse);
        }
    });
}

@Override
public void onBitmapFailed(Drawable drawable) {
    userProfile.setBitmap(null);
    // call the Web API to register the walker here
    new AudioStreetAsyncTask(getActivity(), userProfile, getString(R.string.registration_processing_message), new TaskCompleteListener() {
        @Override
        public void onTaskCompleted(String jsonResponse) {
           Log.d(TAG, jsonResponse);
        }
    }).execute();
}

@Override
public void onPrepareLoad(Drawable drawable) {}
};

Picasso.with(getActivity()).load(imgUrl.toString()).into(target);

Any idea ?

N Sharma
  • 33,489
  • 95
  • 256
  • 444

5 Answers5

36

Use those dependencies in your Gradle:

compile 'com.squareup.okhttp:okhttp:2.2.0'
compile 'com.squareup.okhttp:okhttp-urlconnection:2.2.0'
compile 'com.squareup.picasso:picasso:2.4.0'

And this class instead of the original Picasso class

Picasso class:

 public class PicassoTrustAll {

    private static Picasso mInstance = null;

    private PicassoTrustAll(Context context) {
        OkHttpClient client = new OkHttpClient();
        client.setHostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String s, SSLSession sslSession) {
                return true;
            }
        });
        TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
            @Override
            public void checkClientTrusted(
                    java.security.cert.X509Certificate[] x509Certificates,
                    String s) throws java.security.cert.CertificateException {
            }

            @Override
            public void checkServerTrusted(
                    java.security.cert.X509Certificate[] x509Certificates,
                    String s) throws java.security.cert.CertificateException {
            }

            @Override
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return new java.security.cert.X509Certificate[] {};
            }
        } };
        try {
            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, trustAllCerts, new java.security.SecureRandom());
            client.setSslSocketFactory(sc.getSocketFactory());
        } catch (Exception e) {
            e.printStackTrace();
        }

        mInstance = new Picasso.Builder(context)
                .downloader(new OkHttpDownloader(client))
                .listener(new Picasso.Listener() {
                    @Override
                    public void onImageLoadFailed(Picasso picasso, Uri uri, Exception exception) {
                        Log.e("PICASSO", exception);
                    }
                }).build();

    }

    public static Picasso getInstance(Context context) {
        if (mInstance == null) {
             new PicassoTrustAll(context);
        }
        return mInstance;
    }
}

Usage example:

PicassoTrustAll.getInstance(context)
                .load(url)
                .into(imageView);
Sami Eltamawy
  • 9,874
  • 8
  • 48
  • 66
nexus700120
  • 361
  • 3
  • 3
  • It works fine only with those dependencies http://stackoverflow.com/a/28251889/1364896 – Sami Eltamawy Jun 09 '15 at 08:26
  • it's working fine but not for all the devices. example nexus4 – user1517638 Oct 14 '15 at 10:55
  • It's work like champ.. Thank you so much for this solution. – KishuDroid Mar 30 '16 at 12:23
  • 5
    Could you update the code using okhttp3? You should not use these dependencies anymore since your app will start to crash (java.util.NoSuchElementException). Retrofit 2 does not need okhttp dependency. If you have it you are mixing dependencies and it's not good. Thanks – crubio Jul 31 '17 at 12:43
  • Perfect solution! – Krupa Kakkad Dec 19 '17 at 07:14
  • Thanks, your solution saved me. But Since I had used Retrofit2 in my project, I had to use okhttp3 and updated the above solution accordingly. But this method didn't work on the latest Picasso version (2.71828) that I use, and I had to downgrade Picasso version to 2.4 as your solution! How we can apply this solution for Picasso 2.71828 with okhttp3? @crubio also mentioned this point, I don't know if he could find compatible dependency. – Reyhane Farshbaf Nov 08 '19 at 17:43
3

@nexus700120 solution is not up to date

@Neha Tyagi solution works but creates multiple instances of Picasso in each instance of activity which leaks memory

So I crafted a up to date and singleton solution for redirecting image URLs -

CustomPicasso.java

import android.content.Context;
import android.util.Log;

import com.jakewharton.picasso.OkHttp3Downloader;
import com.squareup.picasso.Picasso;

/**
 * Created by Hrishikesh Kadam on 19/12/2017
 */

public class CustomPicasso {

    private static String LOG_TAG = CustomPicasso.class.getSimpleName();
    private static boolean hasCustomPicassoSingletonInstanceSet;

    public static Picasso with(Context context) {

        if (hasCustomPicassoSingletonInstanceSet)
            return Picasso.with(context);

        try {
            Picasso.setSingletonInstance(null);
        } catch (IllegalStateException e) {
            Log.w(LOG_TAG, "-> Default singleton instance already present" +
                    " so CustomPicasso singleton cannot be set. Use CustomPicasso.getNewInstance() now.");
            return Picasso.with(context);
        }

        Picasso picasso = new Picasso.Builder(context).
                downloader(new OkHttp3Downloader(context))
                .build();

        Picasso.setSingletonInstance(picasso);
        Log.w(LOG_TAG, "-> CustomPicasso singleton set to Picasso singleton." +
                " In case if you need Picasso singleton in future then use Picasso.Builder()");
        hasCustomPicassoSingletonInstanceSet = true;

        return picasso;
    }

    public static Picasso getNewInstance(Context context) {

        Log.w(LOG_TAG, "-> Do not forget to call customPicasso.shutdown()" +
                " to avoid memory leak");

        return new Picasso.Builder(context).
                downloader(new OkHttp3Downloader(context))
                .build();
    }
}

build.gradle (Module:app)

android {

    ...

}

dependencies {

    ...

    compile 'com.squareup.picasso:picasso:2.5.2'
    compile 'com.jakewharton.picasso:picasso2-okhttp3-downloader:1.1.0'
}

Usage -

CustomPicasso.with(context)
    .load("http://i.imgur.com/DvpvklR.png")
    .into(imageView);

For latest revisions check CustomPicasso gist - https://gist.github.com/hrishikesh-kadam/09cef31c736de088313f1a102f5ed3a3

Hrishikesh Kadam
  • 35,376
  • 3
  • 26
  • 36
  • 1
    I have tried this solution in my app and it does not work with https protocol. Keep in mind that this is what the question is about – crubio Dec 22 '17 at 12:19
  • @crubio Can you please give me which URL are you hitting? – Hrishikesh Kadam Dec 22 '17 at 12:20
  • You can try this one for example: https://www.multiestetica.com/img/img_et/avatar/i-avatar-15.jpg – crubio Dec 22 '17 at 12:24
  • @crubio It is working my friend. Created play app, take pull and let me know again if it doesn't work - https://github.com/hrishikesh-kadam/custom-picasso-play – Hrishikesh Kadam Dec 22 '17 at 12:31
  • @crubio Just make sure that you don't make a call to Picasso.with(context) before CustomPicasso.with(context). As this would fall back to original Picasso working. You can verify by checking log as I have logged warning. – Hrishikesh Kadam Dec 22 '17 at 12:51
  • Your play app works. You should put last version of retrofit as dependency though. Anyway, I still don't know why in my project it does not work. – crubio Dec 22 '17 at 12:55
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/161814/discussion-between-hrishikesh-kadam-and-crubio). – Hrishikesh Kadam Dec 22 '17 at 12:57
  • Finally it worked, I think I was experiencing issues with the server cache. Anyway I detected an issue with hasCustomPicassoSingletonInstanceSet. It seems to use original Picasso and I don't want this to happen ever. – crubio Dec 28 '17 at 10:19
  • @crubio still getting ssl handshake error but : multiestetica.com/img/img_et/avatar/i-avatar-15.jpg image is working fine please suggest on this. – RAHULRSANNIDHI Oct 03 '18 at 05:58
2
 final OkHttpClient client = new OkHttpClient.Builder()
                    .protocols(Collections.singletonList(Protocol.HTTP_1_1))
                    .build();

            Picasso picasso = new Picasso.Builder(mContext)
                    .downloader(new OkHttp3Downloader(client))
                    .build();
picasso .with(mContext).load(YOUR_URL).into(YOUR_IMAGEVIEW);

Add

compile 'com.jakewharton.picasso:picasso2-okhttp3-downloader:1.1.0'
Neha Tyagi
  • 3,821
  • 3
  • 15
  • 25
1

Just put this this code in your Application class:

final OkHttpClient client = new OkHttpClient.Builder()
        .protocols(Collections.singletonList(Protocol.HTTP_1_1))
        .build();

final Picasso picasso = new Picasso.Builder(this)
        .downloader(new OkHttp3Downloader(client))
        .build();

Picasso.setSingletonInstance(picasso);

from this link check it.

alireza daryani
  • 787
  • 5
  • 16
1

The following works fine for these dependencies:

implementation 'com.squareup.okhttp3:okhttp:3.0.1'
implementation 'com.squareup.picasso:picasso:2.71828'

First define a client to accept certificates:

public class SelfSignCertHttpClient {
    public static OkHttpClient getSelfSignOkHttpClient(List<Interceptor> interceptors) {
        try {
            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[]{};
                        }
                    }
            };

            final SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, trustAllCerts, new java.security.SecureRandom());

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

            for (Interceptor interceptor : interceptors) {
                builder.addInterceptor(interceptor);
            }

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

Source: https://futurestud.io/tutorials/retrofit-2-how-to-trust-unsafe-ssl-certificates-self-signed-expired

I have also added the option to pass a list of interceptors when creating the client.

You can than define a PicasoTrustAll class:

public class PicassoTrustAll {

    private static Picasso mInstance = null;

    private PicassoTrustAll(Context context) {
        List<Interceptor> interceptors = new ArrayList<>();
        // Add any interceptors you wish (e.g Authorization Header interceptor)

        mInstance = new Picasso.Builder(context)
                .downloader(new OkHttp3Downloader(SelfSignCertHttpClient.getSelfSignOkHttpClient(interceptors)))
                .listener((picasso, uri, exception) -> Log.e("PICASSO", exception.getMessage())).build();

    }

    public static Picasso getInstance(Context context) {
        if (mInstance == null) {
            new PicassoTrustAll(context);
        }
        return mInstance;
    }
}

Sample usage:

PicassoTrustAll.getInstance(this).load("https://10.0.2.2/path/to/picture").into(mainPictureView);
makotora
  • 11
  • 1