Android Parse JSON And Show In Listview Retrieve/Fetch URL Server

android json parsing using volley, android parse json and show in listview, android json parsing and display with recyclerview, Android JSON Parsing Using Volley And Display With RecyclerView, android upload image using volley, android listview using volley

Android Parse JSON And Show In Listview Example is the topic of today.

You will learn how to display JSON data in custom listview in android.

To fetch/retrieve JSON data from URL or web server we need to create one web service.

This web service will get us the data which will parse using JSONArray and JSONObject and we will populate the custom listview.

We will get string data like name, country, city etc. and an image URL which is also in string format.

To how to fetch data from server in android and display in listview with image and text, we need to have data in proper format which is JSON.

In this example, we will get the JSON data , about tennis players and, will populate listview step by step with information about players.

Final OutPut Of Example

Step 1. Writing in Gradle File

To set the image from URL in Listview, we need to fetch image from URL using Picasso library.

You can also use other libraries like AQuery, Volley etc. to load image from URL.

To use Picasso library, wrote down the below line in build.gradle(Module:app) file.

 implementation 'com.squareup.picasso:picasso:2.71828'

Above line will integrate the required classes to use various methods of the Picasso library.

Step 2. Permissions

This example is fetching JSON data from the remote web server by using the web service.

So for this purpose, we need to use internet and so we also need internet permissions.

Add the below line in the AndroidManifest.xml file

  <uses-permission android:name="android.permission.INTERNET" />
  • This permissions is normal permission, so we do not need to ask for runtime permission to the user.

Step 3. HttpRequest class

To make Http calls to retrieve JSON data from URL we need to use HttpURLConnection class.

  • Using HttpURLConnection class, you can make for GET or POST call to the web service.

So create a new class named HttpRequest.java and copy the following source code

import android.util.Log;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import org.json.JSONException;
import org.json.JSONObject;

/**
 * Since HttpClient,BasicNameValuePairs, etc...  are deprecated.
 * I've searched for a good alternative, and couldn't find any. Eventually ended up writing my own solution, so I decided to share to those who needs it.
 * Main goals: to make it intuitive, short, clean and reasonable.
 * NOTE methods: .prepare(), preparePost(), withData(map) & withData(string) are build to allow caller to chain in different variations, examples:
 *HttpRequest req=new HttpRequest("http://host:port/path");
 *
 *Example 1: //prepare Http Post request and send to "http://host:port/path" with data params name=Bubu and age=29, return true - if worked
 *req.preparePost().withData("name=Bubu&age=29").send();
 *
 *Example 2: //prepare http get request,  send to "http://host:port/path" and read server's response as String
 *req.prepare().sendAndReadString();
 *
 *Example 3: //prepare Http Post request and send to "http://host:port/path" with name=Bubu and age=29 and read server's response as JSONObject
 *HashMap<String, String>params=new HashMap<>();
 params.put("name", "Groot");
 params.put("age", "29");
 *req.preparePost().withData(params).sendAndReadJSON();
 */
public class HttpRequest {
    //Supported HttpRequest methods
    public static enum Method{
        POST,PUT,DELETE,GET;
    }
    private URL url;
    private HttpURLConnection con;
    private OutputStream os;
    //After instantiation, when opening connection - IOException can occur
    public HttpRequest(URL url)throws IOException{
        this.url=url;
        con = (HttpURLConnection)this.url.openConnection();
    }
    //Can be instantiated with String representation of url, force caller to check for IOException which can be thrown
    public HttpRequest(String url)throws IOException{ this(new URL(url)); Log.d("parameters", url); }

    /**
     * Sending connection and opening an output stream to server by pre-defined instance variable url
     *
     * @param //isPost boolean - indicates whether this request should be sent in POST method
     * @throws IOException - should be checked by caller
     * */
    private void prepareAll(Method method)throws IOException{
        con.setDoInput(true);
        con.setRequestMethod(method.name());
        if(method==Method.POST||method==Method.PUT){
            con.setDoOutput(true);
            os = con.getOutputStream();
        }
    }
    //prepare request in GET method
    //@return HttpRequest this instance -> for chaining method @see line 22
    public HttpRequest prepare() throws IOException{
        prepareAll(Method.GET);
        return this;
    }
    /**
     * Prepares HttpRequest method with for given method, possible values: HttpRequest.Method.POST,
     * HttpRequest.Method.PUT, HttpRequest.Method.GET & HttpRequest.Method.DELETE
     *
     * @param method HttpRequest.Method - nested enum HttpRequest.Method constant
     * @return HttpRequest this instance -> for chaining method @see line 22
     * @throws IOException - should be checked by caller
     * */
    public HttpRequest prepare(Method method)throws IOException{
        prepareAll(method);
        return this;
    }
    /**
     * Adding request headers (standard format "Key":"Value")
     *
     * @param headers String variadic params in standard format "Key":"Value"
     * @return HttpRequest this instance -> for chaining method @see line 22
     * */
    public HttpRequest withHeaders(String... headers){
        for(int i=0,last=headers.length;i<last;i++) {
            String[]h=headers[i].split("[:]");
            con.setRequestProperty(h[0],h[1]);
        }
        return this;
    }

    /**
     * Writes query to open stream to server
     *
     * @param query String params in format of key1=v1&key2=v2 to open stream to server
     * @return HttpRequest this instance -> for chaining method @see line 22
     * @throws IOException - should be checked by caller
     * */
    public HttpRequest withData(String query) throws IOException{
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
        writer.write(query);
        writer.close();
        return this;
    }
    /**
     * Builds query on format of key1=v1&key2=v2 from given hashMap structure
     * for map: {name=Bubu, age=29} -> builds "name=Bubu&age=29"
     * for map: {Iam=Groot} -> builds "Iam=Groot"
     *
     * @param params HashMap consists of key-> value pairs to build query from
     * @return HttpRequest this instance -> for chaining method @see line 22
     * @throws IOException - should be checked by caller
     * */
    public HttpRequest withData(HashMap<String,String> params) throws IOException{
        StringBuilder result=new StringBuilder();
        for(Map.Entry<String,String>entry : params.entrySet()){
            result.append((result.length()>0?"&":"")+entry.getKey()+"="+entry.getValue());//appends: key=value (for first param) OR &key=value(second and more)
            Log.d("parameters",entry.getKey()+"  ===>  "+ entry.getValue());
        }
        withData(result.toString());
         return this;
    }
    //When caller only need to send, and don't need String response from server
    public int send() throws IOException{
        return con.getResponseCode(); //return HTTP status code to indicate whether it successfully sent
    }
    /**
     * Sending request to the server and pass to caller String as it received in response from server
     *
     * @return String printed from server's response
     * @throws IOException - should be checked by caller
     * */
    public String sendAndReadString() throws IOException{
        BufferedReader br=new BufferedReader(new InputStreamReader(con.getInputStream()));
        StringBuilder response=new StringBuilder();
        for(String line;(line=br.readLine())!=null;)response.append(line+"\n");
        Log.d("ressss",response.toString());
        return response.toString();
     }
    /**
     * Sending request to the server and pass to caller its raw contents in bytes as it received from server.
     *
     * @return byte[] from server's response
     * @throws IOException - should be checked by caller
     * */
    public byte[] sendAndReadBytes() throws IOException{
        byte[] buffer = new byte[8192];
        InputStream is = con.getInputStream();
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        for (int bytesRead;(bytesRead=is.read(buffer))>=0;)output.write(buffer, 0, bytesRead);
        return output.toByteArray();
    }
    //JSONObject representation of String response from server
    public JSONObject sendAndReadJSON() throws JSONException, IOException{
        return new JSONObject(sendAndReadString());
    }
}
  • We will use various methods from the above class to make Http calls.
  • In POST call, we need to have some parameters and in GET call, we do not need to add any parameters.

Step 4. Tennis Model

We want to fetch the information like name, country, city and image URL from the remote MySQL server.

And we will populate listview with the fetched information. So for listview, we should create a model class which will maintain the data set.

Prepare a new class and give it a name as TennisModel.java

Write down following lines in TennisModel.java class

public class TennisModel {

    private String name, country, city, imgURL;

    public String getImgURL(){
        return imgURL;
    }

    public void setImgURL(String imgURL){
        this.imgURL = imgURL;
    }

    public String getName() {
        return name;
    }

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

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }
}
  • As you can see in the above code snippet that it contains a getter and setter methods for each information.
  • We will use getter methods in parsing the JSON and setters in the adapter class of the listview.

Step 5. Separate Layout File

Let us make a new separate layout XML file that will represent a view layout of every row of the listview.

Create a new XML file in res->layout directory and set a name as lv_players.xml

Code structure for lv_players.xml is as below

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

    <ImageView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_marginTop="10dp"
        android:layout_marginLeft="10dp"
        android:scaleType="fitXY"
        android:id="@+id/iv"/>

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="100dp"
        android:layout_marginLeft="10dp"
        android:layout_marginTop="10dp"
        android:orientation="vertical">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="0dp"
            android:layout_marginTop="5dp"
            android:layout_weight="1"
            android:id="@+id/name"
            android:text="ddd"/>
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:id="@+id/country"
            android:text="ddd"/>
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:id="@+id/city"
            android:text="ddd"/>

    </LinearLayout>

</LinearLayout>
  • I have taken one Imageview and three TextViews in the above file.
  • We will set the image of the player in imageview and name, country, city in the each three TextView.

Step 6. Making Tennis Adapter Class

Now let us make an adapter class which will populate the listview.

Create a new class named TennisAdapter.java

Code block for TennisAdapter.java class looks like the below

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.squareup.picasso.Picasso;
import java.util.ArrayList;

public class TennisAdapter extends BaseAdapter {

    private Context context;
    private ArrayList<TennisModel> tennisModelArrayList;

    public TennisAdapter(Context context, ArrayList<TennisModel> tennisModelArrayList) {

        this.context = context;
        this.tennisModelArrayList = tennisModelArrayList;
    }

    @Override
    public int getViewTypeCount() {
        return getCount();
    }
    @Override
    public int getItemViewType(int position) {

        return position;
    }

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

    @Override
    public Object getItem(int position) {
        return tennisModelArrayList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }

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

        if (convertView == null) {
            holder = new ViewHolder();
            LayoutInflater inflater = (LayoutInflater) context
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(R.layout.lv_player, null, true);

            holder.iv = (ImageView) convertView.findViewById(R.id.iv);
            holder.tvname = (TextView) convertView.findViewById(R.id.name);
            holder.tvcountry = (TextView) convertView.findViewById(R.id.country);
            holder.tvcity = (TextView) convertView.findViewById(R.id.city);

            convertView.setTag(holder);
        }else {
            // the getTag returns the viewHolder object set as a tag to the view
            holder = (ViewHolder)convertView.getTag();
        }

        Picasso.get().load(tennisModelArrayList.get(position).getImgURL()).into(holder.iv);
        holder.tvname.setText("Name: "+tennisModelArrayList.get(position).getName());
        holder.tvcountry.setText("Country: "+tennisModelArrayList.get(position).getCountry());
        holder.tvcity.setText("City: "+tennisModelArrayList.get(position).getCity());

        return convertView;
    }

    private class ViewHolder {

        protected TextView tvname, tvcountry, tvcity;
        protected ImageView iv;
    }

}
  • In this class, we will receive one arraylist (tennisModelArrayList) which contains the objects of the TennisModel class.

Following lines from the getView() method will set the required data into respective imageview and textview.

 Picasso.get().load(tennisModelArrayList.get(position).getImgURL()).into(holder.iv);
        holder.tvname.setText("Name: "+tennisModelArrayList.get(position).getName());
        holder.tvcountry.setText("Country: "+tennisModelArrayList.get(position).getCountry());
        holder.tvcity.setText("City: "+tennisModelArrayList.get(position).getCity());
  • We have used getter methods to fetch desired data. Picasso library is used here to load image from image URL.

Step 7. Last Changes

At last, we just need to do some changes in activity_main.xml and MainActivity.java file.

Write the below source code in activity_main.xml file.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="Below ListView is populated from JSON Data"
        android:textColor="#000"
         />

    <ListView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/lv"
        android:layout_marginTop="10dp">


    </ListView>

</LinearLayout>

Mainly, a listview is the important layout widget in the above file.

Now replace your existing code of MainActivity.java with the below source code

import android.annotation.SuppressLint;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.ListView;
import android.widget.Toast;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.HashMap;

public class MainActivity extends AppCompatActivity {

    private String jsonURL = "https://demonuts.com/Demonuts/JsonTest/Tennis/json_parsing.php";
    private final int jsoncode = 1;
    private ListView listView;
    ArrayList<TennisModel> tennisModelArrayList;
    private TennisAdapter tennisAdapter;

    private static ProgressDialog mProgressDialog;

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

        listView = findViewById(R.id.lv);

        fetchJSON();

    }

    @SuppressLint("StaticFieldLeak")
    private void fetchJSON(){

        showSimpleProgressDialog(this, "Loading...","Fetching Json",false);

        new AsyncTask<Void, Void, String>(){
            protected String doInBackground(Void[] params) {
                String response="";
                HashMap<String, String> map=new HashMap<>();
                try {
                    HttpRequest req = new HttpRequest(jsonURL);
                    response = req.prepare(HttpRequest.Method.POST).withData(map).sendAndReadString();
                } catch (Exception e) {
                    response=e.getMessage();
                }
                return response;
            }
            protected void onPostExecute(String result) {
                //do something with response
                Log.d("newwwss",result);
                onTaskCompleted(result,jsoncode);
            }
        }.execute();
    }

    public void onTaskCompleted(String response, int serviceCode) {
        Log.d("responsejson", response.toString());
        switch (serviceCode) {
            case jsoncode:

                if (isSuccess(response)) {
                    removeSimpleProgressDialog();  //will remove progress dialog
                    tennisModelArrayList = getInfo(response);
                    tennisAdapter = new TennisAdapter(this,tennisModelArrayList);
                    listView.setAdapter(tennisAdapter);

                }else {
                    Toast.makeText(MainActivity.this, getErrorCode(response), Toast.LENGTH_SHORT).show();
                }
        }
    }

    public ArrayList<TennisModel> getInfo(String response) {
        ArrayList<TennisModel> tennisModelArrayList = new ArrayList<>();
        try {
            JSONObject jsonObject = new JSONObject(response);
            if (jsonObject.getString("status").equals("true")) {

                JSONArray dataArray = jsonObject.getJSONArray("data");

                for (int i = 0; i < dataArray.length(); i++) {

                    TennisModel playersModel = new TennisModel();
                    JSONObject dataobj = dataArray.getJSONObject(i);
                    playersModel.setName(dataobj.getString("name"));
                    playersModel.setCountry(dataobj.getString("country"));
                    playersModel.setCity(dataobj.getString("city"));
                    playersModel.setImgURL(dataobj.getString("imgURL"));
                    tennisModelArrayList.add(playersModel);

                }
            }

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

    public boolean isSuccess(String response) {

        try {
            JSONObject jsonObject = new JSONObject(response);
            if (jsonObject.optString("status").equals("true")) {
                return true;
            } else {

                return false;
            }

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

    public String getErrorCode(String response) {

        try {
            JSONObject jsonObject = new JSONObject(response);
            return jsonObject.getString("message");

        } catch (JSONException e) {
            e.printStackTrace();
        }
        return "No data";
    }

    public static void removeSimpleProgressDialog() {
        try {
            if (mProgressDialog != null) {
                if (mProgressDialog.isShowing()) {
                    mProgressDialog.dismiss();
                    mProgressDialog = null;
                }
            }
        } catch (IllegalArgumentException ie) {
            ie.printStackTrace();

        } catch (RuntimeException re) {
            re.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public static void showSimpleProgressDialog(Context context, String title,
                                                String msg, boolean isCancelable) {
        try {
            if (mProgressDialog == null) {
                mProgressDialog = ProgressDialog.show(context, title, msg);
                mProgressDialog.setCancelable(isCancelable);
            }

            if (!mProgressDialog.isShowing()) {
                mProgressDialog.show();
            }

        } catch (IllegalArgumentException ie) {
            ie.printStackTrace();
        } catch (RuntimeException re) {
            re.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

Reading Deeply

Let us step by step read and understand the code of MainActivity.java

Consider the following lines of code

 private String jsonURL = "https://demonuts.com/Demonuts/JsonTest/Tennis/json_parsing.php";
    private final int jsoncode = 1;
    private ListView listView;
    ArrayList<TennisModel> tennisModelArrayList;
    private TennisAdapter tennisAdapter;

    private static ProgressDialog mProgressDialog;
  • Very first line is defining the string variable with URL as a value of it.
  • This is the URL which will give us the data in the JSON format.
  • Second line in one integer variable.
  • Third one is making an object of the ListView class.
  • Fourth line is creating an arraylist with the objects of the TennisModel class.
  • Fifth line is making an object of the TennisAdapter class and sixth will create one progress dialog.

Now in onCreate() method, we will call a fetchJSON() method.

Code for fetchJSON() method is as below

 private void fetchJSON(){

        showSimpleProgressDialog(this, "Loading...","Fetching Json",false);

        new AsyncTask<Void, Void, String>(){
            protected String doInBackground(Void[] params) {
                String response="";
                HashMap<String, String> map=new HashMap<>();
                try {
                    HttpRequest req = new HttpRequest(jsonURL);
                    response = req.prepare(HttpRequest.Method.POST).withData(map).sendAndReadString();
                } catch (Exception e) {
                    response=e.getMessage();
                }
                return response;
            }
            protected void onPostExecute(String result) {
                //do something with response
                Log.d("newwwss",result);
                onTaskCompleted(result,jsoncode);
            }
        }.execute();
    }
  • We are making an http request to our URL in this method using AsyncTask class.
  • When http call completes it’s execution, compiler call onPostExecute() method.
  • onPostExecute() method will call onTaskCompleted() method.

Code for onTaskCompleted() method is as follow

 public void onTaskCompleted(String response, int serviceCode) {
        Log.d("responsejson", response.toString());
        switch (serviceCode) {
            case jsoncode:

                if (isSuccess(response)) {
                    removeSimpleProgressDialog();  //will remove progress dialog
                    tennisModelArrayList = getInfo(response);
                    tennisAdapter = new TennisAdapter(this,tennisModelArrayList);
                    listView.setAdapter(tennisAdapter);

                }else {
                    Toast.makeText(MainActivity.this, getErrorCode(response), Toast.LENGTH_SHORT).show();
                }
        }
    }
  • if compiler receives the JSON data correctly, then if(isSuccess(response)) will be true, and compiler will go inside this if() condition.
  • After that it will parse the JSON using getInfo() method.
  • And then compiler will set the adapter in the listview.

Writings for getInfo() method is as the following

 public ArrayList<TennisModel> getInfo(String response) {
        ArrayList<TennisModel> tennisModelArrayList = new ArrayList<>();
        try {
            JSONObject jsonObject = new JSONObject(response);
            if (jsonObject.getString("status").equals("true")) {

                JSONArray dataArray = jsonObject.getJSONArray("data");

                for (int i = 0; i < dataArray.length(); i++) {

                    TennisModel playersModel = new TennisModel();
                    JSONObject dataobj = dataArray.getJSONObject(i);
                    playersModel.setName(dataobj.getString("name"));
                    playersModel.setCountry(dataobj.getString("country"));
                    playersModel.setCity(dataobj.getString("city"));
                    playersModel.setImgURL(dataobj.getString("imgURL"));
                    tennisModelArrayList.add(playersModel);

                }
            }

        } catch (JSONException e) {
            e.printStackTrace();
        }
        return tennisModelArrayList;
    }
  • We are parsing the JSON response in this class.

Our JSON response looks like the below

{
    "status": "true",
    "message": "Data fetched successfully!",
    "data": [
        {
            "id": "1",
            "name": "Roger Federer",
            "country": "Switzerland",
            "city": "Basel",
            "imgURL": "https://demonuts.com/Demonuts/SampleImages/roger.jpg"
        },
        {
            "id": "2",
            "name": "Rafael Nadal",
            "country": "Spain",
            "city": "Madrid",
            "imgURL": "https://demonuts.com/Demonuts/SampleImages/nadal.jpg"
        },
        {
            "id": "3",
            "name": "Novak Djokovic",
            "country": "Serbia",
            "city": "Monaco",
            "imgURL": "https://demonuts.com/Demonuts/SampleImages/djoko.jpg"
        },
        {
            "id": "4",
            "name": "Andy Murray",
            "country": "United Kingdom",
            "city": "London",
            "imgURL": "https://demonuts.com/Demonuts/SampleImages/murray.jpg"
        },
        {
            "id": "5",
            "name": "Maria Sharapova",
            "country": "Russia",
            "city": "Moscow",
            "imgURL": "https://demonuts.com/Demonuts/SampleImages/shara.jpg"
        },
        {
            "id": "6",
            "name": "Caroline Wozniacki",
            "country": "Denmark",
            "city": "Odense",
            "imgURL": "https://demonuts.com/Demonuts/SampleImages/woz.jpg"
        },
        {
            "id": "7",
            "name": "Eugenie Bouchard",
            "country": "Canada",
            "city": " Montreal",
            "imgURL": "https://demonuts.com/Demonuts/SampleImages/bou.png"
        },
        {
            "id": "8",
            "name": "Ana Ivanovic",
            "country": "Serbia",
            "city": "Belgrade",
            "imgURL": "https://demonuts.com/Demonuts/SampleImages/iva.jpg"
        }
    ]
}
  • Compiler will run one for loop for the number of times equal to the number of children in the JSONArray named “data.”
  • During the every iteration of the  for loop compiler will set the data using the setter methods of TennisModel class.

Download Source Code for Android parse JSON and Show In ListView

[sociallocker]Download Source Code For Json_Parse_Listview[/sociallocker]