Android populate ListView from JSON data using Java Servlet HTTP Request

How to display information in a ListView after parsing the JSON response from a Web server

In this example our goal is to make a Web Request, basically a HTTP POST, as soon as the activity starts on another thread using AsyncTask and then wait for the response. The response is a JSON formatted MySQL data from a Java Servlet that provides us with a array of countries with some additional information. We then parse the JSON data and with the help custom ArrayAdapter display on our List.

android populate listview from json data
android populate listview from json data

Source for Activity - AndroidListViewJSONActivity.java

package com.as400samplecode;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.params.ConnManagerParams;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.google.gson.Gson;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;

public class AndroidListViewJSONActivity extends Activity {

 ArrayList<Country> countryList;
 MyCustomAdapter dataAdapter = null;
 int start = 0;
 int limit = 9999;
 
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);

  String url = "http://10.0.2.2:8080/CountryWebService" + "/CountryServlet";
  grabURL(url); 

 }

 public void grabURL(String url) {
  Log.v("Android Spinner JSON Data Activity", url);
  new GrabURL().execute(url);
 }
 
 private class GrabURL extends AsyncTask<String, Void, String> {
  private static final int REGISTRATION_TIMEOUT = 3 * 1000;
  private static final int WAIT_TIMEOUT = 30 * 1000;
  private final HttpClient httpclient = new DefaultHttpClient();
  final HttpParams params = httpclient.getParams();
  HttpResponse response;
  private String content =  null;
  private boolean error = false;
  private ProgressDialog dialog = 
   new ProgressDialog(AndroidListViewJSONActivity.this);

  protected void onPreExecute() {
   dialog.setMessage("Getting your data... Please wait...");
   dialog.show();
  }

  protected String doInBackground(String... urls) {

   String URL = null;
   
   try {

   URL = urls[0];
   HttpConnectionParams.setConnectionTimeout(params, REGISTRATION_TIMEOUT);
   HttpConnectionParams.setSoTimeout(params, WAIT_TIMEOUT);
   ConnManagerParams.setTimeout(params, WAIT_TIMEOUT);

   HttpPost httpPost = new HttpPost(URL);
   
   //add name value pair for the country code
   List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
   nameValuePairs.add(new BasicNameValuePair("start",String.valueOf(start)));
   nameValuePairs.add(new BasicNameValuePair("limit",String.valueOf(limit)));
   httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs)); 
   response = httpclient.execute(httpPost);

    StatusLine statusLine = response.getStatusLine();
    if(statusLine.getStatusCode() == HttpStatus.SC_OK){
     ByteArrayOutputStream out = new ByteArrayOutputStream();
     response.getEntity().writeTo(out);
     out.close();
     content = out.toString();
    } else{
     //Closes the connection.
     Log.w("HTTP1:",statusLine.getReasonPhrase());
     response.getEntity().getContent().close();
     throw new IOException(statusLine.getReasonPhrase());
    }
   } catch (ClientProtocolException e) {
    Log.w("HTTP2:",e );
    content = e.getMessage();
    error = true;
    cancel(true);
   } catch (IOException e) {
    Log.w("HTTP3:",e );
    content = e.getMessage();
    error = true;
    cancel(true);
   }catch (Exception e) {
    Log.w("HTTP4:",e );
    content = e.getMessage();
    error = true;
    cancel(true);
   }

   return content;
  }

  protected void onCancelled() {
   dialog.dismiss();
   Toast toast = Toast.makeText(AndroidListViewJSONActivity.this, 
     "Error connecting to Server", Toast.LENGTH_LONG);
   toast.setGravity(Gravity.TOP, 25, 400);
   toast.show();

  }

  protected void onPostExecute(String content) {
   dialog.dismiss();
   Toast toast;
   if (error) {
    toast = Toast.makeText(AndroidListViewJSONActivity.this, 
      content, Toast.LENGTH_LONG);
    toast.setGravity(Gravity.TOP, 25, 400);
    toast.show();
   } else {
    displayCountryList(content);
   }
  }

 }

 private void displayCountryList(String response){

  JSONObject responseObj = null; 

  try {

   Gson gson = new Gson();
   responseObj = new JSONObject(response); 
   JSONArray countryListObj = responseObj.getJSONArray("countryList");

   countryList = new ArrayList<Country>();
   for (int i=0; i<countryListObj.length(); i++){

    //get the country information JSON object
    String countryInfo = countryListObj.getJSONObject(i).toString();
    //create java object from the JSON object
    Country country = gson.fromJson(countryInfo, Country.class);
    //add to country array list
    countryList.add(country);
   }

   //create an ArrayAdaptar from the String Array
   dataAdapter = new MyCustomAdapter(this,
     R.layout.country_info, countryList);
   ListView listView = (ListView) findViewById(R.id.listView1);
   // Assign adapter to ListView
   listView.setAdapter(dataAdapter);

   //enables filtering for the contents of the given ListView
   listView.setTextFilterEnabled(true);

   listView.setOnItemClickListener(new OnItemClickListener() {
    public void onItemClick(AdapterView<?> parent, View view,
      int position, long id) {
    // When clicked, show a toast with the TextView text
    Country country = (Country) parent.getItemAtPosition(position);
    Toast.makeText(getApplicationContext(),
      country.getCode(), Toast.LENGTH_SHORT).show();
    }
   });



  } catch (JSONException e) {
   e.printStackTrace();
  }

 }

 private class MyCustomAdapter extends ArrayAdapter<Country> {

  private ArrayList<Country> countryList;

  public MyCustomAdapter(Context context, int textViewResourceId, 
    ArrayList<Country> countryList) {
   super(context, textViewResourceId, countryList);
   this.countryList = new ArrayList<Country>();
   this.countryList.addAll(countryList);
  }

  private class ViewHolder {
   TextView code;
   TextView name;
   TextView continent;
   TextView region;
  }

  @Override
  public View getView(int position, View convertView, ViewGroup parent) {

   ViewHolder holder = null;
   Log.v("ConvertView", String.valueOf(position));
   if (convertView == null) {

   LayoutInflater vi = (LayoutInflater)getSystemService(
     Context.LAYOUT_INFLATER_SERVICE);
   convertView = vi.inflate(R.layout.country_info, null);

   holder = new ViewHolder();
   holder.code = (TextView) convertView.findViewById(R.id.code);
   holder.name = (TextView) convertView.findViewById(R.id.name);
   holder.continent = (TextView) convertView.findViewById(R.id.continent);
   holder.region = (TextView) convertView.findViewById(R.id.region);

   convertView.setTag(holder);

   } else {
    holder = (ViewHolder) convertView.getTag();
   }

   Country country = countryList.get(position);
   holder.code.setText(country.getCode());
   holder.name.setText(country.getName());
   holder.continent.setText(country.getContinent());
   holder.region.setText(country.getRegion());

   return convertView;

  }

 }
}

Source for POJO - Country.java

package com.as400samplecode;

public class Country {
 
 String code = null;
 String name = null;
 String continent = null;
 String region = null;
 Double lifeExpectancy = null;
 Double gnp = null;
 Double surfaceArea = null;
 int population = 0;
 
 public String getCode() {
  return code;
 }
 public void setCode(String code) {
  this.code = code;
 }
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public String getContinent() {
  return continent;
 }
 public void setContinent(String continent) {
  this.continent = continent;
 }
 public String getRegion() {
  return region;
 }
 public void setRegion(String region) {
  this.region = region;
 }
 public Double getLifeExpectancy() {
  return lifeExpectancy;
 }
 public void setLifeExpectancy(Double lifeExpectancy) {
  this.lifeExpectancy = lifeExpectancy;
 }
 public Double getGnp() {
  return gnp;
 }
 public void setGnp(Double gnp) {
  this.gnp = gnp;
 }
 public Double getSurfaceArea() {
  return surfaceArea;
 }
 public void setSurfaceArea(Double surfaceArea) {
  this.surfaceArea = surfaceArea;
 }
 public int getPopulation() {
  return population;
 }
 public void setPopulation(int population) {
  this.population = population;
 }
 
} 

Source for Main Screen Layout - main.xml

<?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">

 <TextView android:layout_width="fill_parent"
  android:layout_height="wrap_content" android:padding="10dp"
  android:text="@string/some_text" android:textSize="20sp" />
 
 <ListView android:id="@+id/listView1" android:layout_width="fill_parent"
  android:layout_height="fill_parent" />

</LinearLayout>

Source for List Layout - country_info.xml

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

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:text="Code: "
        android:textAppearance="?android:attr/textAppearanceMedium" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/textView1"
        android:layout_below="@+id/textView1"
        android:text="Name: "
        android:textAppearance="?android:attr/textAppearanceMedium" />

    <TextView
        android:id="@+id/textView3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/textView2"
        android:layout_below="@+id/textView2"
        android:text="Continent: "
        android:textAppearance="?android:attr/textAppearanceMedium" />

    <TextView
        android:id="@+id/textView4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/textView3"
        android:layout_below="@+id/textView3"
        android:text="Region: "
        android:textAppearance="?android:attr/textAppearanceMedium" />

    <TextView
        android:id="@+id/continent"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/textView3"
        android:layout_alignBottom="@+id/textView3"
        android:layout_toRightOf="@+id/textView3"
        android:text="TextView" />

    <TextView
        android:id="@+id/region"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/textView4"
        android:layout_alignBottom="@+id/textView4"
        android:layout_alignLeft="@+id/continent"
        android:text="TextView" />

    <TextView
        android:id="@+id/name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@+id/textView3"
        android:layout_toRightOf="@+id/textView3"
        android:text="TextView" />

    <TextView
        android:id="@+id/code"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@+id/textView2"
        android:layout_alignLeft="@+id/name"
        android:text="TextView" />

</RelativeLayout>

Source for application variables - strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">ListView JSON Web Data</string>
 <string name="some_text">
     Some North American Countries!
 </string>
 
</resources>

Source for application manifest - AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
 package="com.as400samplecode" android:versionCode="1"
 android:versionName="1.0">

 <uses-sdk android:minSdkVersion="15" />
 <uses-permission android:name="android.permission.INTERNET" />
 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
 <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
 <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
 
 <application android:icon="@drawable/ic_launcher"
  android:label="@string/app_name" android:theme="@android:style/Theme.Light">
  <activity android:name=".AndroidListViewJSONActivity"
   android:label="@string/app_name">
   <intent-filter>
    <action android:name="android.intent.action.MAIN" />

    <category android:name="android.intent.category.LAUNCHER" />
   </intent-filter>
  </activity>
 </application>

</manifest>

Source for Java Servlet - CountryServlet.java

package com.as400samplecode;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.as400samplecode.util.Country;
import com.as400samplecode.util.CountryInformation;

import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;

public class CountryServlet extends HttpServlet {
 private static final long serialVersionUID = 1L;

 public CountryServlet() {
  super();
 }

 protected void doGet(HttpServletRequest request, HttpServletResponse response) 
 throws ServletException, IOException {
  doPost(request,response);
 }

 protected void doPost(HttpServletRequest request, HttpServletResponse response) 
 throws ServletException, IOException {

  String start = request.getParameter("start");
  String limit = request.getParameter("limit");

  PrintWriter out = response.getWriter();
  response.setContentType("text/html");
  response.setHeader("Cache-control", "no-cache, no-store");
  response.setHeader("Pragma", "no-cache");
  response.setHeader("Expires", "-1");
  response.setHeader("Access-Control-Allow-Origin", "*");
  response.setHeader("Access-Control-Allow-Methods", "GET,POST");
  response.setHeader("Access-Control-Allow-Headers", "Content-Type");
  response.setHeader("Access-Control-Max-Age", "86400");

  //get list of countries
  CountryInformation countryInformation = new CountryInformation();
  ArrayList<Country> countryList = countryInformation.getList(start, limit);

  Gson gson = new Gson();
  JsonArray arrayObj=new JsonArray();
  for(int i=0;i<countryList.size();i++){

   Country country = countryList.get(i);
   JsonElement countryObj = gson.toJsonTree(country); 
   arrayObj.add(countryObj);
  }

  //create a new JSON object
  JsonObject myObj = new JsonObject();
  //add property as success
  myObj.addProperty("success", true);
  //add the countryList object
  myObj.add("countryList", arrayObj);
  //convert the JSON to string and send back
  out.println(myObj.toString());

  out.close();
 }
}

Source for database utility functions - CountryInformation.java

package com.as400samplecode.util;

import java.sql.Connection;          
import java.sql.ResultSet;           
import java.sql.SQLException;        
import java.sql.PreparedStatement;   
import java.util.ArrayList;

import javax.naming.Context;         
import javax.naming.InitialContext;  
import javax.sql.DataSource;         

public class CountryInformation {            

 Connection conn = null;             
 PreparedStatement stmt = null;      
 String sql = null;
 
 public ArrayList<Country> getList(String start, String limit) {  

    
  ArrayList<Country> countryList = new ArrayList<Country>(); 
  
  try {       
   Context ctx = (Context) new InitialContext().lookup("java:comp/env");
   conn = ((DataSource) ctx.lookup("jdbc/mysql")).getConnection(); 

   sql = "Select * from COUNTRY order by name,code LIMIT ?,?"; 
   
   stmt = conn.prepareStatement(sql);
   stmt.setInt(1,Integer.parseInt(start)); 
   stmt.setInt(2,Integer.parseInt(limit)); 
   ResultSet rs = stmt.executeQuery();  
   
   while(rs.next()){ 
    Country country = new Country();  
    country.setCode(rs.getString("code").trim());
    country.setName(rs.getString("name").trim());
    country.setContinent(rs.getString("continent").trim());
    country.setRegion(rs.getString("region").trim());
    country.setLifeExpectancy(rs.getString("lifeExpectancy") == 
     null ? new Double(0) : 
      Double.parseDouble(rs.getString("lifeExpectancy")
        .trim()));
    country.setGnp(rs.getString("gnp") == null ? new Double(0)  : 
     Double.parseDouble(rs.getString("gnp").trim()));
    country.setSurfaceArea(rs.getString("surfaceArea") == 
     null ? new Double(0)  : 
     Double.parseDouble(rs.getString("surfaceArea").trim()));
    country.setPopulation(rs.getString("population") == null ? 0 : 
     Integer.parseInt(rs.getString("population").trim()));
    countryList.add(country);
   }                                                                          

   rs.close();                                                                
   stmt.close();                                                              
   stmt = null;                                                               


   conn.close();                                                              
   conn = null;                                                    

  }                                                                
  catch(Exception e){System.out.println(e);}                       

  finally {                                                        
   /*                                                              
    * close any jdbc instances here that weren't                   
    * explicitly closed during normal code path, so                
    * that we don't 'leak' resources...                            
    */                                                             

   if (stmt != null) {                                             
    try {                                                          
     stmt.close();                                                 
    } catch (SQLException sqlex) {                                 
     // ignore -- as we can't do anything about it here            
    }                                                              

    stmt = null;                                             
   }                                                         

   if (conn != null) {                                       
    try {                                                    
     conn.close();                                           
    } catch (SQLException sqlex) {                           
     // ignore -- as we can't do anything about it here      
    }                                                        

    conn = null;                                             
   }                                                         
  }               

  return countryList;

 }   

}   

References