Android JSON based Web Services tutorial
Android JSON currency convertor Android JSON webservices tutorialANDROID JSON BASED WEB SERVICES TUTORIAL
JSON or JavaScript Object Notation is a lightweight text-based open standard designed for human-readable data interchange. The JSON format was originally specified by Douglas Crockford, and is described in RFC 4627. The official Internet media type for JSON is application/json. The JSON filename extension is .json.
JSON syntax is similar to the JavaScript syntax of java script objects, it includes the following:
Data is represented in name/value pairs
Curly braces hold objects and each name is followed by ':'(colon), the name/value pairs are separated by , (comma).
Square brackets hold arrays and values are separated by ,(comma).
Data is represented in name/value pairs
Curly braces hold objects and each name is followed by ':'(colon), the name/value pairs are separated by , (comma).
Square brackets hold arrays and values are separated by ,(comma).
following provides a simple example:
{
"staff": [
{
"staff_Id":"1",
"dept": "IT",
"specialization": "Computer Science",
"name": "K.Navin"
},
{
"staff_Id":"2",
"dept": "CSE",
"specialization": "Computer Science",
"name": "V.Joseph Raymond"
}, ]
}
Android JSON Parsers
Android provides four differnet classes to manipulate JSON data. These classes areJSONArray,JSONObject,JSONStringer and JSONTokenizer.
The Demonstrative project uses the JSON services from the following url to fetch currency rate between British pound,Indian rupees,U.S dollor and euro .http://www.rate-exchange.appspot.com
"staff": [
{
"staff_Id":"1",
"dept": "IT",
"specialization": "Computer Science",
"name": "K.Navin"
},
{
"staff_Id":"2",
"dept": "CSE",
"specialization": "Computer Science",
"name": "V.Joseph Raymond"
}, ]
}
Android JSON Parsers
Android provides four differnet classes to manipulate JSON data. These classes areJSONArray,JSONObject,JSONStringer and JSONTokenizer.
JSON - Elements
An JSON file consist of many components. Here is the table defining the compoents of an JSON file and their description:
Sl.No | Component & description |
1 | Array([) In a JSON file , square bracket ([) represents a JSON array |
2 | Objects({) In a JSON file, curly bracket ({) represents a JSON object |
3 | Key A JSON object contains a key that is just a string. Pairs of key/value make up a JSON object |
4 | Value Each key has a value that could be string , integer or double e.t.c |
JSON – Parsing
For parsing a JSON object, we will create an object of class JSONObject and specify a string containing JSON data to it. Its syntax is:
String in;
JSONObject reader = new JSONObject(in);
The last step is to parse the JSON. An JSON file consist of different object with different key/value pair e.t.c. So JSONObject has a seperate function for parsing each of the component of JSON file. Its syntax is given below:
ArrayList<HashMap<String, String>>staffList = new ArrayList<HashMap<String, String>>();
// Getting Array of staff details
JSONObject saffs = json.getJSONArray(“staff”);
// looping through All staff details
for(int i = 0; i < staffs.length(); i++){
JSONObject c = staffs.getJSONObject(i);
// Storing each json item in variable
Integer id = c.getString(“staff_id”);
String name = c.getString(“dept”);
String email = c.getString(“specialization”);
String address = c.getString(“name”);
// creating new HashMap
HashMap<String, String> map = new HashMap<String, String>();
// adding each child node to HashMap key => value
map.put(“STAFF_ID”, id);
map.put(“NAME”, name);
map.put(“DEPARTMENT”, email);
map.put(“SPECIALIZATION”, mobile);
// adding HashList to ArrayList
staffList.add(map);
}
The method getJSONObject returns the JSON object. The method getString returns the string value of the specified key.
Apart from the these methods , there are other methods provided by this class for better parsing JSON files. These methods are listed below:
Sr.No | Method & description |
1 | get(String name) This method just Returns the value but in the form of Object type |
2 | getBoolean(String name) This method returns the boolean value specified by the key |
3 | getDouble(String name) This method returns the double value specified by the key |
4 | getInt(String name) This method returns the integer value specified by the key |
5 | getLong(String name) This method returns the long value specified by the key |
6 | length() This method returns the number of name/value mappings in this object.. |
7 | names() This method returns an array containing the string names in this object. |
The Demonstrative project uses the JSON services from the following url to fetch currency rate between British pound,Indian rupees,U.S dollor and euro .http://www.rate-exchange.appspot.com
1.Create Android project with details as listed in the table below.
Property name | Property value |
Project name | SRM_CurrencyConvertorJSON |
Package name | in.ac.srmuniv.currencyconvertorjson |
Activity name | MainActivity |
Layout xml name | main.xml |
2.Copy the code to the file gridview.xml in res/layout folder
<?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:layout_gravity="center_horizontal"
android:gravity="center_horizontal"
android:text="@string/app_name"
android:textSize="@dimen/headsize" />
<TableLayout
android:id="@+id/TableLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="50dp" >
<TableRow
android:id="@+id/tableRow1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:layout_marginLeft="10dp" >
<Spinner
android:id="@+id/spinner1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:drawSelectorOnTop="true"
android:prompt="@string/select_Category"/>
</TableRow>
<TableRow
android:id="@+id/tableRow2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:layout_marginLeft="10dp" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="@string/to"
android:textAppearance="?android:attr/textAppearanceMedium"/>
</TableRow>
<TableRow
android:id="@+id/tableRow3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:layout_marginLeft="10dp"
android:gravity="center_horizontal" >
<Spinner
android:id="@+id/spinner2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"/>
</TableRow>
<TableRow
android:id="@+id/tableRow6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:layout_marginLeft="10dp" >
<Space android:layout_height="20dp"/>
</TableRow>
<TableRow
android:id="@+id/tableRow3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:layout_marginLeft="10dp" >
<TextView
android:id="@+id/textView3"
style="@style/CodeFont"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Enter Value of money to be converted"/>
</TableRow>
</TableLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<EditText
android:id="@+id/editText1"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_marginEnd="40dp"
android:layout_marginLeft="10dp"
android:inputType="numberDecimal"
android:maxLength="4" />
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/convert" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="@+id/textView2"
style="@style/CodeFont"
android:layout_gravity="center_horizontal"
android:gravity="center_horizontal"
android:text="Converted"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textSize="@dimen/out" />
</LinearLayout>
</LinearLayout>
3.Copy the code to the file row.xml in res/layout folder
<?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="1dip" >
<ImageView
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher" />
<TextView
android:id="@+id/country"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_toRightOf="@+id/image"
android:padding="2dip"
android:textColor="@drawable/red"
android:textStyle="bold" />
<TextView
android:id="@+id/currency"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/country"
android:layout_marginLeft="5dip"
android:layout_toRightOf="@+id/image"
android:padding="2dip"
android:textColor="@drawable/darkgrey" />
</RelativeLayout>
4.Copy the code in MainActivity.java. Activity.
packagein.ac.srmuniv.currencyconvertorjson;
importin.ac.srmuniv.currencyconvertorjson.R;
importandroid.app.Activity;
importandroid.app.ProgressDialog;
importandroid.content.Context;
importandroid.os.AsyncTask;
import android.os.Bundle;
importandroid.view.LayoutInflater;
import android.view.View;
importandroid.view.ViewGroup;
importandroid.widget.AdapterView;
importandroid.widget.AdapterView.OnItemSelectedListener;
importandroid.widget.ArrayAdapter;
import android.widget.Button;
importandroid.widget.EditText;
importandroid.widget.ImageView;
importandroid.widget.Spinner;
importandroid.widget.TextView;
importandroid.widget.Toast;
public class MainActivity extends Activity {
String[] country = { "British", "European", "American", "Indian" };
String[] currency = { "Pounds ", "Euro", "Dollor", "Rupee" };
String[] currency_abr = { "GBP", "EUR", "USD", "INR" };
String to_curr, from_curr;
int arr_images[] = { R.drawable.pound, R.drawable.euro, R.drawable.dollor,
R.drawable.rupee };
TextView converted;
Spinner from_currency;
Spinner to_currency;
EditText input;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
to_curr = "INR";
from_curr = "USD";
setContentView(R.layout.activity_main);
converted = (TextView) findViewById(R.id.textView2);
input = (EditText) findViewById(R.id.editText1);
converted.setText("");
from_currency = (Spinner) findViewById(R.id.spinner1);
from_currency.setAdapter(newMyAdapter(MainActivity.this, R.layout.row,
country));
from_currency.setSelection(2);
to_currency = (Spinner) findViewById(R.id.spinner2);
to_currency.setAdapter(newMyAdapter(MainActivity.this, R.layout.row,
country));
to_currency.setSelection(3);
from_currency.setOnItemSelectedListener(newOnItemSelectedListener() {
public voidonItemSelected(AdapterView<?> parentView, View v,
int position, long id) {
Toast.makeText(getApplicationContext(),
"" + currency_abr[position], Toast.LENGTH_LONG).show();
converted.setHint(currency[position]);
from_curr = currency_abr[position];
}
public voidonNothingSelected(AdapterView<?> parentView) {
// your code here
}
});
to_currency.setOnItemSelectedListener(newOnItemSelectedListener() {
public voidonItemSelected(AdapterView<?> parentView, View v,
int position, long id) {
Toast.makeText(getApplicationContext(),
"" + currency_abr[position], Toast.LENGTH_LONG).show();
converted.setHint(currency[position]);
to_curr = currency_abr[position];
}
public voidonNothingSelected(AdapterView<?> parentView) {
// your code here
}
});
Button button = (Button) findViewById(R.id.button1);
button.setOnClickListener(newView.OnClickListener() {
@Override
public void onClick(View v) {
newDownloadData().execute(to_curr, from_curr, input.getText()
.toString());
}
});
converted = (TextView) findViewById(R.id.textView2);
}
class DownloadData extends AsyncTask<String, String, Double> {
ProgressDialog pd = null;
@Override
protected void onPreExecute() {
super.onPreExecute();
pd = newProgressDialog(MainActivity.this);
pd.setTitle("Converting...");
pd.setMessage("Please wait...");
pd.setCancelable(false);
pd.show();
}
@Override
protected Double doInBackground(String... params) {
String to_curr = params[0];
String from_curr = params[1];
String value = params[2];
// Creating JSON Parser instance
JSONParser jParser = new JSONParser();
// getting JSON string from URL
jParser.getJSONFromUrl("http://www.currency-api.appspot.com /api/"+from_curr+"/"+ to_curr +".json");
jParser.getJSONFromUrl("http://www.currency-api.appspot.com /api/"+from_curr+"/"+ to_curr +".json");
/*
jParser.getJSONFromUrl("http://www.rate-exchange.appspot.com/currency?from="
+ from_curr + "&to=" + to_curr + "&q=" + value);not supported now
jParser.getJSONFromUrl("http://www.rate-exchange.appspot.com/currency?from="
+ from_curr + "&to=" + to_curr + "&q=" + value);not supported now
* JSONObject json = jParser
* .getJSONFromUrl("http://www.google.com/ig/calculator?hl=en&q=" +
* value + from_curr + "=" + to_curr + "?"); //Google stopped
* service from Nov 1 2013
*/
double theResult = jParser.getResult();
return theResult;
}
@Override
protected void onPostExecute(Double theResult) {
super.onPostExecute(theResult);
pd.dismiss();
/*
* double x; try { x = Double.parseDouble(theResult); } catch
* (NumberFormatException e) { // TODO Auto-generated catch block x
* = 1; input.setText(""); }
*/
converted.setText(theResult.toString());
}
}
public class MyAdapter extendsArrayAdapter<String> {
public MyAdapter(Context context, int textViewResourceId,
String[] objects) {
super(context, textViewResourceId, objects);
}
@Override
public View getDropDownView(int position, View convertView,
ViewGroup parent) {
returngetCustomView(position, convertView, parent);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
returngetCustomView(position, convertView, parent);
}
public View getCustomView(int position, View convertView,
ViewGroup parent) {
LayoutInflater inflater = getLayoutInflater();
View row = inflater.inflate(R.layout.row, parent, false);
TextView label = (TextView) row.findViewById(R.id.country);
label.setText(country[position]);
TextView sub = (TextView) row.findViewById(R.id.currency);
sub.setText(currency[position]);
ImageView icon = (ImageView) row.findViewById(R.id.image);
icon.setImageResource(arr_images[position]);
return row;
}
}
}
5.Create a class JSONParser.java copy the follwwing code
packagein.ac.srmuniv.currencyconvertorjson;
importjava.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
importjava.io.InputStreamReader;
importjava.io.UnsupportedEncodingException;
importorg.apache.http.HttpEntity;
importorg.apache.http.HttpResponse;
importorg.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
//import org.apache.http.client.methods.HttpPost;
importorg.apache.http.impl.client.DefaultHttpClient;
importorg.json.JSONException;
import org.json.JSONObject;
import android.util.Log;
public class JSONParser {
static InputStream is = null;
JSONObject jObj = null;
// constructor
public JSONParser() {
}
public voidgetJSONFromUrl(String url) {
String json = "";
// Making HTTP request
try {
// defaultHttpClient
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
// HttpPost httpPost = new HttpPost(url);// For google currency convertornow depricated
HttpResponse httpResponse = httpClient.execute(httpGet);
HttpEntity httpEntity = httpResponse.getEntity();
is = httpEntity.getContent();
} catch(UnsupportedEncodingException e) {
e.printStackTrace();
} catch(ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(
is, "iso-8859-1"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
json = sb.toString();
Log.d("JSON result", json);
} catch (Exception e) {
Log.e("Buffer Error", "Error converting result " + e.toString());
}
// try parse the string to a JSON object
try {
jObj = new JSONObject(json);
} catch (JSONException e) {
Log.e("JSON Parser", "Error parsing data " + e.toString());
}
}
double getResult() {
double theResult = 0.0;
try {
//theResult = jObj.getDouble("v");
theResult = jObj.getDouble("rate");
//theResult = jObj.getDouble("v");
theResult = jObj.getDouble("rate");
System.out.println(theResult);
}
catch (JSONException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return theResult;
}
}
4.Modify Androidmanifest.xml
<?xml version="1.0"encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="in.ac.srmuniv.currencyconvertorjson"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/MyTheme" >
<activity
android:name=".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>
6.Copy the code to the file string.xml in res/values folder <?xml version="1.0"encoding="utf-8"?>
<resources>
<string name="app_name">SRM_CurrencyConvertorJSON</string>
<string name="action_settings">Settings</string>
<string name="hello_world">Hello world!</string>
<drawable name="white">#ffffff</drawable>
<drawable name="black">#000000</drawable>
<drawable name="green">#347C2C</drawable>
<drawable name="pink">#FF00FF</drawable>
<drawable name="violet">#a020f0</drawable>
<drawable name="grey">#778899</drawable>
<drawable name="red">#C11B17</drawable>
<drawable name="yellow">#FFFF8C</drawable>
<drawable name="PowderBlue">#b0e0e6</drawable>
<drawable name="brown">#2F1700</drawable>
<drawable name="Hotpink">#7D2252</drawable>
<string name="select_Category">Select Category</string>
<drawable name="darkgrey">#606060</drawable>
<string name="to">to</string>
<string name="convert">Convert</string>
<color name="bk">#F0E0D0</color>
</resources>
7.Copy the code to the file dimens.xml in res/values folder
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="convert">20sp</dimen>
<dimen name="out">70sp</dimen>
<dimen name="headsize">22sp</dimen>
</resources>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<!--
Base application theme, dependent on API level. This theme is replaced
by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
-->
<style name="AppBaseTheme"parent="android:Theme.Light">
<!--
Theme customizations available in newer API levels can go in
res/values-vXX/styles.xml, while customizations related to
backward-compatibility can go here.
-->
</style>
<!-- Application theme. -->
<style name="AppTheme"parent="AppBaseTheme">
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
</style>
<style name="CustomTheme"parent="android:Theme">
<item name="android:windowTitleSize">40dip</item>
<item name="android:windowTitleBackgroundStyle">@style/AppTheme</item>
</style>
<style name="MyTheme"parent="android:Theme.Light">
<item name="android:windowNoTitle">true</item>
<item name="android:windowBackground">@color/bk</item>
<item name="android:listViewStyle">@style/MySpinnerView</item>
</style>
<style name="MySpinnerView"parent="@android:style/Widget.Spinner">
<item name="android:spinnersShown">@drawable/euro</item>
</style>
<style name="CodeFont"parent="@android:style/TextAppearance.Medium">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">fill_parent</item>
<item name="android:textColor">#00BFA0</item>
<item name="android:typeface">monospace</item>
</style>
</resources>
9.Run the device/emulator with internet connection available
Fig 1 Shows the JSON based currency convertor app taking currency rate from www.rate-exchange.appspot.com a google appengine based service
CODE EXPLANATION9.Run the device/emulator with internet connection available
Fig 1 Shows the JSON based currency convertor app taking currency rate from www.rate-exchange.appspot.com a google appengine based service
The currency convertor app has Mainactivity which contains appropriate UI.User can select currencies through spinners and value entered through editText.The values are appended to URL of json based webservice.MainActivity uses AsyncTask for making webservice request and fetching result.
Figure 2 Shows the rate -exchange google appengine based json webservice
JSONParser class uses HttpClient class with HttpGet method to send values of from_currency ,to_currency and the amount of value to be converted. try {
// defaultHttpClient
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
// HttpPost httpPost = new HttpPost(url);// For google currency
// convertor now depricated
HttpResponse httpResponse = httpClient.execute(httpGet);
HttpEntity httpEntity = httpResponse.getEntity();
is = httpEntity.getContent();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}The response received from http://www.rate-exchange.appspot.com is stored in String and passed as argument to the constructor of JSONObject.The following is the received json object for the get request
{"to": "INR", "rate": 61.491999999999997, "from": "USD", "v": 614.91999999999996}
// try parse the string to a JSON object
try {
jObj = new JSONObject(json);
} catch (JSONException e) {
Log.e("JSON Parser", "Error parsing data " + e.toString());
}
.....
.....
JSONObject jObj contains various attributes but we are concerned with the attribute "v" which contains the converted rate multiplied with value .The method getDouble returns the double value for the specified key "v".
try {
theResult = jObj.getDouble("v");
System.out.println(theResult);
}
catch (JSONException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}