Библиотека Android Picasso, как добавить заголовки аутентификации?

Я попытался установить пользовательский OkHttpClient с помощью настраиваемого аутентификатора, однако, как говорится в документе: «Отвечает на запросы аутентификации с удаленного веб-сервера или прокси-сервера». Я должен сделать 2 запроса для каждого изображения, и это не идеально.

Есть ли перехватчик запросов, как у Retrofit? Или я что-то упустил в OkHttpClient?

Я использую последние версии:

compile 'com.squareup.picasso:picasso:2.3.2'
compile 'com.squareup.okhttp:okhttp:2.0.+'
compile 'com.squareup.okhttp:okhttp-urlconnection:2.0.+'
compile 'com.squareup.okio:okio:1.0.0'

Спасибо!


person gonzalomelov    schedule 17.06.2014    source источник


Ответы (5)


Поскольку класс Picasso 2.5.0 OkHttpDownloader был изменен, при условии, что вы используете OkHttp3 (и поэтому https://github.com/JakeWharton/picasso2-okhttp3-downloader ), поэтому вам нужно сделать что-то вроде этого:

OkHttpClient client = new OkHttpClient.Builder()
        .addInterceptor(new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request newRequest = chain.request().newBuilder()
                        .addHeader("X-TOKEN", "VAL")
                        .build();
                return chain.proceed(newRequest);
            }
        })
        .build();

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

Источник: https://github.com/square/picasso/issues/900.

person bryant1410    schedule 24.02.2015
comment
В первой строке вы пропустили 'new' перед 'OkHttpClient();' - person Mieszko; 03.09.2015
comment
Обратите внимание, что самая новая версия okhttpclient — 3 и несовместима с picasso 2. Если вы хотите использовать это решение, вам понадобится okhttpclient 2. - person user1354603; 07.04.2016
comment
networkInterceptors — это неизменяемый список в OkHttp3, вы не можете добавлять в него напрямую, вам нужно использовать конструктор. OkHttpClient.Builder builder = new OkHttpClient().newBuilder(); builder.networkInterceptors().add(...) ; client = builder.build(). - person pwightman; 14.04.2016
comment
Вы можете получить OkHttp3Downloader с сайта https://github.com/JakeWharton/picasso2-okhttp3-downloader. - person darwin; 22.04.2016
comment
Также в качестве примечания: когда вы используете новый экземпляр picasso, не используйте .with(context), так как это отменит пользовательский перехватчик. - person Donavan White; 17.05.2016
comment
скажем, я хочу добавить заголовки только к веб-запросу изображения, а не к другим. как это сделать?? потому что способ, который вы предложили выше, добавит заголовок ко всем запросам, проходящим через клиент okhttp. и через него может проходить json-запрос. пожалуйста, предложите. - person Sagar Nayak; 16.01.2018
comment
@Sagar Nayak, тогда вам следует использовать разные клиенты okhttp в зависимости от типа запроса, один с добавлением заголовков аутентификации, а другой без. - person bryant1410; 16.01.2018
comment
Есть идеи, как это сделать с Xamarin? Я не вижу доступных свойств/методов. - person Justin; 01.08.2018

См. ответ bryant1410 для более актуального решения.


Что-то вроде этого делает работу для установки заголовка API-ключа:

public class CustomPicasso {

    private static Picasso sPicasso;

    private CustomPicasso() {
    }

    public static Picasso getImageLoader(final Context context) {
        if (sPicasso == null) {
            Picasso.Builder builder = new Picasso.Builder(context);
            builder.downloader(new CustomOkHttpDownloader());
            sPicasso = builder.build();
        }
        return sPicasso;
    }

    private static class CustomOkHttpDownloader extends OkHttpDownloader {

        @Override
        protected HttpURLConnection openConnection(final Uri uri) throws IOException {
            HttpURLConnection connection = super.openConnection(uri);
            connection.setRequestProperty(Constants.HEADER_X_API_KEY, "MY_API_KEY");
            return connection;
        }
    }
}
person nhaarman    schedule 18.06.2014
comment
Завтра попробую!! Спасибо, выглядит довольно изящным решением! - person gonzalomelov; 19.06.2014
comment
Вы уверены, что это работает? Я получаю NoSuchMethodError: нет источника статического метода (Ljava/io/File;) Lokio/Source; в классе Локио/Окио; или его суперклассы (объявление «okio.Okio» появляется в /system/framework/okhttp.jar) при попытке сделать это. - person David Corsalini; 14.07.2014
comment
Извините за поздний ответ, но ваше решение сработало отлично! Спасибо! - person gonzalomelov; 01.09.2014
comment
не работает, потому что метод openConnection больше нельзя переопределить... :/ - person martyglaubitz; 03.09.2015
comment
@martyonair Вот почему я специально упомянул ответ bryant1410. - person nhaarman; 03.09.2015

Вы также можете добавить аутентификацию, как это предлагается в документации OkHttp.

Просто добавьте этот клиент

final OkHttpClient client = new OkHttpClient.Builder()
                .authenticator(new Authenticator() {
                    @Override
                    public Request authenticate(Route route, Response response) throws IOException {
                        String credential = okhttp3.Credentials.basic("user", "pw");
                        return response.request().newBuilder()
                                .header("Authorization", credential)
                                .build();
                    }
                })
                .build();

Пикассо так:

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

Единственная необходимая зависимость:

compile 'com.jakewharton.picasso:picasso2-okhttp3-downloader:1.0.2'
person f4b    schedule 22.06.2016
comment
Это работает, но единственная проблема, которую я заметил в журналах сервера, заключается в том, что когда я запрашиваю загрузку изображения, сначала пытается без заголовка аутентификации, а после того, как сервер возвращает 401, он повторяет вызов с моим аутентификатором. В логах приложений все выглядит хорошо. Когда я переключился на Interceptor вместо Authenticator, я больше не вижу 401 в журналах сервера. - person Galeen; 12.11.2018

Это работает

        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                           .authenticator(new Authenticator()
                           {
                               @Override
                               public Request authenticate(Route route, Response response) throws IOException
                               {
                                   String credential =  Credentials.basic("username","password");
                                   return response.request().newBuilder()
                                           .header("Authorization", credential)
                                           .build();
                               }
                           }).build();

                   Picasso picasso = new Picasso.Builder(OnDemandImageCaptureActivity.this)
                           .downloader(new OkHttp3Downloader(okHttpClient))
                           .build();
                        picasso.load("http://example.com/abc.jpeg").into(ivcamera);

зависимость:

compile 'com.squareup.picasso:picasso:2.5.2'
compile 'com.jakewharton.picasso:picasso2-okhttp3-downloader:1.1.0'
person Rakesh Ghasadiya    schedule 02.05.2017

Такой простой способ сохранит настройки тайм-аута и кеша OkHttpClient по умолчанию:

private class MyOkHttpDownloader extends OkHttpDownloader {

    public MyOkHttpDownloader(final Context context) {
        super(context);
        getClient().interceptors().add(new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request newRequest = chain.request().newBuilder()
                        .addHeader("X-TOKEN", "VAL")
                        .build();
                return chain.proceed(newRequest);
            }
        });
    }
}

Picasso picasso = new Picasso.Builder(context).downloader(new MyOkHttpDownloader(context)).build();
person xuxu    schedule 23.07.2015
comment
.interceptors() не является общедоступным - person MoxGeek; 14.10.2019