Pass cookies from HttpURLConnection (java.net.CookieManager) to WebView (android.webkit.CookieManager) Pass cookies from HttpURLConnection (java.net.CookieManager) to WebView (android.webkit.CookieManager) android android

Pass cookies from HttpURLConnection (java.net.CookieManager) to WebView (android.webkit.CookieManager)


I would like to suggest a completely different approach to your problem. Instead of copying cookies from one place to another (manual sync), let's make HttpURLConnection and WebViews use the same cookie storage.

This completely eliminates the need for sync. Any cookie updated in any one of them, will be immediately and automatically reflected in the other.

To do this, create your own implementation of java.net.CookieManager which forwards all requests to the WebViews' webkit android.webkit.CookieManager.

Implementation:

import java.io.IOException;import java.net.CookieManager;import java.net.CookiePolicy;import java.net.CookieStore;import java.net.URI;import java.util.Arrays;import java.util.List;import java.util.Map;public class WebkitCookieManagerProxy extends CookieManager {    private android.webkit.CookieManager webkitCookieManager;    public WebkitCookieManagerProxy()    {        this(null, null);    }    WebkitCookieManagerProxy(CookieStore store, CookiePolicy cookiePolicy)    {        super(null, cookiePolicy);        this.webkitCookieManager = android.webkit.CookieManager.getInstance();    }    @Override    public void put(URI uri, Map<String, List<String>> responseHeaders) throws IOException     {        // make sure our args are valid        if ((uri == null) || (responseHeaders == null)) return;        // save our url once        String url = uri.toString();        // go over the headers        for (String headerKey : responseHeaders.keySet())         {            // ignore headers which aren't cookie related            if ((headerKey == null) || !(headerKey.equalsIgnoreCase("Set-Cookie2") || headerKey.equalsIgnoreCase("Set-Cookie"))) continue;            // process each of the headers            for (String headerValue : responseHeaders.get(headerKey))            {                this.webkitCookieManager.setCookie(url, headerValue);            }        }    }    @Override    public Map<String, List<String>> get(URI uri, Map<String, List<String>> requestHeaders) throws IOException     {        // make sure our args are valid        if ((uri == null) || (requestHeaders == null)) throw new IllegalArgumentException("Argument is null");        // save our url once        String url = uri.toString();        // prepare our response        Map<String, List<String>> res = new java.util.HashMap<String, List<String>>();        // get the cookie        String cookie = this.webkitCookieManager.getCookie(url);        // return it        if (cookie != null) res.put("Cookie", Arrays.asList(cookie));        return res;    }    @Override    public CookieStore getCookieStore()     {        // we don't want anyone to work with this cookie store directly        throw new UnsupportedOperationException();    }}

and finally use it by doing this on your application initialization:

android.webkit.CookieSyncManager.createInstance(appContext);// unrelated, just make sure cookies are generally allowedandroid.webkit.CookieManager.getInstance().setAcceptCookie(true);// magic starts hereWebkitCookieManagerProxy coreCookieManager = new WebkitCookieManagerProxy(null, java.net.CookiePolicy.ACCEPT_ALL);java.net.CookieHandler.setDefault(coreCookieManager);


As compared with DefaultHttpClient, there are a few extra steps. The key difference is how to access the existing cookies in HTTPURLConnection:

  1. Call CookieHandler.getDefault() and cast the result to java.net.CookieManager.
  2. With the cookie manager, call getCookieStore() to access the cookie store.
  3. With the cookie store, call get() to access the list of cookies for the given URI.

Here's a complete example:

@Overrideprotected void onCreate(Bundle savedInstanceState) {    // Get cookie manager for WebView    // This must occur before setContentView() instantiates your WebView    android.webkit.CookieSyncManager webCookieSync =        CookieSyncManager.createInstance(this);    android.webkit.CookieManager webCookieManager =        CookieManager.getInstance();    webCookieManager.setAcceptCookie(true);    // Get cookie manager for HttpURLConnection    java.net.CookieStore rawCookieStore = ((java.net.CookieManager)        CookieHandler.getDefault()).getCookieStore();    // Construct URI    java.net.URI baseUri = null;    try {        baseUri = new URI("http://www.example.com");    } catch (URISyntaxException e) {        // Handle invalid URI        ...    }    // Copy cookies from HttpURLConnection to WebView    List<HttpCookie> cookies = rawCookieStore.get(baseUri);    String url = baseUri.toString();    for (HttpCookie cookie : cookies) {        String setCookie = new StringBuilder(cookie.toString())            .append("; domain=").append(cookie.getDomain())            .append("; path=").append(cookie.getPath())            .toString();        webCookieManager.setCookie(url, setCookie);    }    // Continue with onCreate    ...}


I magically solved all my cookie problems with this one line in onCreate:

CookieHandler.setDefault(new CookieManager());