【问题标题】:Doesn't Picasso support to download images which uses https protocolPicasso 不支持下载使用 https 协议的图片
【发布时间】:2014-06-27 02:04:17
【问题描述】:

您好,我正在使用Picasso 库从 URL 下载图像。

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

URL 使用 https 协议,这里我无法使用 Picasso 下载 https 协议的图像。

不支持下载使用https协议的图片吗,只有我使用http协议才有效?

这里我正在尝试获取使用 https 协议的位图

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

有什么想法吗?

【问题讨论】:

  • 能否请您投票并接受我的解决方案,因为它是最新的,并且 nexus700120 提供的解决方案已过时。

标签: android picasso


【解决方案1】:

在您的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'

还有这个类而不是原来的Picasso

毕加索类:

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

使用示例:

PicassoTrustAll.getInstance(context)
                .load(url)
                .into(imageView);

【讨论】:

  • 它只适用于那些依赖stackoverflow.com/a/28251889/1364896
  • 它工作正常,但不适用于所有设备。例如 nexus4
  • 它就像冠军一样工作。非常感谢您的解决方案。
  • 你能用okhttp3更新代码吗?您不应再使用这些依赖项,因为您的应用程序将开始崩溃 (java.util.NoSuchElementException)。 Retrofit 2 不需要 okhttp 依赖。如果你有它,你正在混合依赖关系,这并不好。谢谢
  • 完美解决方案!
【解决方案2】:

@nexus700120 解决方案不是最新的

@Neha Tyagi 解决方案有效,但会在每个泄漏内存的活动实例中创建多个 Picasso 实例

所以我为重定向图像 URL 设计了一个最新的单例解决方案 -

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'
}

用法-

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

有关最新版本,请查看 CustomPicasso gist - https://gist.github.com/hrishikesh-kadam/09cef31c736de088313f1a102f5ed3a3

【讨论】:

  • 我已在我的应用程序中尝试过此解决方案,但它不适用于 https 协议。请记住,这就是问题所在
  • @crubio 你能告诉我你点击的是哪个网址吗?
  • @crubio 我的朋友正在工作。创建了 play 应用程序,如果它不起作用,请拉动并再次告诉我 - github.com/hrishikesh-kadam/custom-picasso-play
  • @crubio 只要确保你没有在 CustomPicasso.with(context) 之前调用 Picasso.with(context)。因为这将回到毕加索的原始工作。您可以通过检查日志来验证,因为我已经记录了警告。
【解决方案3】:
 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);

添加

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

【讨论】:

    【解决方案4】:

    只需将此代码放在您的应用程序类中:

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

    从这个link检查它。

    【讨论】:

      【解决方案5】:

      以下内容适用于这些依赖项:

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

      首先定义一个客户端来接受证书:

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

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

      我还添加了在创建客户端时传递拦截器列表的选项。

      您可以定义一个 PicasoTrustAll 类:

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

      示例用法:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-08-16
        • 2019-05-28
        • 2015-07-01
        • 2019-08-06
        • 2012-03-24
        • 2017-01-10
        • 1970-01-01
        • 2013-03-11
        相关资源
        最近更新 更多