Let us retrieve data using HTTP GET requests to a simple HTML page, using the standard java.net API. Then, let us learn to use the Android-included Apache HttpClient API. After we use HttpClient directly to get a feel for it, we will also make use of a helper class, HttpRequestHelper, that you can use to simplify the process and encapsulate the details. This class and the Apache networking API in general, has a few advantages over rolling your own networking with java.net, which will be illustrated shortly. The helper class is used to make additional HTTP and HTTPS requests, using GET and POST. We will also look into the basic authentication. First of all, let us take up a HTTP request with an HTTP GET call using HttpUrlConnection.
** UPDATE: Android Complete tutorial now available here.
GET is the most basic HTTP request method. Here, the data that is sent is embedded in the URL, using the query string. In the Network-Explorer application that is shown below, the next class has an Activity that demonstrates the GET request method.
public class SimpleGet extends Activity { //other portions of onCreate omitted for brevity this.getButton.setOnClickListener(new OnClickListener() { public void onClick(View v) { getOutput.setText(""); String output = getHttpResponse(getInput.getText().toString()); if (output != null) { getOutput.setText(output); } } }); }; private String getHttpResponse(String location) { String result = null; URL url = null; try { url = new URL(location); } catch (MalformedURLException e) { // log and or handle } if (url != null) { try { HttpURLConnection urlConn = (HttpURLConnection) url.openConnection(); BufferedReader in = new BufferedReader( new InputStreamReader( Invoke getHttpResponse B method Construct URL object C Open connection using D HttpURLConnection www.it-ebooks.info Working with HTTP 171 urlConn.getInputStream())); String inputLine; int lineCount = 0; // limit lines for example while ((lineCount < 10) && ((inputLine = in.readLine()) != null)) { lineCount++; result += "n" + inputLine; } in.close(); urlConn.disconnect(); } catch (IOException e) { // log and or handle } } else { // log and or handle } return result; } }
The getHttpResponse() method that we’ve built B, is called to get an HTTP response and show the first few lines of it in our SimpleGet class. An object C, of java.net.URL is constructed within this method. A connection to server is opened using an HttpURLConnection D. The object C takes care of many of the details for us here. The BufferedReader is used to read data from the connection one line at a time E. Note that, the same thread that is used for the UI is used here. Hence, the UI is blocked at this point. This is usually not the case and it is used here just for the purpose of demonstrataion. We’ll look into usage of seperate threads shortly. Once the data is received, it is appended to the result string that our method returns F. Then, we close the reader and the connection. A quick and dirty access to HTTP network resources is provided using the plain and simple java.net support that has been ported to Android this way. This way of communicating with HTTP is fairly easy, but can get hard with more complicated data. A few of the problems here can be avoided by spawning separate threads and keeping track of them and by writing your own small framework/API structure around that concept for each HTTP request. But there is a better option. Fortunately, Android provides another set of APIs in the form of the Apache HttpClient3 library that abstract the java.net classes further and are designed to offer more robust HTTP support and help handle the separate-thread issue.
To begin with HttpClient, let us take a look at using core classes to perform HTTP GET and POST method requests. Let us concentrate on making network requests in a Thread separate from the UI, using a combination of the Apache ResponseHandler and Android Handler. Apache HttpClient with Android Handler and Apache ResponseHandler
private final Handler handler = new Handler() { public void handleMessage(Message msg) { progressDialog.dismiss(); String bundleResult = msg.getData().getString("RESPONSE"); output.setText(bundleResult); } }; . . . onCreate omitted for brevity private void performRequest() { final ResponseHandler<String> responseHandler = new ResponseHandler<String>() { public String handleResponse(HttpResponse response) { StatusLine status = response.getStatusLine(); HttpEntity entity = response.getEntity(); String result = null; try { result = StringUtils.inputStreamToString( entity.getContent()); Message message = handler.obtainMessage(); Bundle bundle = new Bundle(); bundle.putString("RESPONSE", result); message.setData(bundle); handler.sendMessage(message); } catch (IOException e) { // log and or handle } return result; } }; this.progressDialog = ProgressDialog.show(this, "working . . .", "performing HTTP request"); new Thread() { public void run() { try { DefaultHttpClient client = new DefaultHttpClient(); HttpGet httpMethod = new HttpGet( urlChooser.getSelectedItem().toString()); client.execute( httpMethod, responseHandler); } catch (ClientProtocolException e) { // log and or handle } catch (IOException e) { // log and or handle
First, a Handler is created, which is capable of sending messages to and from other threads. This technique(as used in the previous ex) allows background tasks to send Message objects to hook back into the main UI thread B. Once the Android Handler is created, an Apache ResponseHandler C is created. This class can be used with HttpClient HTTP requests to pass in as a callback point. On completion of the HTTP request that is fired by the HttpClient, the onResponse() method of a ResponseHandler is used. The HttpEntity returned by the API D, is used to get the payload from the response that comes in. Thus, the HTTP call is made in an asynchronous manner. i.e., we don’t have to block and wait the entire time between when the request is fired and when it completes. Refer figure 6.3 for the relationship of the request, response, Handler, ResponseHandler, and separate threads This provides a basic understanding of HttpClient at work. Next, we will encapsulate a few of the details into a convenient helper class so that we can call it over and over without having to repeat a lot of the setup.