user2672763
user2672763

Reputation: 811

Automatic cookie handling with OkHttp 3

I am using okhttp 3.0.1.

Every where I am getting example for cookie handling that is with okhttp2

OkHttpClient client = new OkHttpClient();
CookieManager cookieManager = new CookieManager();
cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
client.setCookieHandler(cookieManager);

Can please some one guide me how to use in version 3. setCookieHandler method is not present in the version 3.

Upvotes: 58

Views: 87759

Answers (12)

Peterstev Uremgba
Peterstev Uremgba

Reputation: 729

if you use Kotlin with dagger or hilt and you inject your Okhttp, you can add

implementation 'com.squareup.okhttp3:okhttp-urlconnection:4.9.0'

I feel the version should be the same as your okhttpclient version.

@Provides
@Singleton
fun providesOkHTTPClient(application: Application): OkHttpClient {
    val cookieManager = CookieManager()
    cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL)
    
    return OkHttpClient.Builder()
        .cookieJar(JavaNetCookieJar(cookieManager))
        .addInterceptor(
            ChuckInterceptor(application)
                .showNotification(true)
                .retainDataFor(ChuckInterceptor.Period.ONE_DAY)
        ).addInterceptor(
            HttpLoggingInterceptor().setLevel(
                if (BuildConfig.DEBUG) HttpLoggingInterceptor.Level.BODY
                else HttpLoggingInterceptor.Level.NONE
            )
        ).build()
}

remember to add the dependency on the same module (data) where you are providing okhttpClient

Upvotes: 0

Sayan Manna
Sayan Manna

Reputation: 679

Add implementation "com.squareup.okhttp3:okhttp-urlconnection:3.8.1" into your build.gradle.

var interceptor = HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)
var cookieHandler: CookieHandler = CookieManager()

private var retrofit: Retrofit? = null
retrofit = Retrofit.Builder()
                        .baseUrl(BASE_URL)
                        .client(client)
                        .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                        .build()

private val client : OkHttpClient
            private get() {
                val builder = OkHttpClient.Builder()
                builder.addNetworkInterceptor(interceptor)
                builder.cookieJar(JavaNetCookieJar(cookieHandler))
                builder.connectTimeout(15, TimeUnit.SECONDS)
                builder.readTimeout(20, TimeUnit.SECONDS)
                builder.writeTimeout(20, TimeUnit.SECONDS)
                builder.retryOnConnectionFailure(true)
                return builder.build()
            }

Upvotes: 0

Marcos Souza
Marcos Souza

Reputation: 51

You can try it in Kotlin:

val cookieJar = JavaNetCookieJar(CookieManager())
val url = "https://www.google.com/"

val requestBuilder = Request
        .Builder()
        .url(url)
        .get()

val request = requestBuilder
        .build()

val response = OkHttpClient.Builder()
        .cookieJar(cookieJar)
        .build()
        .newCall(request)
        .execute()

Gradle

dependencies {
    implementation("com.squareup.okhttp3:okhttp:4.2.2")
    implementation("com.squareup.okhttp3:okhttp-urlconnection:4.2.2")
}

Upvotes: 4

Vihaan Verma
Vihaan Verma

Reputation: 13143

minimal solution that persists cookie after first run

public class SharedPrefCookieJar implements CookieJar {

    Map<String, Cookie> cookieMap = new HashMap();
    private Context mContext;
    private SharedPrefsManager mSharedPrefsManager;

    @Inject
    public SharedPrefCookieJar(Context context, SharedPrefsManager sharedPrefsManager) {
        mContext = context;
        mSharedPrefsManager = sharedPrefsManager;
        cookieMap = sharedPrefsManager.getCookieMap(context);
        if (cookieMap == null) {
            cookieMap = new HashMap<>();
        }
    }

    @Override
    public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {

        for (Cookie cookie : cookies) {
            cookieMap.put(cookie.name(), cookie);
        }
        mSharedPrefsManager.setCookieMap(mContext, cookieMap);
    }

    @Override
    public List<Cookie> loadForRequest(HttpUrl url) {
        List<Cookie> validCookies = new ArrayList<>();
        for (Map.Entry<String, Cookie> entry : cookieMap.entrySet()) {
            Cookie cookie = entry.getValue();
            if (cookie.expiresAt() < System.currentTimeMillis()) {

            } else {
                validCookies.add(cookie);
            }
        }
        return validCookies;
    }

}

with dagger

@Module
public class ApiModule {


    @Provides
    @Singleton
    InstagramService provideInstagramService(OkHttpClient client)
    {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(InstagramService.BASE_URL)
                .client(client)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();
        InstagramService instagramService = retrofit.create(InstagramService.class);
        return instagramService;
    }


    @Provides
    @Singleton
    OkHttpClient provideOkHttpClient(SharedPrefCookieJar sharedPrefCookieJar){
        OkHttpClient client;
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        if(BuildConfig.DEBUG)
        {
            HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
            httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
            builder
                .addInterceptor(httpLoggingInterceptor)
                .addInterceptor(new InstagramHeaderInterceptor())
                .addNetworkInterceptor(new LoggingInterceptor());

        }
        client = builder.cookieJar(sharedPrefCookieJar).build();
        return client;
    }
}

Upvotes: 2

Shubham
Shubham

Reputation: 2757

Adding compile "com.squareup.okhttp3:okhttp-urlconnection:3.8.1" to your build.gradle.

And then adding

 CookieManager cookieManager = new CookieManager();
 cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);

 OkHttpClient defaultHttpClient = new OkHttpClient.Builder()
                                 .cookieJar(new JavaNetCookieJar(cookieManager))
                                 .build()

helped me without adding any third-party dependency except the one from OkHttp.

Upvotes: 19

iman kazemayni
iman kazemayni

Reputation: 1343

i used franmontiel PeristentCookieJar library for okhttp3 and retrofit.2. the benefit of this approach is : not need manipulate your okhttp request. Just set cookies or session when creating retrofit

1. first add this to your build.gradle(projectname)
 allprojects {
     repositories {
         jcenter()
         maven { url "https://jitpack.io" }
     }
 }
2. add this to your build.gradle
    compile 'com.github.franmontiel:PersistentCookieJar:v1.0.1'
3. build retrofit like this
public static Retrofit getClient(Context context) {

            ClearableCookieJar cookieJar = new PersistentCookieJar(new SetCookieCache(), new SharedPrefsCookiePersistor(context));
            OkHttpClient okHttpClient = new OkHttpClient.Builder()
                    .cookieJar(cookieJar)
                    .build();
            if (retrofit==null) {
                retrofit = new Retrofit.Builder()
                        .baseUrl(BASE_URL)
                        .addConverterFactory(GsonConverterFactory.create())
                        .client(okHttpClient)
                        .build();
            }
            return retrofit;
        }

Upvotes: 5

xyman
xyman

Reputation: 449

Here is working CookieJar implementation for OkHttp3. If you have multiple instances of OkHttp3 (usually you should have only one instance and use it as singletone) you should set the same instance of cookiejar to all of the http clients so they can share cookies !!! This implementation is not persisting cookies(they will all be discard on application restart) but it should be easy to implement SharedPreferences persistence instead of in-memory list of cookies(cookieStore).

    CookieJar cookieJar = new CookieJar() {
        private final HashMap<String, List<Cookie>> cookieStore = new HashMap<>();

        @Override
        public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
            cookieStore.put(url.host(), cookies);
        }

        @Override
        public List<Cookie> loadForRequest(HttpUrl url) {
            List<Cookie> cookies = cookieStore.get(url.host());
            return cookies != null ? cookies : new ArrayList<Cookie>();
        }
    };
    OkHttpClient httpClient = new OkHttpClient.Builder()
            .cookieJar(cookieJar)
            .build();

Upvotes: 17

riversun
riversun

Reputation: 838

I can show you a library for letting OkHttp3 handle cookies automatically. It can be used easily.

Just Keep cookies on memory, to do persistence yourself if you need. Run on Android and Pure Java environment.

    String url = "https://example.com/webapi";

    OkHttp3CookieHelper cookieHelper = new OkHttp3CookieHelper();

    OkHttpClient client = new OkHttpClient.Builder()
            .cookieJar(cookieHelper.cookieJar())
            .build();

    Request request = new Request.Builder()
            .url(url)
            .build();

Gradle

compile 'org.riversun:okhttp3-cookie-helper:1.0.0'

Maven

<dependency>
<groupId>org.riversun</groupId>
<artifactId>okhttp3-cookie-helper</artifactId>
<version>1.0.0</version>
</dependency>

Upvotes: -1

Matt Wolfe
Matt Wolfe

Reputation: 9284

I used @gncabrera's solution but also created a helper class to help with initialization and also to make it easy to share a CookieJar across the application.

public class OkHttpClientCreator {

    private static CookieJar mCookieJar;

    public static OkHttpClient.Builder getNewHttpClientBuilder(boolean isDebug, boolean useCookies) {
        if (mCookieJar == null && useCookies) {
            mCookieJar = new BasicCookieJar();
        }
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        if (useCookies) {
            builder.cookieJar(mCookieJar);
        }
        if (isDebug) {
            builder.addInterceptor(new LoggingInterceptor());
        }
        return builder;
    }

    public static OkHttpClient getNewHttpClient(boolean isDebug, boolean useCookies) {
       return getNewHttpClientBuilder(isDebug, useCookies).build();
    }

}

The logging interceptor is used in debug mode to print out request information and the cookie jar instance is shared. across callers so that if requests need to use a common cookie handler they can. These cookies won't persist across app launches but that's not a requirement for my application since we use token based sessions and the only need for cookies is the short time between logging in and generating the token.

Note: BasicCookieJar is just the same implementation as gncabrera's MyCookieJar

Upvotes: 0

franmontiel
franmontiel

Reputation: 1910

If you want to use the new OkHttp 3 CookieJar and get rid of the okhttp-urlconnection dependency you can use this PersistentCookieJar.

You only need to create an instance of PersistentCookieJar and then just pass it to the OkHttp builder:

CookieJar cookieJar =
                    new PersistentCookieJar(new SetCookieCache(), new SharedPrefsCookiePersistor(context));

OkHttpClient okHttpClient = new OkHttpClient.Builder()
                    .cookieJar(cookieJar)
                    .build();

Upvotes: 70

1f7
1f7

Reputation: 575

right now I'm playing with it. try PersistentCookieStore, add gradle dependencies for JavaNetCookieJar:

compile "com.squareup.okhttp3:okhttp-urlconnection:3.0.0-RC1"

and init

    // init cookie manager
    CookieHandler cookieHandler = new CookieManager(
            new PersistentCookieStore(ctx), CookiePolicy.ACCEPT_ALL);
    // init okhttp 3 logger
    HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
    logging.setLevel(HttpLoggingInterceptor.Level.BODY);
    // init OkHttpClient
    OkHttpClient httpClient = new OkHttpClient.Builder()
            .cookieJar(new JavaNetCookieJar(cookieHandler))
            .addInterceptor(logging)
            .build();

`

Upvotes: 36

gncabrera
gncabrera

Reputation: 645

Here you have a simple approach to create your own CookieJar. It can be extended as you wish. What I did is to implement a CookieJar and build the OkHttpClient using the OkHttpClient.Builder with this this CookieJar.

public class MyCookieJar implements CookieJar {

    private List<Cookie> cookies;

    @Override
    public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
        this.cookies =  cookies;
    }

    @Override
    public List<Cookie> loadForRequest(HttpUrl url) {
        if (cookies != null)
            return cookies;
        return new ArrayList<Cookie>();

    } 
}

Here is how you can create the OkHttpClient

OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.cookieJar(new MyCookieJar());
OkHttpClient client = builder.build();

Upvotes: 33

Related Questions