如何在Picasso库中的头部添加身份验证令牌

4

我正在使用picasso库来下载位图,因此在api中需要在头部传递token。我尝试了这篇帖子中的以下代码:Android Picasso library,如何添加身份验证标头?

public static Picasso getImageLoader(final Context context) {
    // fetch the auth value
    sSharedPreferences = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext());

    Picasso.Builder builder = new Picasso.Builder(context);
    builder.downloader(new OkHttpDownloader(context) {
        @Override
        protected HttpURLConnection openConnection(Uri uri) throws IOException {
            HttpURLConnection connection = super.openConnection(uri);
            connection.setRequestProperty(Constant.HEADER_X_API_KEY, sSharedPreferences.getString(SharedPreferenceKeys.JSESSIONID, ""));
            return connection;
        }
    });
    sPicasso = builder.build();
    return sPicasso;
}

Picasso 请求

mTarget = new Target() {
    @Override
    public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom loadedFrom) {
        mdpImageView.setImageBitmap(bitmap);
        Logger.d(TAG, "Test");
    }

    @Override
    public void onBitmapFailed(Drawable drawable) {
        Logger.d(TAG, "Test");
    }

    @Override
    public void onPrepareLoad(Drawable drawable) {
        Logger.d(TAG, "Test");
    }
};

CustomPicasso.getImageLoader(getActivity()).with(getActivity()).load(URL).into(mTarget);

问题

我调试了我的代码,发现它从未调用OkHttpDownloaderopenconnection覆盖方法,因此我的请求总是失败,并最终调用onBitmapFailed

请帮助我了解如何正确传递标头值。

提前致谢。

5个回答

8
解决这个问题花费了两天时间。对于自定义下载器,你不必调用with方法,因为这将初始化默认的下载器和picasso实例。只需按照以下方式操作即可轻松获得位图:
Picasso.Builder builder = new Picasso.Builder(getActivity());
picasso =  builder.downloader(new OkHttpDownloader(getActivity()) {
    @Override
    protected HttpURLConnection openConnection(Uri uri) throws IOException {
        HttpURLConnection connection = super.openConnection(uri);
        connection.setRequestProperty(Constant.HEADER_X_API_KEY, mSharedPreferences.getString(SharedPreferenceKeys.JSESSIONID, ""));
        return connection;
    }
}).build();
picasso.load(url).into(mTarget);

1
这对我最终起到了作用,只需调用它,然后使用Picasso实例,这里我添加了访问令牌。但您也可以添加用户名和密码。
private void setupPicasso()
{        
    //need to set picasso up to use auth - took a while to work this out!
    final Context c = context;
    OkHttpClient client = new OkHttpClient.Builder()
            .addInterceptor(new Interceptor() {
                @Override
                public Response intercept(Chain chain) throws IOException {
                    String token = <token you got when you logged in>;
                    String authString = "Bearer "+token;                        
                    Request newRequest = chain.request().newBuilder()
                            .addHeader("Authorization", authString)
                            .build();
                    return chain.proceed(newRequest);
                }
            })
            .build();
    picasso = new Picasso.Builder(context)
            .downloader(new OkHttp3Downloader(client))
            .build();
}

缓存在使用自定义的OkHttpClient和Picasso时无法正常工作。对于RecyclerView来说是不好的。但是Glide可以。但是在使用Glide时,RecyclerView的滚动不够流畅。 - undefined

0

0
Picasso picasso;
Builder builder = new Picasso.Builder(this);
picasso = builder.loader(new BasicAuthOkHttpLoader(this)).build();

将 Loader 实现到 BasicAuthOkHttpLoader 类中。

在重写的 Load 方法中,编写你的身份验证逻辑。

 @Override
  public Response load(String url, boolean localCacheOnly) throws IOException {
    HttpURLConnection connection = client.open(new URL(url));
    String authString = "username:password";
    String authStringEnc = Base64.encodeToString(authString.getBytes(), Base64.NO_WRAP);
    connection.setRequestProperty("Authorization", "Basic " + authStringEnc);
    connection.setUseCaches(true);

    // no caching happens without this setting in our scenario
    connection.setRequestProperty("Cache-Control", "max-stale=2592000");// 30 days
    if (localCacheOnly) {
      connection.setRequestProperty("Cache-Control", "only-if-cached");
    }

    boolean fromCache = parseResponseSourceHeader(connection.getHeaderField(RESPONSE_SOURCE));

    return new Response(connection.getInputStream(), fromCache);
  }

更多细节请参见:如何实现自定义加载器的HTTP基本认证


那段代码中的某些类已经被弃用。请指定我应该使用哪个版本的picasso和okhttp库。 - N Sharma
picasso-1.1.1.jar 可用。 - Harsha Vardhan

0

我使用了另一个库AQuery,仅用几分钟就能获得授权访问到Picasa,此外该库还使用了手机的凭据,因此非常容易。

即使您不使用这个库,也可以看一下下面我如何实现只包含所需字段的实验性方法。较小的结果可以加快网络IO速度,而且在CPU方面有很大的差异。因为JSON更小,所以解析速度更快,或者XML的DOM更小,因此构建速度非常快。

在这里,我正在使用仅返回XML中用户公共相册所需字段的实验方法。

GoogleHandle handle = new GoogleHandle(this.getActivity(),
            AQuery.AUTH_PICASA, AQuery.ACTIVE_ACCOUNT);

    // experimental fields method encoding the data part of the query string only.
    String url = "";
    try {
        url = "https://picasaweb.google.com/data/feed/api/user/default?kind=album&access=public&fields="
                + URLEncoder
                        .encode("entry(title,id,gphoto:numphotosremaining,gphoto:numphotos,media:group/media:thumbnail)",
                                "UTF-8");
    } catch (UnsupportedEncodingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        //whatever I know this will work
        // I hard coded the string.
    }


        aq.auth(handle).progress(R.id.pbTrackerAlbumsProgress)
                .ajax(url, XmlDom.class, this, "renderAlbums");



public void renderAlbums(String url, XmlDom xml, AjaxStatus status) {
    List<PicasaAlbum> entries = convertAll(xml);


    if (entries.size() > 0) {
        isAuthError = false;
        // if the xml iis null we can't display the list
        // we can setup the adapter
        aa = new ArrayAdapter<PicasaAlbum>(this.getActivity(),
                R.layout.listview_item_album, entries) {

            public View getView(int position, View convertView,
                    ViewGroup parent) {

                if (convertView == null) {

                    // convertView =
                    // View.inflate(getActivity().getBaseContext(),
                    // R.layout.listview_item_album, parent);
                    convertView = getActivity().getLayoutInflater()
                            .inflate(R.layout.listview_item_album, parent,
                                    false);
                }

                PicasaAlbum picasaAlbum = getItem(position);

                AQuery aqLocal = aq.recycle(convertView);

                aqLocal.id(R.id.albumTitle).text(picasaAlbum.title);
                // aq.id(R.id.meta).text(picasaAlbum.author);

                String tbUrl = picasaAlbum.thumbNailUrl.toString();

                Bitmap placeholder = aqLocal
                        .getCachedImage(R.drawable.ic_launcher2);

                if (aqLocal.shouldDelay(position, convertView, parent,
                        tbUrl)) {

                    aqLocal.id(R.id.tb).image(placeholder);
                } else {
                    aqLocal.id(R.id.tb).image(tbUrl, true, true, 0,
                            R.drawable.ic_launcher2x, placeholder,
                            AQuery.FADE_IN_NETWORK, 0);
                }

                return convertView;

            }

        };
        ((TextView) view.findViewById(R.id.tvTrackerExistingAlbum))
                .setText("Select the album for route marker photos");
        ((ProgressBar) view.findViewById(R.id.pbTrackerAlbumsProgress))
                .setVisibility(View.GONE);
        ListView lv = (ListView) view.findViewById(R.id.lvTrackerAlbums);

        lv.setAdapter(aa);
        aa.notifyDataSetChanged();
        lv.setVisibility(View.VISIBLE);
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接