Addressing Multithreading Issues

The examples we've shown so far created a new HttpClient for each request. In practice, however, you should create one HttpClient for the entire application and use that for all of your HTTP communication. With one HttpClient servicing all of your HTTP requests, you should also pay attention to multithreading issues that could surface if you make multiple simultaneous requests through the same HttpClient. Fortunately, the HttpClient provides facilities that make this easy—all you have to do is create the DefaultHttpClient using a ThreadSafeClientConnManager, as shown in Listing 8-6.

Listing 8-6. Creating an HttpClient for Multithreading Purposes

// ApplicationEx.java import org.apache.http.HttpVersion;

import org.apache.http.client.HttpClient;

import org.apache.http.conn.ClientConnectionManager;

import org.apache.http.conn.scheme.PlainSocketFactory;

import org.apache.http.conn.scheme.Scheme;

import org.apache.http.conn.scheme.SchemeRegistry;

import org.apache.http.conn.ssl.SSLSocketFactory;

import org.apache.http.impl.client.DefaultHttpClient;

import org.apache.http.impl.conn.tsccm.ThreadSafeQientConnManager;

import org.apache.http.params.BasicHttpParams;

import org.apache.http.params.HttpParams;

import org.apache.http.params.HttpProtocolParams;

import org.apache.http.protocol.HTTP;

import android.app.Application; import android.util.Log;

public class ApplicationEx extends Application {

private static final String TAG = "ApplicationEx"; private HttpClient httpClient;

^Override public void onCreate() {

super.onCreate();

httpClient = createHttpClient();

^Override public void onLowMemory() {

super.onLowMemory(); shutdownHttpClient();

^Override public void onTerminate() {

super.onTerminate(); shutdownHttpClient();

private HttpClient createHttpClient() {

Log.d(TAG,"createHttpQient()..."); HttpParams params = new BasicHttpParams(); HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_l); HttpProtocolParams.setContentCharset(params, HTTP.DEFAULT_CONTENT_CHARSET); HttpProtocolParams.setUseExpectContinue(params, true);

SchemeRegistry schReg = new SchemeRegistry(); schReg.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); schReg.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443)); ClientConnectionManager conMgr = new ThreadSafeQientConnManager(params,schReg);

return new DefaultHttpClient(conMgr, params);

public HttpClient getHttpClient() { return httpClient;

private void shutdownHttpClient() {

if(httpClient!=null && httpClient.getConnectionManager()!=null) {

httpClient.getConnectionManager().shutdown();

// HttpActivity.java import java.net.URI;

import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.util.EntityUtils;

import android.app.Activity; import android.os.Bundle; import android.util.Log;

public class HttpActivity extends Activity {

/** Called when the activity is first created. */ ^Override public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

Log.d("ServicesDemoActivity", "a debug statement"); getHttpContent();

public void getHttpContent() {

ApplicationEx app = (ApplicationEx)this.getApplication(); HttpClient client = app.getHttpClient(); HttpGet request = new HttpGet(); request.setURI(new URI("http://www.google.com/")); HttpResponse response = client.execute(request);

String page=EntityUtils.toString(response.getEntity()); System.out.println(page);

catch (Exception e) {

e.printStackTrace();

If your application needs to make more than a few HTTP calls, you should create an HttpClient that services all of your HTTP requests. One way to do this is to take advantage of the fact that each Android application has an associated application object. By default, if you don't define a custom application object, Android uses android.app.Application. Here's the interesting thing about the application object: there will always be exactly one application object for your application and all of your components can access it (using the global context object).

For example, from an activity class, you can call getApplication() to get the application object for your application. The idea here is that because the application is a singleton, and always available, we can extend that class and create our HttpClient there. We then provide an accessor method for all of the components in our application to get the HttpClient. This is what we have done in Listing 8-6. First notice that we have two classes defined in the listing (each should be placed in a separate Java file): one is our custom application object, and the other is a typical component—an activity class. In the ApplicationEx class we extend android.app.Application and then create our HttpClient in the onCreate() method. The class then provides an accessor method for components to obtain a reference to the client. In the HttpActivity class, we get a reference to the global application object and then cast that to our ApplicationEx class. We then call the getHttpClient() method and use that to make an HTTP call.

Now take a look at the createHttpClient() method of ApplicationEx. This method is responsible for creating our singleton HttpClient. Notice that when we instantiate the DefaultHttpClient(), we pass in a ClientConnectionManager. The ClientConnectionManager is responsible for managing HTTP connections for the HttpClient. Because we want to use a single HttpClient for all of the HTTP requests, we create a ThreadSafeClientConnManager.

Note that when you override or extend the default application object, you also have to modify the application node in the AndroidManifest.xml file by setting the android:name attribute like this:

<application android:icon="@drawable/icon" android:label="@string/app_name" android:name="ApplicationEx">

Note You should also call the shutdown() method on the connection manager as demonstrated in Listing 8-6.

This concludes our discussion of using HTTP services with the HttpClient. In the sections that follow, we will turn our focus to another interesting part of the Android Platform: writing background/long-running services. Although not immediately obvious, the processes of making HTTP calls and writing Android services are linked in that you will do a lot of integration from within Android services. Take, for example, a simple mail-client application. On an Android device, this type of application will likely be composed of two pieces: one that will provide the UI to the user, and another to poll for mail messages. The polling will likely have to be done within a background service. The component that polls for new messages will be an Android service, which will in turn use the HttpClient to perform the work.

Now, let's get on with writing services.

0 0

Post a comment