I\'m trying a simple app to read in the HTML of a website, and tranform it to create an easily readable UI in Android (This is an exersize in learning android, not to make a
I had the same problem. Since I am using Volley and not HTTPClient directly the Singleton for HTTPClient didn't seem like the correct solution. But using that same idea I simply saved the CookieManager in my application singleton. So if app is my application singleton then in the onCreate() of each activity I add this:
if (app.cookieManager == null) {
app.cookieManager = new CookieManager(null, CookiePolicy.ACCEPT_ALL);
}
CookieHandler.setDefault(app.cookieManager);
To make this even better, all of my activities are subclasses of MyAppActivity so all I have to do is put it in the onCreate for MyAppActivity and then all of my activities inherit this functionality. Now all my activities are using the same cookie manager and my web service session is shared by all the activities. Simple and it works great.
CookieManager
is used by the Java's internal HTTP client. It has nothing to do with Apache HttpClient.
In your code you always create for each request a new instance of HttpClient
and therefore a new CookieStore
instance, which obviously gets garbage collected along with all cookies stored in as soon as that HttpClient
instance goes out of scope.
You should either
(1) Re-use the same instance of HttpClient
for all logically related HTTP requests and share it between all logically related threads (which is the recommended way of using Apache HttpClient)
(2) or, at the very least, share the same instance of CookieStore
between logically related threads
(3) or, if you insist on using CookieManager
to store all your cookies, create a custom CookieStore
implementation backed by CookieManager
In my application server wants to use same session with same cookies... After few hours of "googling" and painful headache I just saved cookies to SharedPreference or just put in some object and set DefaultHttpClient with same cookies again ... onDestroy just remove SharedPreferences ... that's all:
Look the following example:
public class NodeServerTask extends AsyncTask<Void, Void, String> {
private DefaultHttpClient client;
protected String doInBackground(Void... params) {
HttpPost httpPost = new HttpPost(url);
List<NameValuePair> urlParameters = new ArrayList<NameValuePair>();
urlParameters.add(nameValuePair);
try {
httpPost.setEntity(new UrlEncodedFormEntity(urlParameters));
List<Cookie> cookies = loadSharedPreferencesCookie();
if (cookies!=null){
CookieStore cookieStore = new BasicCookieStore();
for (int i=0; i<cookies.size(); i++)
cookieStore.addCookie(cookies.get(i));
client.setCookieStore(cookieStore);
}
HttpResponse response = client.execute(httpPost);
cookies = client.getCookieStore().getCookies();
saveSharedPreferencesCookies(cookies);
// two methods to save and load cookies ...
private void saveSharedPreferencesCookies(List<Cookie> cookies) {
SerializableCookie[] serializableCookies = new SerializableCookie[cookies.size()];
for (int i=0;i<cookies.size();i++){
SerializableCookie serializableCookie = new SerializableCookie(cookies.get(i));
serializableCookies[i] = serializableCookie;
}
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = preferences.edit();
ObjectOutputStream objectOutput;
ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
try {
objectOutput = new ObjectOutputStream(arrayOutputStream);
objectOutput.writeObject(serializableCookies);
byte[] data = arrayOutputStream.toByteArray();
objectOutput.close();
arrayOutputStream.close();
ByteArrayOutputStream out = new ByteArrayOutputStream();
Base64OutputStream b64 = new Base64OutputStream(out, Base64.DEFAULT);
b64.write(data);
b64.close();
out.close();
editor.putString("cookies", new String(out.toByteArray()));
editor.apply();
} catch (IOException e) {
e.printStackTrace();
}
}
private List<Cookie> loadSharedPreferencesCookie() {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
byte[] bytes = preferences.getString("cookies", "{}").getBytes();
if (bytes.length == 0 || bytes.length==2)
return null;
ByteArrayInputStream byteArray = new ByteArrayInputStream(bytes);
Base64InputStream base64InputStream = new Base64InputStream(byteArray, Base64.DEFAULT);
ObjectInputStream in;
List<Cookie> cookies = new ArrayList<Cookie>();
SerializableCookie[] serializableCookies;
try {
in = new ObjectInputStream(base64InputStream);
serializableCookies = (SerializableCookie[]) in.readObject();
for (int i=0;i<serializableCookies.length; i++){
Cookie cookie = serializableCookies[i].getCookie();
cookies.add(cookie);
}
return cookies;
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
Google Luck
I suppose one of best thing is apply Singleton Pattern to your HTTPClient so you just have only one instance!
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
public class myHttpClient {
private static HttpClient mClient;
private myHttpClient() {};
public static HttpClient getInstance() {
if(mClient==null)
mClient = new DefaultHttpClient();
return mClient;
}
}
A good solution for the cookie storage would be to follow the ThreadLocal pattern in order to avoid storing cookies randomly.
This will help keeping a one and only CookieStore. For more explanation of this pattern, you can follow this useful link.
http://veerasundar.com/blog/2010/11/java-thread-local-how-to-use-and-code-sample/
Cheers
(As promised a solution to this. I still don't like it and feel like I'm missing out on the "Correct" way of doing this but, it works.)
You can use the CookieManager
to register your cookies (and therefore make these cookies available between apps) with the following code:
Saving cookies into the CookieManager
:
List<Cookie> cookies = httpClient.getCookieStore().getCookies();
if(cookies != null)
{
for(Cookie cookie : cookies)
{
String cookieString = cookie.getName() + "=" + cookie.getValue() + "; domain=" + cookie.getDomain();
CookieManager.getInstance().setCookie(cookie.getDomain(), cookieString);
}
}
CookieSyncManager.getInstance().sync();
Checking for cookies on specified domain:
if(CookieManager.getInstance().getCookie(URI_FOR_DOMAIN)
To reconstruct values for HttpClient:
DefaultHttpClient httpClient = new DefaultHttpClient(params);
String[] keyValueSets = CookieManager.getInstance().getCookie(URI_FOR_DOMAIN).split(";");
for(String cookie : keyValueSets)
{
String[] keyValue = cookie.split("=");
String key = keyValue[0];
String value = "";
if(keyValue.length>1) value = keyValue[1];
httpClient.getCookieStore().addCookie(new BasicClientCookie(key, value));
}