Android JSON Parsing Tutorial

In this Android tutorial, I will walk you through to access a web service end point, parse JSON response and display it in an Android list view. In the last Java tutorial we saw about creating a RESTful web service in Java that produces a JSON response. We will use that service to produce a sample JSON response and consume it via an example Android application.

Earlier I wrote an Android tutorial to read Twitter feeds, in that tutorial I accessed the Twitter API and consumed the JSON response. This tutorial is similar to that and has some improvements in code. The RESTful web service that produces the JSON response and the Android app that is going to consume the JSON response are in the same system.

Access URI and Read Response

Following Java class is a generic utility to access a network URI and read its response. This is a simple task and we need not go for a third-party API. We can have this as a based code and extend over it.

package com.javapapers.android.util;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.util.Log;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;

public class AndroidNetworkUtility {
    private static final String TAG = "AndroidNetworkUtility";

    public boolean isConnected(Context ctx) {
        boolean flag = false;
        ConnectivityManager connectivityManager =
                (ConnectivityManager) ctx.getSystemService(ctx.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();

        if (networkInfo != null && networkInfo.isConnected()) {
            flag = true;
        }
        return flag;
    }

    public String getHttpResponse(HttpRequestBase request) {
        String result = null;
        InputStream inputStream = null;
        try {
            Log.d(TAG, "about to instantiate DefaultHttpClient");
            DefaultHttpClient httpClient = new DefaultHttpClient(new BasicHttpParams());
            Log.d(TAG, "got httpClient" + request.getURI().toString());
            HttpResponse httpResponse = httpClient.execute(request);
            Log.d(TAG, "got httpResponse");
            int statusCode = httpResponse.getStatusLine().getStatusCode();
            Log.d(TAG, "Status Code: " + statusCode);
            String reason = httpResponse.getStatusLine().getReasonPhrase();
            Log.d(TAG, "Reason: " + reason);
            StringBuilder sb = new StringBuilder();
            if (statusCode == 200) {
                HttpEntity entity = httpResponse.getEntity();
                inputStream = entity.getContent();
                BufferedReader bReader = new BufferedReader(
                        new InputStreamReader(inputStream, "UTF-8"), 8);
                String line = null;
                while ((line = bReader.readLine()) != null) {
                    sb.append(line);
                }
            } else {
                sb.append(reason);
            }
            result = sb.toString();
            Log.d(TAG, result);
        } catch (UnsupportedEncodingException ex) {
            Log.e(TAG, ex.toString());
            ex.printStackTrace();
        } catch (ClientProtocolException ex1) {
            Log.e(TAG, ex1.toString());
            ex1.printStackTrace();
        } catch (IOException ex2) {
            Log.e(TAG, ex2.toString());
            ex2.printStackTrace();
        } finally {
            Log.d(TAG, "finally .............");
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        Log.d(TAG, result);
        return result;
    }
}

Consume JSON Response

Following service class uses the above given util class to connect the web service URI and consume JSON response. This again can be considered a generic class and can be ported easily to any other domain specific uses. Following are the two areas to note in this,

  1. Set “Accept” header in HttpGet as “application/json” to request for a JSON response.
  2. I have used Google Gson library to parse the JSON response content and convert it to domain object. I have created a domain class Product which maps the JSON response. I have used it in TypeToken in Gson API to automagically read the response content into an ArrayList object. This is a cool thing to do and do not try to manually parse the JSON response line by line and create the domain values.

Gradle Dependency for Google Gson Library to parse JSON

Add the following dependency to app Gradle dependencies file. Hope you are using Android Studio and if not, I highly recommend to migrate.

dependencies {
    compile 'com.google.code.gson:gson:2.3.1'
}

In the example Android application, I am accessing a RESTful web service that is deloplyed in my local system. The IP address given in the code is my systems local IP address. You can use any web service that produces a JSON response for this example. All you need to do is to give the URI and create a domain object that maps the response.

package com.javapapers.android.jsonparsing;

import android.util.Log;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.javapapers.android.util.AndroidNetworkUtility;

import org.apache.http.client.methods.HttpGet;

import java.util.ArrayList;

public class ProductService {
    private static final String TAG = "ProductService";

    private static final String PRODUCT_WEB_SERVICE_URL = "http://192.168.1.11:8080/JSON_RESTful_Service/rest/products";

    public ArrayList<Product> getProducts() {
        Log.i(TAG, "getProducts ......");
        ArrayList<Product> productList = null;
        HttpGet httpGet = new HttpGet(PRODUCT_WEB_SERVICE_URL);

        //setting header to request for a JSON response
        httpGet.setHeader("Accept", "application/json");
        AndroidNetworkUtility httpUtil = new AndroidNetworkUtility();
        String productJSONStr = httpUtil.getHttpResponse(httpGet);
        Log.d(TAG, "Response: " + productJSONStr);
        productList = convertJson(productJSONStr);
        return productList;
    }

    private ArrayList<Product> convertJson(String productJSONStr) {
        ArrayList<Product> productList = null;
        if (productJSONStr != null && productJSONStr.length() > 0) {
            try {
                Gson gson = new Gson();
                productList =
                        gson.fromJson(productJSONStr, new TypeToken<ArrayList<Product>>() {
                        }.getType());
            } catch (IllegalStateException e) {
                e.printStackTrace();
            }
        }
        return productList;
    }
}

With this key part of this tutorial is done. Accessing the web service end point URI and parsing the JSON response is done. Now the result values are available in an ArrayList instance and we need to display it in a an Android list view. I have earlier written many tutorials for Android list view. Refer this Android ListView custom layout tutorial or continue reading here.

Android-JSON-Web-Service-Parse

Android List View Activity

MainActivity.java

package com.javapapers.android.jsonparsing;

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

import com.javapapers.android.util.AndroidNetworkUtility;

public class MainActivity extends Activity {
    final static String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        AndroidNetworkUtility androidNetworkUtility = new AndroidNetworkUtility();
        if (androidNetworkUtility.isConnected(this)) {
            Log.i(TAG, "Connected.");
            new ProductAsyncTask().execute(this);
        } else {
            Log.v(TAG, "Network not Available!");
        }
    }
}

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:background="@android:color/holo_purple">

    <ListView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/prodsLV"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginBottom="0dp"
        android:layout_marginTop="0dp"
        android:dividerHeight="1dp"
        android:divider="@android:color/black" />
</RelativeLayout>

listview_row_layout.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="fill_parent"
    android:layout_marginBottom="0dp"
    android:layout_marginTop="0dp"
    android:focusableInTouchMode="true"
    android:paddingTop="10dp"
    android:paddingBottom="5dp">

    <TextView
        android:id="@+id/id"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:paddingRight="10dp"
        android:paddingTop="10dp"
        android:paddingLeft="10dp"
        android:scaleType="centerCrop"
        android:textColor="@android:color/black" />

    <TextView
        android:id="@+id/name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@+id/id"
        android:layout_centerVertical="true"
        android:paddingTop="10dp"
        android:text="Cherry"
        android:textColor="#ffffffff" />

    <TextView
        android:id="@+id/category"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:paddingTop="15dp"
        android:paddingRight="15dp"
        android:textColor="#ffffffff" />
</RelativeLayout>
package com.javapapers.android.jsonparsing;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

public class ProductArrayAdapter extends ArrayAdapter<Product> {
    private static final String TAG = "ProductArrayAdapter";
    private List<Product> productList = new ArrayList<Product>();

    static class ProductViewHolder {
        TextView id;
        TextView name;
        TextView category;
    }

    public ProductArrayAdapter(Context context, int textViewResourceId) {
        super(context, textViewResourceId);
    }

    @Override
    public void add(Product object) {
        productList.add(object);
        super.add(object);
    }

    @Override
    public int getCount() {
        return this.productList.size();
    }

    @Override
    public Product getItem(int index) {
        return this.productList.get(index);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View row = convertView;
        ProductViewHolder viewHolder;
        if (row == null) {
            LayoutInflater inflater = (LayoutInflater) this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            row = inflater.inflate(R.layout.listview_row_layout, parent, false);
            viewHolder = new ProductViewHolder();
            viewHolder.id = (TextView) row.findViewById(R.id.id);
            viewHolder.name = (TextView) row.findViewById(R.id.name);
            viewHolder.category = (TextView) row.findViewById(R.id.category);
            row.setTag(viewHolder);
        } else {
            viewHolder = (ProductViewHolder) row.getTag();
        }
        Product product = getItem(position);
        viewHolder.id.setText(product.getId());
        viewHolder.name.setText(product.getName());
        viewHolder.category.setText(product.getCategory());
        return row;
    }

    public Bitmap decodeToBitmap(byte[] decodedByte) {
        return BitmapFactory.decodeByteArray(decodedByte, 0, decodedByte.length);
    }
}

Access Network in Android AsyncTask

Network calls should not be made from the primary UI thread activity. I have created an AsyncTask and will make the network call to access the web service URI from it.

package com.javapapers.android.jsonparsing;

import android.app.Activity;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.ListView;

import java.util.ArrayList;

public class ProductAsyncTask extends AsyncTask<Object, Void, ArrayList<Product>> {
    Activity callerActivity;
    private Context mContext;
    private ProductArrayAdapter productArrayAdapter;
    private ListView listView;

    private static final String TAG = "ProductAsyncTask";

    @Override
    protected ArrayList<Product> doInBackground(Object... params) {
        Log.i(TAG, "doing in background :) ");
        ArrayList<Product> productList = null;
        mContext = (Context) params[0];
        callerActivity = (Activity) params[0];
        ProductService productService = new ProductService();
        Log.i(TAG, "ProductService instantiated .....................");
        productList = productService.getProducts();
        Log.d(TAG, "COUNT: " + productList.size());
        return productList;
    }

    @Override
    protected void onPostExecute(ArrayList<Product> productList) {

        listView = (ListView) callerActivity.findViewById(R.id.prodsLV);
        productArrayAdapter = new ProductArrayAdapter(mContext, R.layout.listview_row_layout);

        for (Product product : productList) {
            productArrayAdapter.add(product);
        }
        listView.setAdapter(productArrayAdapter);
    }
}

Following is the domain class:

package com.javapapers.android.jsonparsing;

public class Product {
    private String id;
    private String name;
    private String category;

    public Product() {

    }

    public Product(String id, String name, String category) {
        super();
        this.id = id;
        this.name = name;
        this.category = category;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getCategory() {
        return category;
    }

    public void setCategory(String category) {
        this.category = category;
    }

}

Download the Android application project AndroidJSONParsing

This Android tutorial was added on 04/06/2015.

Comments on "Android JSON Parsing Tutorial" Tutorial:

  1. Firoz Shaikh says:

    Finally we arrived at JSON by the way. But you know why i inspired write comment?
    .
    I Got My Java Cup Again on the top of the page.

    Cheers.

  2. Joe says:

    @Firoz,

    Thanks. I keep changing the design based on user feedback.

    I changed the previous notepad design in order to improve the page load speed. But, got some good amount of comments asking me to go back to the notepad with coffee cup design.

    Now what I have taken the best of sleek design and merged it with the old notepad+cup design. Hope you guys like it.

  3. krip says:

    Thanks for wrote down the tutorial and shared the project file with newbies like me. May I suggest you to host each project using public git repo such github. By this way, you bandwidth will be reduce and if anything happen with hosting, thus file still available.

  4. Joe says:

    @krip,

    That’s a good idea. Sure I will look at hosting the code samples in github kind of public repos.

Comments are closed for this "Android JSON Parsing Tutorial" tutorial.