Monday, June 11, 2012

How do I make an http request using cookies on Android?


I'd like to make an http request to a remote server while properly handling cookies (eg. storing cookies sent by the server, and sending those cookies when I make subsequent requests). It'd be nice to preserve any and all cookies, but really the only one I care about is the session cookie.



With java.net, it appears that the preferred way to do this is using java.net.CookieHandler (abstract base class) and java.net.CookieManager (concrete implementation). Android has java.net.CookieHandler, but it does not seem to have java.net.CookieManager.



I could code it all by hand by inspecting http headers, but it seems like there must be an easier way.



What is the proper way to make http requests on Android while preserving cookies?


Source: Tips4all

3 comments:

  1. It turns out that Google Android ships with Apache HttpClient 4.0, and I was able to figure out how to do it using the "Form based logon" example in the HttpClient docs:

    http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/httpclient/src/examples/org/apache/http/examples/client/ClientFormLogin.java



    import java.util.ArrayList;
    import java.util.List;
    import org.apache.http.HttpEntity;
    import org.apache.http.HttpResponse;
    import org.apache.http.NameValuePair;
    import org.apache.http.client.entity.UrlEncodedFormEntity;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.cookie.Cookie;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.apache.http.message.BasicNameValuePair;
    import org.apache.http.protocol.HTTP;

    /**
    * A example that demonstrates how HttpClient APIs can be used to perform
    * form-based logon.
    */
    public class ClientFormLogin {

    public static void main(String[] args) throws Exception {

    DefaultHttpClient httpclient = new DefaultHttpClient();

    HttpGet httpget = new HttpGet("https://portal.sun.com/portal/dt");

    HttpResponse response = httpclient.execute(httpget);
    HttpEntity entity = response.getEntity();

    System.out.println("Login form get: " + response.getStatusLine());
    if (entity != null) {
    entity.consumeContent();
    }
    System.out.println("Initial set of cookies:");
    List<Cookie> cookies = httpclient.getCookieStore().getCookies();
    if (cookies.isEmpty()) {
    System.out.println("None");
    } else {
    for (int i = 0; i < cookies.size(); i++) {
    System.out.println("- " + cookies.get(i).toString());
    }
    }

    HttpPost httpost = new HttpPost("https://portal.sun.com/amserver/UI/Login?" +
    "org=self_registered_users&" +
    "goto=/portal/dt&" +
    "gotoOnFail=/portal/dt?error=true");

    List <NameValuePair> nvps = new ArrayList <NameValuePair>();
    nvps.add(new BasicNameValuePair("IDToken1", "username"));
    nvps.add(new BasicNameValuePair("IDToken2", "password"));

    httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));

    response = httpclient.execute(httpost);
    entity = response.getEntity();

    System.out.println("Login form get: " + response.getStatusLine());
    if (entity != null) {
    entity.consumeContent();
    }

    System.out.println("Post logon cookies:");
    cookies = httpclient.getCookieStore().getCookies();
    if (cookies.isEmpty()) {
    System.out.println("None");
    } else {
    for (int i = 0; i < cookies.size(); i++) {
    System.out.println("- " + cookies.get(i).toString());
    }
    }

    // When HttpClient instance is no longer needed,
    // shut down the connection manager to ensure
    // immediate deallocation of all system resources
    httpclient.getConnectionManager().shutdown();
    }
    }

    ReplyDelete
  2. Have you tried org.apache.http.cookie?

    ReplyDelete
  3. I do not work with google android but I think you'll find it's not that hard to get this working. If you read the relevant bit of the java tutorial you'll see that a registered cookiehandler gets callbacks from the HTTP code.

    So if there is no default (have you checked if CookieHandler.getDefault() really is null?) then you can simply extend CookieHandler, implement put/get and make it work pretty much automatically. Be sure to consider concurrent access and the like if you go that route.

    edit: Obviously you'd have to set an instance of your custom implementation as the default handler through CookieHandler.setDefault() to receive the callbacks. Forgot to mention that.

    ReplyDelete