Archie.bpgc
Archie.bpgc

Reputation: 24012

Android: Persisting Server Session using cookie When Making HTTP calls

Server side sessions are stored in database and maintained using cookies. So, every client must come with a valid cookie matching a session in the database.

and on Android side:

DefaultHttpClient client = new DefaultHttpClient();
HttpPost httppost = new HttpPost(url);
HttpResponse response = client.execute(httppost);

If I am using the same client for all the server calls, the client takes care of these cookies.

But the problem is, when the client is destroyed, because of memory needed by the device, the cookies are lost and any subsequent server calls doesn't work.

Is there a way to make the HttpClient persistent? Or what is the usual way to maintain cookies on android side.

Upvotes: 6

Views: 5387

Answers (4)

Steve Bergamini
Steve Bergamini

Reputation: 14600

The "correct" way of doing this is to implement a CookieHandler: http://developer.android.com/reference/java/net/CookieHandler.html

The most basic way of doing this is to extend Application and put this in your applications onCreate():

CookieHandler.setDefault(new CookieManager());

PLEASE NOTE: This will only implement a DEFAULT CookieManger. The default CookieManger will manage cookies for all of your HTTP requests during a specific session of your application. However, it does not have any means of persisting cookies over subsequent uses of the application.

In order to do that, you'll need to write your own cookie manager by implementing CookieStore: http://developer.android.com/reference/java/net/CookieStore.html

Here's an example of a CookieStore implementation i used in an app that is currently in the Google Play store:

package com.touchvision.util;

import java.net.CookieStore;
import java.net.HttpCookie;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.util.Log;

import com.touchvision.Config;

/*
 * This is a custom cookie storage for the application. This
 * will store all the cookies to the shared preferences so that it persists
 * across application restarts.
 */
public class TvCookieStore implements CookieStore {

    private static final String LOGTAG = "TV-TvCookieStore";

    /*
     * The memory storage of the cookies
     */
    private Map<String, Map<String,String>> mapCookies = new HashMap<String, Map<String,String>>();
    /*
     * The instance of the shared preferences
     */
    private final SharedPreferences sharedPrefs;

    /*
     * @see java.net.CookieStore#add(java.net.URI, java.net.HttpCookie)
     */
    public void add(URI uri, HttpCookie cookie) {

        String domain = cookie.getDomain();     

        // Log.i(LOGTAG, "adding ( " + domain +", " + cookie.toString() );

        Map<String,String> cookies = mapCookies.get(domain);
        if (cookies == null) {
            cookies = new HashMap<String, String>(); 
            mapCookies.put(domain, cookies);
        }
        cookies.put(cookie.getName(), cookie.getValue());

        if (cookie.getName().startsWith("SPRING_SECURITY") && !cookie.getValue().equals("")){
           //  Log.i(LOGTAG, "Saving rememberMeCookie = " + cookie.getValue() );            
            // Update in Shared Preferences
            Editor e = sharedPrefs.edit();       
            e.putString(Config.PREF_SPRING_SECURITY_COOKIE, cookie.toString());       
            e.commit(); // save changes 
        }

    }

   /*
    * Constructor
    * 
    * @param  ctxContext the context of the Activity
    */
    public TvCookieStore(Context ctxContext) {

        // Log.i(LOGTAG, "constructor()");

        sharedPrefs = ctxContext.getSharedPreferences(Config.SHARED_PREF_NAME, Context.MODE_PRIVATE);
    }

    /*
     * @see java.net.CookieStore#get(java.net.URI)
     */
    public List<HttpCookie> get(URI uri) {

        List<HttpCookie> cookieList = new ArrayList<HttpCookie>();

        String domain = uri.getHost(); 

        // Log.i(LOGTAG, "getting ( " + domain +" )" );

        Map<String,String> cookies = mapCookies.get(domain);
        if (cookies == null) {
               cookies = new HashMap<String, String>(); 
               mapCookies.put(domain, cookies);
        }  

        for (Map.Entry<String, String> entry : cookies.entrySet()) {
            cookieList.add(new HttpCookie(entry.getKey(), entry.getValue()));
            // Log.i(LOGTAG, "returning cookie: " + entry.getKey() + "="+ entry.getValue());
        }
        return cookieList; 

    }

    /*
     * @see java.net.CookieStore#removeAll()
     */
    public boolean removeAll() {

        // Log.i(LOGTAG, "removeAll()" );

        mapCookies.clear();
        return true;

    }        

    /*
     * @see java.net.CookieStore#getCookies()
     */
    public List<HttpCookie> getCookies() {

        Log.i(LOGTAG, "getCookies()" );

        Set<String> mapKeys = mapCookies.keySet();

        List<HttpCookie> result = new ArrayList<HttpCookie>();
        for (String key : mapKeys) {
            Map<String,String> cookies =    mapCookies.get(key);
            for (Map.Entry<String, String> entry : cookies.entrySet()) {
                result.add(new HttpCookie(entry.getKey(), entry.getValue()));
                Log.i(LOGTAG, "returning cookie: " + entry.getKey() + "="+ entry.getValue());
            }             
        }

        return result;

    }

    /*
     * @see java.net.CookieStore#getURIs()
     */
    public List<URI> getURIs() {

        Log.i(LOGTAG, "getURIs()" );

        Set<String> keys = mapCookies.keySet();
        List<URI> uris = new ArrayList<URI>(keys.size());
        for (String key : keys){
            URI uri = null;
            try {
                uri = new URI(key);
            } catch (URISyntaxException e) {
                e.printStackTrace();
            }
            uris.add(uri);
        }
        return uris;

    }

    /*
     * @see java.net.CookieStore#remove(java.net.URI, java.net.HttpCookie)
     */
    public boolean remove(URI uri, HttpCookie cookie) {

        String domain = cookie.getDomain();     

        Log.i(LOGTAG, "remove( " + domain +", " + cookie.toString() );

        Map<String,String> lstCookies = mapCookies.get(domain);

        if (lstCookies == null)
            return false;

        return lstCookies.remove(cookie.getName()) != null;

    }

}

The above custom CookieStore uses SharedPreferences to persist cookies. You implement the above class the similar to how you would implement the default CookieManager in your application class, but the line would look like this:

CookieHandler.setDefault( new CookieManager( new TvCookieStore(this), CookiePolicy.ACCEPT_ALL));

As you can see, the only Cookie i really cared about persisting was the Spring Security Cookie (we were using Spring Framework on the server side). Your code will obviously be different to account for your specific needs.

Another quick note: I tried countless times to do what you're doing and handle the persistence of cookies within my http client class. It was nothing but headaches. Give this strategy a shot.

Upvotes: 7

Biraj Zalavadia
Biraj Zalavadia

Reputation: 28484

Try this way Hope this helps you

public static List<Cookie> cookies;

public static List<Cookie> sync(String url) {

        CookieManager cookieManager = CookieManager.getInstance();
        if (cookieManager == null)
            return null;

        RFC2109Spec cookieSpec = new RFC2109Spec();
        String rawCookieHeader = null;
        try {
            URL parsedURL = new URL(url);
            rawCookieHeader = cookieManager.getCookie(parsedURL.getHost());
            if (rawCookieHeader == null)
                return null;
            int port = parsedURL.getPort() == -1 ? parsedURL.getDefaultPort()
                    : parsedURL.getPort();

            CookieOrigin cookieOrigin = new CookieOrigin(parsedURL.getHost(),
                    port, "/", false);
            List<Cookie> cookies = cookieSpec.parse(new BasicHeader(
                    "set-cookie", rawCookieHeader), cookieOrigin);
            return cookies;
        } catch (Exception e) {

        }
        return null;
    }


public void sync() {
    if (cookies != null) {

        CookieManager cookieManager = CookieManager.getInstance();
        cookieManager.setAcceptCookie(true);
        for (Cookie cookie : cookies) {

            Cookie sessionInfo = cookie;
            String cookieString = sessionInfo.getName() + "="
                    + sessionInfo.getValue() + "; domain="
                    + sessionInfo.getDomain();
            cookieManager.setCookie("yourDomainUrl", cookieString);
            CookieSyncManager.getInstance().sync();
        }
    }
}


public static DefaultHttpClient getHttpclient() {
        HttpParams httpParameters = new BasicHttpParams();
        HttpConnectionParams.setConnectionTimeout(httpParameters, 30000);
        HttpConnectionParams.setSoTimeout(httpParameters, 30000);
        DefaultHttpClient httpclient = new DefaultHttpClient(httpParameters);

        if (cookies != null) {
            int size = cookies.size();
            for (int i = 0; i < size; i++) {
                httpclient.getCookieStore().addCookie(cookies.get(i));
            }
        } else {
            cookies = sync("yourDomain");
            if (cookies != null) {
                int size = cookies.size();
                for (int i = 0; i < size; i++) {
                    httpclient.getCookieStore().addCookie(cookies.get(i));
                }
            }
        }
        httpclient.getParams().setParameter(CoreProtocolPNames.USER_AGENT,
                "android");
        return httpclient;

    }

How to use?

DefaultHttpClient client =getHttpclient();
HttpPost httppost = new HttpPost(url);
HttpResponse response = client.execute(httppost);
try {
                    cookies = httpclient.getCookieStore().getCookies();
                    sync();
                } catch (Exception e) {
                }

Upvotes: 0

Pratik Dasa
Pratik Dasa

Reputation: 7439

Try below code:

public static List<Cookie> cookies;

cookies = httpclient.getCookieStore().getCookies();
if (cookies != null) {
            CookieSyncManager.createInstance(MainActivity.activity); 
            CookieManager cookieManager = CookieManager.getInstance();
            cookieManager.setAcceptCookie(true);
            for (Cookie cookie : cookies) {

                Cookie sessionInfo = cookie;
                String cookieString = sessionInfo.getName() + "="
                        + sessionInfo.getValue() + "; domain="
                        + sessionInfo.getDomain();
                cookieManager.setCookie(
                        domainUrl,cookieString);
                CookieSyncManager.getInstance().sync();
            }
        }

Upvotes: 0

David Allan Houser Jr
David Allan Houser Jr

Reputation: 127

This may not be cookies but maybe it will helphttp://developer.android.com/reference/android/accounts/package-summary.html

Upvotes: 0

Related Questions