Reputation: 24012
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
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
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
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
Reputation: 127
This may not be cookies but maybe it will helphttp://developer.android.com/reference/android/accounts/package-summary.html
Upvotes: 0