Monday, June 1, 2015

MV102 Android HttpClient Get Method and Remote JSON Data


.
MV102 Android HttpClient Get Method and Remote JSON Data
This tutorial demonstrates the use of Android HTTPClient to get Remote JSON.
Get Request is sent to the website via REST API.
The website returns JSON output.
The Android Apps parses JSON and display the data in the ListView.
There are buttons to refresh data from remote site and to add a new volunteer name.
A better way of handling the JSON data from the server is by converting them into JSON Object in the Http Handler class. That will be demonstrated at http://android-steps.blogspot.my/2015/06/mv2001-android-httpclient-remote-json.html

0) Starting Up

You need to set up a live website to run the PHP REST Script.
This tutorial uses the free webhosting service www.hostinger.my 
Download the PHP REST Script here and upload to your website.
This tutorial connects to the demo site http://notarazi.esy.es/myvolunteers/api/volunteers.

1) Create a new project

Create a new Android Project and give a name MyVolunteers102.
Select Blank Activity.
Accept the default activity name as MainActivity.
You should get the project files/folders as follows.

2) Add Permission To AndroidManifest

This project requires Internet Permission so that the apps could send data to and receive data from the remote website.
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myvolunteers102"
    android:versionCode="1"
    android:versionName="1.0" >
  <uses-permission android:name="android.permission.INTERNET" />
    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.myvolunteers102.MainActivity"
            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>

3) Resources

3.1) Drawable

Download the following drawable files and place to your resource folder.

3.2) Layouts

We need to edit/create three resource files…
  1. res/layout/activity_main.xml contains the main layout consisting of a listview, an action button to refresh and a button a add new volunteer.
    (action button item must be added to res/menu/activity_main.xml)
  2. res/layout/activity_main_list_item.xml contains the row layout for the listview.
File: res/layout/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"
    tools:context=".MainActivity" >
    <ListView
        android:id="@+id/lvw_persons"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="@string/hello_world" />
    <ImageView
        android:id="@+id/imv_person"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_marginRight="10dp"
        android:layout_marginBottom="10dp"
        android:src="@drawable/person_add_small" />
   
</RelativeLayout>
File:res/menu/activity_main.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
   <item
        android:id="@+id/menu_refresh"
        android:orderInCategory="90"
        android:showAsAction="always"
        android:icon="@drawable/refresh"
        android:title="Refresh"/>
    <item
        android:id="@+id/menu_settings"
        android:orderInCategory="100"
        android:showAsAction="never"
        android:title="@string/menu_settings"/>
</menu>
File: res/layout/activity_main_list_item.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="wrap_content"
   android:orientation="vertical"
   android:padding="10dp"
   android:paddingLeft="10dp"
   android:paddingRight="10dp" >
   <!-- Name Label -->
   <TextView
       android:id="@+id/name"
       android:layout_width="fill_parent"
       android:layout_height="wrap_content"
       android:paddingBottom="2dip"
       android:paddingTop="6dip"
       android:textColor="#43bd00"
       android:textSize="16sp"
       android:textStyle="bold"
       android:text="Name"/>
   <!-- Email label -->
   <TextView
       android:id="@+id/email"
       android:layout_width="fill_parent"
       android:layout_height="wrap_content"
       android:paddingBottom="2dip"
       android:textColor="#acacac"
       android:text="Email"/>
</LinearLayout>
4) Edit Controller Files
Besides MainActivity.java, there is an additional class (ServiceHandler.java) file that will specifically handle the http request (post and get method).
MainActivity will call ServiceHandler to handle post/get method and it will return the JSON data for parsing.
A better way of handling the JSON data from the server is by converting them into JSON Object in the Http Handler class. That will be demonstrated at http://android-steps.blogspot.my/2015/06/mv2001-android-httpclient-remote-json.html

4.1) Create HTTP Handler

File: ServiceHandler.java
package com.example.myvolunteers102;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.List;
public class ServiceHandler {
   static String response = null;
   public final static int GET = 1;
   public final static int POST = 2;
   public ServiceHandler() {
   }
   /**
    * Making service call
    * @url - url to make request
    * @method - http request method
    * */
   public String makeServiceCall(String url, int method) {
       return this.makeServiceCall(url, method, null);
   }
   /**
    * Making service call
    * @url - url to make request
    * @method - http request method
    * @params - http request params
    * */
   public String makeServiceCall(String url, int method,
                                 List<NameValuePair> params) {
       try {
           // http client
           DefaultHttpClient httpClient = new DefaultHttpClient();
           HttpEntity httpEntity = null;
           HttpResponse httpResponse = null;
           // Checking http request method type
           if (method == POST) {
               HttpPost httpPost = new HttpPost(url);
               // adding post params
               if (params != null) {
                   httpPost.setEntity(new UrlEncodedFormEntity(params));
               }
               httpResponse = httpClient.execute(httpPost);
           } else if (method == GET) {
               // appending params to url
               if (params != null) {
                   String paramString = URLEncodedUtils
                           .format(params, "utf-8");
                   url += "?" + paramString;
               }
               HttpGet httpGet = new HttpGet(url);
               httpResponse = httpClient.execute(httpGet);
           }
           httpEntity = httpResponse.getEntity();
           response = EntityUtils.toString(httpEntity);
       } catch (UnsupportedEncodingException e) {
           e.printStackTrace();
       } catch (ClientProtocolException e) {
           e.printStackTrace();
       } catch (IOException e) {
           e.printStackTrace();
       }
       return response;
   }
}

4.2) Edit Main Controller

onCreate method contains a call to set the View Objects (setViewObjects) and a call to execute Get Method Request (getPersons).
Change the url value to your own site.
File: MainActivity.java
package com.example.myvolunteers102;
import java.util.ArrayList;
import java.util.HashMap;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.app.ProgressDialog;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.Toast;
public class MainActivity extends Activity {
           // JSON Node names
           private static final String TAG_PERSONS= "result";
           private static final String TAG_ID = "id";
           private static final String TAG_NAME = "name";
           private static final String TAG_EMAIL = "email";
           // persons JSONArray
           JSONArray persons = null;
           // Hashmap for ListView
           ArrayList<HashMap<String, String>> alsPersons = new ArrayList<HashMap<String, String>>();
           SimpleAdapter adpPersons;
           
           @Override
           protected void onCreate(Bundle savedInstanceState) {
               super.onCreate(savedInstanceState);
               setContentView(R.layout.activity_main);
               setViewObjects();
               new GetPersons().execute();
           }
           
           private void setViewObjects() {
                   //bind ListView
           ListView mListView = (ListView) findViewById(R.id.lvw_persons);
           //set adapter
           adpPersons = new SimpleAdapter(MainActivity.this, alsPersons,
                   R.layout.activity_main_list_item, new String[] { TAG_NAME, TAG_EMAIL,}
                                   , new int[] { R.id.name,R.id.email}
           );
           
           //plug adapter to ListView
           mListView.setAdapter(adpPersons);                
           //bind ImageView
           ImageView imvPerson =(ImageView) findViewById(R.id.imv_person);
           
           //attach onClickListener to ImageView
           imvPerson.setOnClickListener(new View.OnClickListener() {
               public void onClick(View v) {
                       Toast.makeText(getApplicationContext(), "Add Person", Toast.LENGTH_SHORT).show();
               }
           });          
           }
        @Override
           public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.activity_main, menu);
            return true;
           }
           @Override
           public boolean onOptionsItemSelected(MenuItem item) {
               // Handle item selection
               switch (item.getItemId()) {
                   case R.id.menu_settings:
                       //
                   case R.id.menu_refresh:
                           new GetPersons().execute();  
                   default:
                       return super.onOptionsItemSelected(item);
               }
           }          
           /**
            * Async task class to get json by making HTTP call
            * */
           private class GetPersons extends AsyncTask<Void, Void, Void> {
               private ProgressDialog pDialog;
               // URL to get persons JSON
               private String url = "http://notarazi.esy.es/myvolunteers/api/volunteers";
               
               @Override
               protected void onPreExecute() {
                   super.onPreExecute();
                   // Showing progress dialog
                   pDialog = new ProgressDialog(MainActivity.this);
                   pDialog.setMessage("Please wait...");
                   pDialog.setCancelable(false);
                   pDialog.show();
               }
               @Override
               protected Void doInBackground(Void... arg0) {
                   // Creating service handler class instance
                   ServiceHandler sh = new ServiceHandler();
                   // Making a request to url and getting response
                   String jsonStr = sh.makeServiceCall(url, ServiceHandler.GET);
                   Log.d("Response: ", "> " + jsonStr);
                   if (jsonStr != null) {
                       try {
                           JSONObject jsonObj = new JSONObject(jsonStr);
                           // Getting JSON Array node
                           JSONArray arrPersons = jsonObj.getJSONArray(TAG_PERSONS);
                           //reset personList
                           alsPersons.clear();
                           
                           // looping through All Persons
                           for (int i = 0; i < arrPersons.length(); i++) {
                               JSONObject jobPerson = arrPersons.getJSONObject(i);
                               String id = jobPerson.getString(TAG_ID);
                               String name = jobPerson.getString(TAG_NAME);
                               String email = jobPerson.getString(TAG_EMAIL);
                               // tmp hashmap for single person
                               HashMap<String, String> hmpPerson = new HashMap<String, String>();
                               // adding each child node to HashMap key => value
                               hmpPerson.put(TAG_ID, id);
                               hmpPerson.put(TAG_NAME, name);
                               hmpPerson.put(TAG_EMAIL, email);
                               // adding person to person list
                               alsPersons.add(hmpPerson);
                           }
                       } catch (JSONException e) {
                           e.printStackTrace();
                       }
                   } else {
                       Log.e("ServiceHandler", "Couldn't get any data from the url");
                   }
                   return null;
               }
               @Override
               protected void onPostExecute(Void result) {
                   super.onPostExecute(result);
                   // Dismiss the progress dialog
                   if (pDialog.isShowing())
                       pDialog.dismiss();
                   /**
                    * Updating parsed JSON data into ListView
                    * */
                   adpPersons.notifyDataSetChanged();
               }
           }
        }
OUTCOME.
When the apps starts, it will automatically get data from remote site.
If connection is successful, the data will be displayed in the list.
We can refresh the list to get recent data from the remote site.
Later on we will add a new activity for the user to enter a new volunteer.

DOWNLOAD

REFERENCES



.

No comments:

Post a Comment