by Lars Vogel

Follow me on twitter

Lars Vogel on Google+

Android HTTP Access - Tutorial

Lars Vogel

Version 1.5

06.01.2012

Revision History
Revision 0.119.07.2010Lars
Vogel
Created
Revision 0.2 - 1.630.08.2010 - 06.11.2012 Lars
Vogel
bug fixes and enhancements

Performing HTTP operations with Android

This article describes how to access web resources via HTTP in Android. It is based on Eclipse 3.7, Java 1.6 and Android 4.0 (Ice Cream Sandwich).


Table of Contents

1. Overview of HTTP access on Android
1.1. Available API's
1.2. Security
2. Android StrictMode
3. HTTP Clients
3.1. HttpURLConnection
3.2. Apache HTTP Client
4. Apache HTTPClient example
5. Check the network availability
6. Proxy
7. Handling network failures
8. Thank you
9. Questions and Discussion
10. Links and Literature
10.1. Source Code
10.2. Android Resources
10.3. vogella Resources

1. Overview of HTTP access on Android

1.1. Available API's

Android contains the standard Java network java.net package which can be used to access network resources. Android also contains the Apache HttpClient library.

The base class for HTTP network access in the java.net package is that HttpURLConnection class .

It used to be that the preferred access of the network would be the Apache HttpClient library. September 2011 the Android development team published a blog entry in which they suggest to prefer HttpURLConnection in future Android projects as they constantly improving this implementation.

1.2. Security

To access the Internet your application requires the android.permission.INTERNET permission.

2. Android StrictMode

Within Android development you should avoid performing long running operations on the UI thread. This includes file and network access. StrictMode allows to setup policies in your application to avoid doing incorrect things. As of Android 3.0 (Honeycomb) StrictMode is configured to crash with an NetworkOnMainThreadException exception if network access happens in the UI thread.

While you should do network access in a background thread this tutorial will avoid this to allow the user to learn network access independent from background processing.

If you targeting Android 3.0 or higher you can turn this check of via the following code at beginning of your onCreate() method of your Activity.

			
StrictMode.ThreadPolicy policy = new StrictMode.
			ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
		

3. HTTP Clients

3.1. HttpURLConnection

HttpURLConnection is a general-purpose, lightweight HTTP client suitable for most applications. This API is recommended by the Android development team to use in newer applications, as this interface get constantly improved.

In the latest version HttpURLConnection supports transparent response compression (via the header Accept-Encoding: gzip, Server Name Indication (extension of SSL and TLS) and a response cache.

The API is relatively straigh forward. For example to retrieve the webpage www.vogella.de.

				
 URL url = new URL("http://www.vogella.de/");
   HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
   try {
     InputStream in = new BufferedInputStream(urlConnection.getInputStream());
     readStream(in);
    finally {
     urlConnection.disconnect();
   }
 }
			

3.2. Apache HTTP Client

Android contains the Apache HttpClient library. You can either use the DefaultHttpClient or AndroidHttpClient to setup the HTTP client.

DefaultHttpClient is the standard HttpClient and uses the SingleClientConnManager class to handle HTTP connections. SingleClientConnManager is not thread-safe, this means that access to it via several threads will create problems.

The following is an example an HTTP Get request via HttpClient.

				
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet("http://www.vogella.de");
HttpResponse response = client.execute(request);
// Get the response
BufferedReader rd = new BufferedReader(new InputStreamReader(
	response.getEntity().getContent()));
String line = "";
while ((line = rd.readLine()) != null) {
	textView.append(line);
}
			

AndroidHttpClient is a special implementation of DefaultHttpClient which is pre-configured for Android.

AndroidHttpClient was introduced in Android 2.2. An instance can be received via the newInstance() method which allows to specify the user agent as parameter. AndroidHttpClient supports SSL and has utility methods for GZIP compressed data. It registers the ThreadSafeClientConnManager which allows thread safe HTTP access via a managed connection pool. AndroidHttpClient also applied reasonable default for timeouts and socket buffer sizes. It also supports HTTPS by default.

4. Apache HTTPClient example

Create the project de.vogella.android.network.html with the activity ReadWebpage. Change the layout main.xml to the following.

			
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <LinearLayout
        android:id="@+id/LinearLayout01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" >
    </LinearLayout>

    <EditText
        android:id="@+id/address"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" >
    </EditText>

    <Button
        android:id="@+id/ReadWebPage"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="myClickHandler"
        android:text="Read Webpage" >
    </Button>

    <TextView
        android:id="@+id/pagetext"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:scrollbars="vertical" >
    </TextView>

</LinearLayout>
		

Add the permission android.permission.INTERNET to the AndroidManifest.xml file to allow your application to access the Internet.

Create the following code to read a webpage and show the HTML code in the TextView.

This example also demonstrate the usage of Android preferences to store user data. The URL which the user has typed is stored in the preferences in the onPause() method. This method is called whenever the Activity is send into the background.

			
package de.vogella.android.network.html;

import java.io.BufferedReader;
import java.io.InputStreamReader;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

import android.app.Activity;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;

public class ReadWebpage extends Activity {
	private static final String PREFERENCES = "PREFERENCES";
	private static final String URL = "url";
	private String lastUrl;
	private EditText urlText;
	private TextView textView;

	
/** Called when the activity is first created. */
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); urlText = (EditText) findViewById(R.id.address); textView = (TextView) findViewById(R.id.pagetext); loadPreferences(); urlText.setText(lastUrl); }
/** * Demonstrates loading of preferences The last value in the URL string will * be loaded */
private void loadPreferences() { SharedPreferences preferences = getSharedPreferences(PREFERENCES, Activity.MODE_PRIVATE); // Set this to the Google Homepage lastUrl = preferences.getString(URL, "http://209.85.229.147"); } @Override protected void onPause() { super.onPause(); SharedPreferences preferences = getSharedPreferences(PREFERENCES, Activity.MODE_PRIVATE); Editor preferenceEditor = preferences.edit(); preferenceEditor.putString(URL, urlText.getText().toString()); // You have to commit otherwise the changes will not be remembered preferenceEditor.commit(); } public void myClickHandler(View view) { switch (view.getId()) { case R.id.ReadWebPage: try { textView.setText(""); HttpClient client = new DefaultHttpClient(); HttpGet request = new HttpGet(urlText.getText().toString()); HttpResponse response = client.execute(request); // Get the response BufferedReader rd = new BufferedReader(new InputStreamReader( response.getEntity().getContent())); String line = ""; while ((line = rd.readLine()) != null) { textView.append(line); } } catch (Exception e) { System.out.println("Nay, did not work"); textView.setText(e.getMessage()); } break; } } }

5. Check the network availability

Obviously the network on an Android device is not always available. You can check the network is currently available via the following code. This requires the ACCESS_NETWORK_STATE permission.

			
public boolean isNetworkAvailable() {
    ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo = cm.getActiveNetworkInfo();
    // if no network is available networkInfo will be null, otherwise check if we are connected
    if (networkInfo != null && networkInfo.isConnected()) {
        return true;
    }
    return false;
}
		

6. Proxy

This chapter is only relevant for you if you are testing with the Android similator behind a proxy. In class you are behind a proxy during your testing you can set the proxy via the class "Settings". For example you could add the following line to your onCreate method in your activity.

			
Settings.System.putString(getContentResolver(), Settings.System.HTTP_PROXY, "myproxy:8080");
		

To change the proxy settings you have to have the permission "android.permission.WRITE_SETTINGS" in "AndroidManifest.xml".

Tip

It seems that DNS resolving doesn't work behind a proxy. See Bug 2764

7. Handling network failures

Network connection fail frequently especially for mobile clients. For example if you switch from Wifi to 3G then an existing network connection will break and you need to retry the request.

The Apache HttpClient has an default DefaultHttpRequestRetryHandler object registered which will per default 3 times retry a failed connection. The problem is that switching from one network to another make take a little while and DefaultHttpRequestRetryHandler will retry immediately.

To work around this issue you can implement your own version of DefaultHttpRequestRetryHandler in which you wait a pre-defined time.

For example the implementation could look like:

			
AbstractHttpClient client = (AbstractHttpClient) new DefaultHttpClient();

DefaultHttpRequestRetryHandler retryHandler = new DefaultHttpRequestRetryHandler() {

	@Override
	public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
		if (!super.retryRequest(exception, executionCount, context)) {
			return false;
		}
		// Retry but wait a bit
		try {
			Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		return true;

	}
};
client.setHttpRequestRetryHandler(retryHandler);
		

8. Thank you

Please help me to support this article:

Flattr this

9. Questions and Discussion

Before posting questions, please see the vogella FAQ. If you have questions or find an error in this article please use the www.vogella.de Google Group. I have created a short list how to create good questions which might also help you.

10. Links and Literature

10.1. Source Code

Source Code of Examples

10.3. vogella Resources

Eclipse RCP Training (German) Eclipse RCP Training with Lars Vogel

Android Tutorial Introduction to Android Programming

GWT Tutorial Program in Java and compile to JavaScript and HTML

Eclipse RCP Tutorial Create native applications in Java

JUnit Tutorial Test your application

Git Tutorial Put everything you have under distributed version control system