8

I am learning to store cookies in Android and came across several ways of implementing it. One of them being the use of CookieManager and CookieStore.

As I was going through Android docs, I came across the following statement:

To establish and maintain a potentially long-lived session between client and server, HttpURLConnection includes an extensible cookie manager. Enable VM-wide cookie management using CookieHandler and CookieManager:

CookieManager cookieManager = new CookieManager();  
CookieHandler.setDefault(cookieManager);

I don't understand the meaning of VM-wide cookie management. I know that VM means Virtual Machine.

My Interpretations:

  1. One way I interpreted it is, creating a CookieManagerand passing it to setDefault() makes it available throughout the application. Hence, I tried the following to test it.

     URL url = new URL("http://something.com");
     URI uri=new URI("http://something.com");
     urlConnection = (HttpURLConnection) url.openConnection();
     cks=urlConnection.getHeaderField("Set-Cookie");  
     //cks is a String
     cookieManager=new CookieManager();
     CookieHandler.setDefault(cookieManager);
     HttpCookie hc=new HttpCookie("Cookie1",cks);
     cookieManager.getCookieStore().add(uri,hc);
     cks1=cookieManager.getCookieStore().getCookies().get(0).getValue();
     //cks1 is another String
    

    I set cks and cks1 to TextViews and it printed cookie content/value as expected. Based on my interpretation, I tried cookieManager.getCookieStore().getCookies().get(0).getValue(); in another activity but it didn't recognise the object which means it is out of scope and not accessible. Also, created a new CookieManager and tried to get the cookies but it returned null. So, I assume this interpretation of VM-wide being accessible across activities is incorrect.

  2. Second Interpretation was Cookies will be automatically stored when CookieManager is set up. I got it from a solution to another question on SO: Cookie management with Java URLConnection

One of the statements in the solution that suggested so:

When HttpURLConnection receives a cookie from the server the CookieManager will receive the cookie and store it. Future requests to the same server will automatically send the previously set cookies.

I removed cookieManager.getCookieStore().add(uri,hc); to test it and discovered that cookies are not stored automatically. So, that interpretation fails too.

ANOTHER DOUBT THAT HAUNTS ME:

Most of the solutions to storing cookies for later use suggests using SharedPreferences. The thing that haunts me is all of them stores cookies in CookieManager initially and later moves it to SharedPreferences. Why not use SharedPreferences directly?

For example:

URL url = new URL("http://something.com");
 urlConnection = (HttpURLConnection) url.openConnection();
 cks=urlConnection.getHeaderField("Set-Cookie"); 
 SharedPreferences pref = getApplicationContext().getSharedPreferences("MyPref", MODE_PRIVATE); 
 Editor editor = pref.edit();
 editor.putString("cookie_name", cks);  // Saving cookie
 editor.commit();

So what is the point of using CookieManager and then moving it to SharedPreferences?

Nick Cardoso
  • 20,807
  • 14
  • 73
  • 124
Mathews Mathai
  • 1,707
  • 13
  • 31
  • "I tried cookieManager...; in another activity but it didn't recognise the object which means it is out of scope and not accessible" - You got a fresh instance or you tried accessing it across activites? Any exception? – Nick Cardoso Mar 26 '18 at 07:14
  • I tried accessing it across activities(same object). – Mathews Mathai Mar 26 '18 at 07:18
  • And you got a NPE presumably? or is it a static field? – Nick Cardoso Mar 26 '18 at 07:23
  • It is a `static field` :D – Mathews Mathai Mar 26 '18 at 07:32
  • Ok, but I'm still not clear what "didn't recognise the object" means. Post the error you are seeing – Nick Cardoso Mar 26 '18 at 07:35
  • What I mean is it doesn't recognise the object any differently. Accessing `cookieManager` in new activity works even without `CookieHandler.setDefault(cookieManager);`. Also, it is only recognised in another activity when it is defined as `static`. I am trying to understand what exactly `CookieHandler.setDefault(cookieManager);` is doing and what is meant by VM wide cookie management.. – Mathews Mathai Mar 26 '18 at 07:56
  • once it is set you should be able to use CookieHandler.getDefault() - you should not need any static objects – Nick Cardoso Mar 26 '18 at 07:59
  • Oh. That is what I was missing. I get it now. Is this `CookieManager` common for all the apps or just the app it is defined in? And does it exist when I restart the app? What I was trying to do is access the same object everywhere and expected it to work. Didn't know there was a `getDefault()` function. Thanks a lot. – Mathews Mathai Mar 26 '18 at 08:01

1 Answers1

4

More details on Android's cookie management framework can be found in this doc, but in short, you only need to setDefault() once. In subsequent calls you can use CookieHandler.getDefault() and you supply the cookies to the sessions as demonstrated in this answer

Using the default implementations you'll only be able to access cookies from your own application.

In simplest terms an Android VM is the layer that translates your application bytecode into machine code and it is one VM per application - so VM-Wide means Application scoped.

SharedPrefs can be used to persist cookies between sessions, although this should be rarely useful (just my opinion)

Nick Cardoso
  • 20,807
  • 14
  • 73
  • 124
  • Got it :D Thanks a lot, Nick. `One VM per application` completes it. Also, is the `default CookieManager` saved and restored on restarting the app or is it a new instance everytime? – Mathews Mathai Mar 26 '18 at 08:12
  • I believe you need to set the instance each time – Nick Cardoso Mar 26 '18 at 08:15
  • Even with `CookieManager`, I will have to read the `headers` and store in them manually using `cookieManager.getCookieStore().add(uri,hc);`, right? Or is it done automatically? – Mathews Mathai Mar 26 '18 at 08:18
  • 1
    Yes you still need to, it's just a little simpler (no need to worry about object format). I'll reword my answer because thats a mistake – Nick Cardoso Mar 26 '18 at 08:25
  • @MathewsMathai I see you don't have the benefactor badge - so if you are not aware, you have to manually award bounties (if you are going to) – Nick Cardoso Mar 27 '18 at 17:03
  • 1
    Done :D Thought it was automatic. – Mathews Mathai Mar 27 '18 at 17:18
  • 1
    I think lots of people believe that, but it's not - if you get an answer that scores highly but don't award it, the system awards half – Nick Cardoso Mar 27 '18 at 17:27