38

I have tried setting a custom OkHttpClient with a custom Authenticator, however as the doc says: "Responds to authentication challenges from the remote web or proxy server." I have to make 2 requests for each image, and that is not ideal.

Is there a request interceptor like Retrofit does? Or am I missing something in the OkHttpClient?

I'm using the latest versions:

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' 

Thanks!

5 Answers 5

98

Since Picasso 2.5.0 OkHttpDownloader class has been changed, assuming you are using OkHttp3 (and so picasso2-okhttp3-downloader), so you have to do something like this:

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

Source: https://github.com/square/picasso/issues/900

Sign up to request clarification or add additional context in comments.

8 Comments

In first line you have missed 'new' before 'OkHttpClient();'
Note that the newest okhttpclient version is at 3 and not compatible with picasso 2. If you want to use this solution you will need okhttpclient 2.
networkInterceptors is an immutable list in OkHttp3, you can't add to it directly, you need to use a builder. OkHttpClient.Builder builder = new OkHttpClient().newBuilder(); builder.networkInterceptors().add(...) ; client = builder.build().
You can get the OkHttp3Downloader from github.com/JakeWharton/picasso2-okhttp3-downloader
Also just as a note, when you use the new picasso instance, don't use .with(context), as this will undo the custom interceptor.
|
9

See bryant1410's answer for a more up-to-date solution.


Something like this does the job for setting an API-key header:

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

5 Comments

Will try tomorrow!! Thanks, it looks a pretty neat solution!
Are you sure this is working? I get NoSuchMethodError: No static method source(Ljava/io/File;)Lokio/Source; in class Lokio/Okio; or its super classes (declaration of 'okio.Okio' appears in /system/framework/okhttp.jar) when trying this.
Sorry for the late response but your solution worked great! Thanks!
doesn't work because the method openConnection cannot be overriden anymore... :/
@martyonair Which is why I specifically mentioned bryant1410's answer.
4

You can also add Authentication as suggested in the documentation of OkHttp

Just add this client

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

to Picasso like this:

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

The only dependency needed is:

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

1 Comment

This one works, but only problem which I notice on server logs is that when I request to download an image, first tries without authentication header and after the server return 401 it repeats the call with my authenticator. On app side logs all looks good. When I switched to Interceptor instead of Authenticator, I don't see 401 on server logs anymore.
4

It's working

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

dependency:

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

Comments

0

A simple way like this will keep default OkHttpClient timeout and cache configurations:

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

1 Comment

.interceptors() isn't public

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.