Tuesday, 20 October 2015

Android WebService Tutorial

WebService - AsyncTask - JSON Parsing -  ListView

Scope:

In this Tutorial , I will be explaining about how to invoke a webservice [RESTFUL] from Android.

How to handle the webservice response [JSON]

How to parse the response and display it in a ListView.

Introduction:

Why do we invoke webservice? 

In recent times almost all the websites are going with a mobile application. So, mobiles applications, very often you should get data from a Web Service to update content displayed to users.

JSON?

RESFUL webservices return their response in the form of JSON .  JSON is best alternaive to XML .
JSON is very light weight, structured, easy to parse and much human readable.

Sample JSON:
{
    "contacts": [
        {
                
                "name": "Prabhuraj",
                "email": "prabhuraj@gmail.com",
                "job": {
                    "designation": "Developer",
                    "city": "Chennai",
                       }
        },
        {
                "name": "Johnny Depp",
                "email": "johnny_depp@gmail.com",
                "job": {
                  "designation": "SeniorDeveloper",
                    "city": "Hyderabad",

                }
        }, ........
]
}

Here Square bracket ([) represents starting of an JSONArray node whereas curly bracket ({) represents JSONObject.

Creating a new Android Project in Android Studio


1. Create a new project in Android Studio from file-> new -> new project  [give the name you want]

A default activity and a Layout xml will be created. I named it as WebServiceExampleActivity and activity_web_service_example.xml

2. Modify the Manifest file to include permission as


<manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="example.com.example2" >

    <uses-permission android:name="android.permission.INTERNET" />


3. Am going to display the parsed JSON  in a ListView, so declaring a ListView widget in my Layout 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"     tools:context="example.com.example2.ListViewExampleActivity">     <ListView         android:id="@+id/list"         android:layout_width="match_parent"         android:layout_height="wrap_content"></ListView> </RelativeLayout>


4. My WebServiceExampleActivity

package example.com.example2;



import android.app.Activity;

import android.os.AsyncTask;

import android.os.Bundle;

import android.widget.ArrayAdapter;

import android.widget.ListView;



import org.apache.http.HttpEntity;

import org.apache.http.HttpResponse;

import org.apache.http.client.ClientProtocolException;

import org.apache.http.client.HttpClient;

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

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

import org.apache.http.protocol.BasicHttpContext;

import org.apache.http.protocol.HttpContext;

import org.apache.http.util.EntityUtils;

import org.json.JSONArray;

import org.json.JSONException;

import org.json.JSONObject;

import java.io.IOException;

import java.util.ArrayList;

import java.util.List;



public class WebServiceExampleActivity extends Activity {

    ArrayList<String> arrayList = new ArrayList<String>();

    ListView listView;

    static String response = null;

    private static final String TAG_CONTACTS = "contacts";

    private static final String TAG_NAME = "name";

    JSONArray contacts = null;


    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_web_service_example);

        listView = (ListView) findViewById(R.id.mylist);

        new GetContacts().execute();

    }


// webservice call I have written as a sepearate method for readability 

    public String servicecall(){

        HttpClient httpClient = new DefaultHttpClient();

        HttpContext localContext = new BasicHttpContext();

        HttpGet httpGet = new HttpGet("http://api.androidhive.info/contacts/");

        String text = null;

        try {

            HttpResponse httpresponse = httpClient.execute(httpGet, localContext);

            HttpEntity entity = httpresponse.getEntity();

            response = EntityUtils.toString(entity);



        } catch (ClientProtocolException e) {

            e.printStackTrace();

        } catch (IOException e) {

            e.printStackTrace();

        }

        return response;

    }



    public class GetContacts extends AsyncTask<Void, Void, List<String>> {


        @Override

        protected void onPreExecute() {

            super.onPreExecute();

          }


// doInBackground is by default void returns null. Here since I am using a List to store the //values, its declarations is modified as protected List<String> doInBackground().

// When this is modified, automatically the parameter in postexecute is modified.
        @Override

        protected List<String> doInBackground(Void... params) {

            String jsonresponse = servicecall();



            if (jsonresponse != null){

                try {

                    JSONObject jsonObject = new JSONObject(jsonresponse);

                    contacts = jsonObject.getJSONArray(TAG_CONTACTS);

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

                        JSONObject innerobject = contacts.getJSONObject(i);

                        String name = innerobject.getString("name");

                        arrayList.add(name);

                    }

                } catch (JSONException e) {

                    e.printStackTrace();

                }

            }

            return arrayList;

        }


// ArrayAdapter should always be  ArrayAdapter<String>  though we are using a List. The conte//nts are String. This will throw error if its modified as ArrayAdapter<<List<String>>

        @Override

        protected void onPostExecute(List<String> result) {

            ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(getApplicationContext(),android.R.layout.simple_list_item_1,arrayList);

            listView.setAdapter(arrayAdapter);

        }
    }

}