Android Apache HTTP Client: Post, Download, Upload multipart

In this post I want to describe how to build an Android Apache HTTP client . In one of my post I describe how we can use HttpUrlConnection to create a client. Using Apache  HTTP library I want to explain how we can send POST request, download images and upload multipart binary data. Moreover I will describe how to exchange cookies.

If you still want to use Apache client you have to add these lines to build.gradle (compile-time):

android {
  useLibrary 'org.apache.http.legacy'
}

Android Apache HTTP: POST Request

As we know already POST and GET are the basic method that we can use to exchange data with a remote server.As example I will send to a remote server some data in text format (by now). So the first step is creating a DefaultHttpClient that is used a wrapper to send data.

HttpClient client = new DefaultHttpClient();
Android Apache HTTP client tutorial

Once we have our client we have to instantiate a class that handles POST request:

HttpPost post = new HttpPost(url);

where url is the url we want to invoke. To send data we simply have to create a list of NameValuePair a simple class that holds the name and the value of our parameters we want to send.

List<NameValuePair> nvList = new ArrayList<NameValuePair>();
BasicNameValuePair bnvp = new BasicNameValuePair("name", name);
// We can add more
nvList.add(bnvp);

In this case at line 2 we set the name of the parameter as name and we add the bnvp to the list as said before. Now we have build our list and set it inside our post request so that it can be sent:

post.setEntity(new UrlEncodedFormEntity(nvList));

In this case we encode our parameters using Url encoding. The last step is executing the request through our DefaultHttpClient instance. As a result we obtain an HttpResponse that can be used to read the result of our request:

HttpResponse resp = client.execute(post);

To read the response we can obtain an InputStream (line 1) and consume it reading data in this way:

InputStream is = resp.getEntity().getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder str = new StringBuilder();
String line = null;
while((line = reader.readLine()) != null){
  str.append(line + "n");
}
is.close();
buffer.append(str.toString());

At the end we have a string that we can use to update our UI.
We have to remember that this operation can be time consuming so that we have to execute this request in an AsyncTask. For more information read the post ‘Android HTTP Client: GET, POST, Download, Upload, Multipart Request’.It is enough to say that all we have done by now should be inside the doInBackground method. Running the example we have:

android apache http Server side
android_http_apache_client_server

Download binary data

Another common operation is downloading binary data from sever. In this case, we want to download an image from the server and show it in our UI.

The operation is very simple using Android Apache HTTP client, because in this case we have to make an HTTP Post request, passing the image name (line 7-10) and read the binary response (line 15-28):

@Override
protected byte[] doInBackground(String... params) {
  String url = params[0];
  String name = params[1];

  HttpClient client = new DefaultHttpClient();
  HttpPost post = new HttpPost(url);
  List<NameValuePair> paramList = new ArrayList<NameValuePair>();
  paramList.add(new BasicNameValuePair("name", name));
  byte[] data = null;

  try {
    post.setEntity(new UrlEncodedFormEntity(paramList));
    HttpResponse resp = client.execute(post);
    InputStream is = resp.getEntity().getContent();
    int contentSize = (int) resp.getEntity().getContentLength();
    System.out.println("Content size ["+contentSize+"]");
    BufferedInputStream bis = new BufferedInputStream(is, 512);

    data = new byte[contentSize];
    int bytesRead = 0;
    int offset = 0;

    while (bytesRead != -1 &amp;&amp; offset &lt; contentSize) {
      bytesRead = bis.read(data, offset, contentSize - offset);
      offset += bytesRead;
    }
  }
  catch(Throwable t) {
    // Handle error here
    t.printStackTrace();
  }

  return data;
}

At line 17 we read the response length so that we can create a byte array with the same size (see line 21), then at line 19 we create a buffered input stream to read the response stream. Then we simply read the response filling the data byte array. As result we have:

android HTTP download image

Upload binary data

This is one of most interesting aspect. To handle this operation using android apache client, we need to add an external library to simplify the task. This is a drawback of using android apache http client respect to the android native api. On the other side as we saw android native api doesn’t handle multipart request so we have to do everything from zero. Using this library we can simplify the process but we have as a consequence a bigger apk at the end. The library is open source and it is called httpmime-xxx.jar. You can download it here. Remember to add it to your project and has to be exported (see Order and Export in Eclipse). As example we create a multipart request containing some text data and an image. So we start creating always our DefaultHttpClient and HttpPost:

HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(url);

Now we have to create our post content, called Entity:

MultipartEntity multiPart = new MultipartEntity();

and then add the single parts: two are text data and one is the binary data (the image we want to upload):

multiPart.addPart("param1", new StringBody(param1));
multiPart.addPart("param2", new StringBody(param2));
multiPart.addPart("file", new ByteArrayBody(baos.toByteArray(), "logo.png"));

Notice at line 3 we create a part using a ByteArrayBody to contain the binary data. Then we fill the post content with the data we created:

post.setEntity(multiPart);

and then we simply send (or post) it to the server:

client.execute(post);

Running the app we have:

android http apache upload Server side

android_http_apache_client_upload_server

Exchange Cookie

One interesting aspect in HTTP protocol is the cookie management. As we know HTTP is a stateless protocol so using cookies we can persist some information across HTTP requests. As example we can suppose to make two HTTP request: one where we invoke a URL and the server returns a cookie containing some information and another one where we send back to the server the cookie.

The first request is very simple:

HttpPost post = new HttpPost(url);
HttpResponse resp = client.execute(post);

Then we read the cookie (line 1,3):

cookieStore store = ((DefaultHttpClient) client).getCookieStore();

List<Cookie> cookies = store.getCookies();
if (cookies != null) {
  for (Cookie c : cookies) {
    System.out.println("Name ["+c.getName()+"] - Val ["+c.getValue()+"]
            - Domain ["+c.getDomain()+"] - Path ["+c.getPath()+"]");
    store.addCookie(c);
  }
}

At line 1 we simply get the cookie store where the cookies are stored. At line 3 we retrieves the cookies list. In the second post request we have to maintain the cookie we retrieved in the first request so we have:

HttpContext ctx = new BasicHttpContext();
ctx.setAttribute(ClientContext.COOKIE_STORE, store);

// Post again with cookie
HttpPost post1 = new HttpPost(url);
client.execute(post1);
HttpResponse resp1 = client.execute(post, ctx);

At line 1 we create BasicHttpContext to handle cookies and at line 2 we set the store inside our context and finally at line 7 we execute the request passing the context too.

One thing we have to notice is that the DefaultHttpClient is always the same so that we can re-use the cookies.

Running the example we have:

android_http_apache_client_cookie android_http_apache_client_server_cookie
Client side cookie output Server side cookie output
You know how to upload and download file from cloud storage? I wrote an interesting post named Android cloud storage API tutorial that can save a lot of work when managing remote files.

Source code available at github.

8 Comments

  1. Eliax1996 January 20, 2014
  2. Fred . February 19, 2014
  3. survivingwithandroid February 19, 2014
  4. Fred . February 20, 2014
  5. survivingwithandroid February 20, 2014
  6. Fred . February 20, 2014
  7. jack August 6, 2014

Add Comment