Consuming Webservices - Weather Demo

/* This code is Based on example given by M. Murphy CommonsWare, LLC

"The Busy Coder's Guide To Android Development" V3.4 Chapter 29.

App has been modified to get the weather forecast of a particular

location (no GPS). The elements included in the response object

are briefly shown as an array of nodes.

*/

packagecom.commonsware.android.internet;

importjava.io.StringReader;

importjava.util.ArrayList;

importjava.util.List;

importjavax.xml.parsers.DocumentBuilder;

importjavax.xml.parsers.DocumentBuilderFactory;

importorg.apache.http.client.HttpClient;

importorg.apache.http.client.ResponseHandler;

importorg.apache.http.client.methods.HttpGet;

importorg.apache.http.impl.client.BasicResponseHandler;

importorg.apache.http.impl.client.DefaultHttpClient;

import org.w3c.dom.Document;

import org.w3c.dom.Element;

import org.w3c.dom.NodeList;

importorg.xml.sax.InputSource;

importandroid.app.Activity;

importandroid.location.Location;

importandroid.location.LocationListener;

importandroid.location.LocationManager;

importandroid.os.Bundle;

importandroid.util.Log;

importandroid.webkit.WebView;

publicclassWeatherDemoextends Activity {

private String format;

privateWebViewbrowser;

privateHttpClientclient;

private List<Forecast> forecasts = newArrayList<Forecast>();

@Override

publicvoidonCreate(Bundle icicle) {

super.onCreate(icicle);

setContentView(R.layout.main);

format = getString(R.string.url);

browser = (WebView) findViewById(R.id.webkit);

client = newDefaultHttpClient();

}

@Override

publicvoidonResume() {

super.onResume();

// provide coordinates of a given location

Location loc = newLocation("CLEVELAND AERA");

loc.setLatitude(41.4797);

loc.setLongitude(-81.6785);

updateForecast(loc);

}

privatevoidupdateForecast(Location loc) {

//obtaining forecast for given region

String url = String.format(format,

loc.getLatitude(),

loc.getLongitude());

Log.e("URL value: ", url );

HttpGetgetMethod = newHttpGet(url);

try {

ResponseHandler<String> responseHandler = newBasicResponseHandler();

String responseBody = client.execute(getMethod, responseHandler);

buildForecasts(responseBody);

String page = generatePage();

browser.loadDataWithBaseURL(null, page, "text/html", "UTF-8", null);

} catch (Throwable t) {

Log.e("ERROR", t.toString() );

browser.loadData("<html<body>" + t.toString() + "</body</html>",

"text/html",

"UTF-8");

}//updateForecast

}

// //////////////////////////////////////////////////////////////////////////

voidbuildForecasts(String raw) throws Exception {

DocumentBuilder builder = DocumentBuilderFactory.newInstance()

.newDocumentBuilder();

Document doc = builder.parse(newInputSource(newStringReader(raw)));

NodeList times = doc.getElementsByTagName("start-valid-time");

for (inti = 0; itimes.getLength(); i++) {

Element time = (Element) times.item(i);

Forecast forecast = newForecast();

forecasts.add(forecast);

forecast.setTime(time.getFirstChild().getNodeValue());

}

NodeList temps = doc.getElementsByTagName("value");

for (inti = 0; itemps.getLength(); i++) {

Element temp = (Element) temps.item(i);

Forecast forecast = forecasts.get(i);

forecast.setTemp(new Integer(temp.getFirstChild().getNodeValue()));

}

NodeList icons = doc.getElementsByTagName("icon-link");

for (inti = 0; iicons.getLength(); i++) {

Element icon = (Element) icons.item(i);

Forecast forecast = forecasts.get(i);

forecast.setIcon(icon.getFirstChild().getNodeValue());

}

}

String generatePage() {

StringBufferbufResult = newStringBuffer("<html<body<table>");

bufResult.append("<trth width=\"50%\">Time</th>"

+ "<thTemperature</thth>Forecast</th</tr>");

for (Forecast forecast : forecasts) {

bufResult.append("<tr<td align=\"center\">");

bufResult.append(forecast.getTime());

bufResult.append("</td<td align=\"center\">");

bufResult.append(forecast.getTemp());

bufResult.append("</td<td<imgsrc=\"");

bufResult.append(forecast.getIcon());

bufResult.append("\"</td</tr>");

}

bufResult.append("</table</body</html>");

return (bufResult.toString());

}

/////////////////////////////////////////////////////////////////

class Forecast {

String time = "";

Integer temp = null;

String iconUrl = "";

String getTime() {

return (time);

}

voidsetTime(String time) {

this.time = time.substring(0, 16).replace('T', ' ');

}

Integer getTemp() {

return (temp);

}

voidsetTemp(Integer temp) {

this.temp = temp;

}

String getIcon() {

return (iconUrl);

}

voidsetIcon(String iconUrl) {

this.iconUrl = iconUrl;

}

}

}//Forecast

Layout

<?xmlversion="1.0"encoding="utf-8"?>

WebViewxmlns:android="

android:id="@+id/webkit"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

/>

Manifest – Permission(s)

manifestxmlns:android="

package="com.commonsware.android.internet"

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

uses-sdkandroid:minSdkVersion="4"/>

application

activityandroid:name=".WeatherDemo"android:label="WeatherDemo"

intent-filter

actionandroid:name="android.intent.action.MAIN"/>

categoryandroid:name="android.intent.category.LAUNCHER"/>

</intent-filter

</activity

</application

</manifest

WEB SERVICES

REQUEST (HttpGetsent to website using IExplorer)

RESPONSE

<?xml version="1.0" ?>

-dwml version="1.0"xmlns:xsd="" xsi:noNamespaceSchemaLocation="">

-head

-product srsName="WGS 1984" concise-name="time-series" operational-mode="official">

titleNOAA's National Weather Service Forecast Data</title

fieldmeteorological</field

categoryforecast</category

creation-date refresh-frequency="PT1H">2011-02-17T16:28:30Z</creation-date

</product

+source

more-information</more-information

-production-center

Meteorological Development Laboratory

sub-centerProduct Generation Branch</sub-center

</production-center

disclaimer</disclaimer

credit</credit

credit-logo</credit-logo

feedback</feedback

</source

</head

-data

-location

location-keypoint1</location-key

pointlatitude="41.48" longitude="-81.68" />

</location

moreWeatherInformation applicable-location="point1"></moreWeatherInformation

-time-layout time-coordinate="local" summarization="none">

layout-keyk-p3h-n35-1</layout-key

start-valid-time2011-02-17T13:00:00-05:00</start-valid-time

start-valid-time2011-02-17T16:00:00-05:00</start-valid-time

start-valid-time2011-02-17T19:00:00-05:00</start-valid-time

start-valid-time2011-02-17T22:00:00-05:00</start-valid-time

start-valid-time2011-02-18T01:00:00-05:00</start-valid-time

start-valid-time2011-02-18T04:00:00-05:00</start-valid-time

start-valid-time2011-02-18T07:00:00-05:00</start-valid-time

start-valid-time2011-02-18T10:00:00-05:00</start-valid-time

start-valid-time2011-02-18T13:00:00-05:00</start-valid-time

start-valid-time2011-02-18T16:00:00-05:00</start-valid-time

start-valid-time2011-02-18T19:00:00-05:00</start-valid-time

start-valid-time2011-02-18T22:00:00-05:00</start-valid-time

start-valid-time2011-02-19T01:00:00-05:00</start-valid-time

start-valid-time2011-02-19T04:00:00-05:00</start-valid-time

start-valid-time2011-02-19T07:00:00-05:00</start-valid-time

start-valid-time2011-02-19T10:00:00-05:00</start-valid-time

start-valid-time2011-02-19T13:00:00-05:00</start-valid-time

start-valid-time2011-02-19T16:00:00-05:00</start-valid-time

start-valid-time2011-02-19T19:00:00-05:00</start-valid-time

start-valid-time2011-02-20T01:00:00-05:00</start-valid-time

start-valid-time2011-02-20T07:00:00-05:00</start-valid-time

start-valid-time2011-02-20T13:00:00-05:00</start-valid-time

start-valid-time2011-02-20T19:00:00-05:00</start-valid-time

start-valid-time2011-02-21T01:00:00-05:00</start-valid-time

start-valid-time2011-02-21T07:00:00-05:00</start-valid-time

start-valid-time2011-02-21T13:00:00-05:00</start-valid-time

start-valid-time2011-02-21T19:00:00-05:00</start-valid-time

start-valid-time2011-02-22T01:00:00-05:00</start-valid-time

start-valid-time2011-02-22T07:00:00-05:00</start-valid-time

start-valid-time2011-02-22T13:00:00-05:00</start-valid-time

start-valid-time2011-02-22T19:00:00-05:00</start-valid-time

start-valid-time2011-02-23T01:00:00-05:00</start-valid-time

start-valid-time2011-02-23T07:00:00-05:00</start-valid-time

start-valid-time2011-02-23T13:00:00-05:00</start-valid-time

start-valid-time2011-02-23T19:00:00-05:00</start-valid-time

</time-layout

-parameters applicable-location="point1">

-temperature type="hourly" units="Fahrenheit" time-layout="k-p3h-n35-1">

nameTemperature</name

value57</value

value57</value

value52</value

value49</value

value48</value

value46</value

value46</value

value49</value

value53</value

value51</value

value41</value

value36</value

value33</value

value31</value

value29</value

value33</value

value37</value

value37</value

value33</value

value29</value

value28</value

value38</value

value33</value

value29</value

value27</value

value33</value

value29</value

value26</value

value25</value

value34</value

value29</value

value24</value

value23</value

value35</value

value33</value

</temperature

-conditions-icon type="forecast-NWS" time-layout="k-p3h-n35-1">

nameConditions Icons</name

icon-link</icon-link

icon-link</icon-link

icon-link</icon-link

icon-link</icon-link

icon-link</icon-link

icon-link</icon-link

icon-link</icon-link

icon-link</icon-link

icon-link</icon-link

icon-link</icon-link

icon-link</icon-link

icon-link</icon-link

icon-link</icon-link

icon-link</icon-link

icon-link</icon-link

icon-link</icon-link

icon-link</icon-link

icon-link</icon-link

icon-link</icon-link

icon-link</icon-link

icon-link</icon-link

icon-link</icon-link

icon-link</icon-link

icon-link</icon-link

icon-link</icon-link

icon-link</icon-link

icon-link</icon-link

icon-link</icon-link

icon-link</icon-link

icon-link</icon-link

icon-link</icon-link

icon-link</icon-link

icon-link</icon-link

icon-link</icon-link

icon-link</icon-link

</conditions-icon

</parameters

</data

</dwml

MONEY EXCHANGE (RSS agent)

// Using RSS to find the current rate of exchange for USD

// data taken from

// example uses background thread for slow internet process

// and foreground thread for GUI management

// ------

package cis493.testa;

import java.io.IOException;

import java.io.InputStream;

import java.net.HttpURLConnection;

import java.net.MalformedURLException;

import java.net.URL;

import java.net.URLConnection;

import java.util.ArrayList;

import javax.xml.parsers.DocumentBuilder;

import javax.xml.parsers.DocumentBuilderFactory;

import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.DOMException;

import org.w3c.dom.Document;

import org.w3c.dom.Element;

import org.w3c.dom.NodeList;

import org.xml.sax.SAXException;

import android.app.ListActivity;

import android.content.Context;

import android.os.Bundle;

import android.os.Handler;

import android.util.Log;

import android.view.View;

import android.widget.ArrayAdapter;

import android.widget.ListView;

import android.widget.ProgressBar;

import android.widget.TextView;

import android.widget.Toast;

public class USD_Exchange extends ListActivity {

ArrayList<SingleNewsItem> newsList = new ArrayList<SingleNewsItem>();

ArrayAdapter<String> aa;

String exchangeDate = "";

ProgressBar myBar1;

Handler myHandler = new Handler();

Context myMainContext;

TextView myMsg;

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

// show circular progress bar while other things are done

myBar1 = (ProgressBar)findViewById(R.id.myProgress1);

myMsg = (TextView) findViewById(R.id.myMsg);

myMainContext = getApplicationContext();

}//onCreate

@Override

protected void onListItemClick(ListView l, View v, int position, long id) {

super.onListItemClick(l, v, position, id);

try {

String text = "Position: " + position

+ "\n"

+ newsList.get(position).getDescription();

Toast.makeText(this, text, 1).show();

// do something useful with the data

} catch (Exception e) {

Log.e("<EXCHANGE ERROR>", e.getMessage());

}

}

@Override

protected void onStart() {

super.onStart();

// create background thread were the busy work will be done

Thread myThread1 = new Thread(backgroundTask, "getRssMoneyData" );

myThread1.start();

}

/////////////////////////////////////////////////////////////////////

//this is the "Runnable" object that executes the background thread

private Runnable backgroundTask = new Runnable () {

@Override

public void run() {

//busy work goes here...

try {

getRssPopulateListView();

myHandler.post(foregroundTask);

}

catch (Exception e) {

e.printStackTrace();

}

}//run

};//backgroundTask

// //////////////////////////////////////////////////////////////////

// this is the foreground "Runnable" object responsible for the GUI

// when RSS process is it shows list and removes circular progress bar

private Runnable foregroundTask = new Runnable() {

@Override

public void run() {

try {

myMsg.setText(exchangeDate);

myBar1.setVisibility(View.INVISIBLE);

// use your own (small font) layout to show a single row

int layoutID = R.layout.my_simple_list_item_1;

// show on a ListView news held in ArrayList just assembled

ArrayAdapter<SingleNewsItem> aaNews =

new ArrayAdapter<SingleNewsItem>(

myMainContext,

layoutID,

newsList);

setListAdapter(aaNews);

}

catch (Exception e) {

e.printStackTrace();

}

}

}; //foregroundTask

/////////////////////////////////////////////////////////////////////

public void getRssPopulateListView(){

try {

// go to web site, pickup RSS feed

URL url = new URL("

URLConnection connection;

connection = url.openConnection();

HttpURLConnection httpConnection = (HttpURLConnection) connection;

int responseCode = httpConnection.getResponseCode();

if (responseCode == HttpURLConnection.HTTP_OK) {

InputStream in = httpConnection.getInputStream();

DocumentBuilderFactory dbf = DocumentBuilderFactory

.newInstance();

DocumentBuilder db = dbf.newDocumentBuilder();

// create an parse tree for the XML input stream

Document dom = db.parse(in);

// this will be a single node in the tree

Element docEle = dom.getDocumentElement();

// extract individual exchange values

// such as: (1 US Dollar = xx other currency)

NodeList nl = docEle.getElementsByTagName("item");

if ((nl != null) & (nl.getLength() > 0)) {

for (int i = 0; i < nl.getLength(); i++) {

dissectNode(nl, i);

}// for

}// if

}// if

} catch (MalformedURLException e) {

Log.v("1-disecting", e.getMessage());

} catch (IOException e) {

Log.v("2-disecting", e.getMessage());

} catch (ParserConfigurationException e) {

Log.v("3-disecting", e.getMessage());

} catch (SAXException e) {

Log.v("4-disecting", e.getMessage());

}

}

/////////////////////////////////////////////////////////////////

public void dissectNode(NodeList nl, int i){

// examine input collection (NodeList) holding items,

// get from each news item the first child of elements:

// title, description, pubData, link. Put those pieces

// together into a SingleNewsItem object and add it to

// the ArrayList called: newsList

try {

Element entry = (Element) nl.item(i);

Element title = (Element) entry.getElementsByTagName(

"title").item(0);

Element description = (Element) entry.getElementsByTagName(

"description").item(0);

Element pubDate = (Element) entry.getElementsByTagName(

"pubDate").item(0);

Element link = (Element) entry.getElementsByTagName(

"link").item(0);

String titleValue = title.getFirstChild().getNodeValue();

String descriptionValue =description.getFirstChild().getNodeValue();

String dateValue = pubDate.getFirstChild().getNodeValue();

String linkValue = link.getFirstChild().getNodeValue();

// combine title & description for a simple ListView

titleValue += "\n " + descriptionValue;

if (exchangeDate.length()==0){

exchangeDate = dateValue;

}

// assemble 'singleItems' add each to the collection

SingleNewsItem singleItem = new SingleNewsItem(

dateValue,titleValue,descriptionValue, linkValue);

newsList.add(singleItem);

} catch (DOMException e) {

e.printStackTrace();

}

}//dissectNode

}//class

MAIN LAYOUT

<?xmlversion="1.0"encoding="utf-8"?>

LinearLayoutxmlns:android="

android:orientation="vertical"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

LinearLayout

android:orientation="horizontal"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:background="#ff006666"

ProgressBar

android:id="@+id/myProgress1"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_margin="5px"

style="?android:attr/android:progressBarStyleSmall"/>

TextView

android:id="@+id/myMsg"

android:text="Please wait ..."

android:layout_width="fill_parent"

android:layout_height="fill_parent"/>

</LinearLayout

ListView

android:id="@android:id/list"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:drawSelectorOnTop="false"

/>

</LinearLayout

my_simple_list_line_1.xml (small font)

<?xmlversion="1.0"encoding="utf-8"?>

TextViewxmlns:android="

android:id="@android:id/text1"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:gravity="center_vertical"

android:paddingLeft="10dip"

android:textSize="14sp"

android:minHeight="40sp"

/>

Manifest

<?xmlversion="1.0"encoding="utf-8"?>

manifestxmlns:android="

package="cis493.testa"

android:versionCode="1"

android:versionName="1.0"

applicationandroid:icon="@drawable/icon"android:label="@string/app_name"

activityandroid:name=".USD_Exchange"

android:label="@string/app_name"

intent-filter

actionandroid:name="android.intent.action.MAIN"/>

categoryandroid:name="android.intent.category.LAUNCHER"/>

</intent-filter

</activity

</application

uses-sdkandroid:minSdkVersion="8"/>

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

</manifest

Fragment of [ response ] RSS XML file received by client

<?xml version="1.0" encoding="utf-8"?>

<?xml-stylesheet type="text/css" href="../css/rss.css" ?>

<rss version="2.0" xmlns:atom="

<channel>

<title>Exchange Rates For US Dollar</title>

<link>

<description>The latest currency exchange rates for US Dollar</description>

<lastBuildDate>Thu, 17 Feb 2011 21:15:39 GMT</lastBuildDate>

<language>en-us</language>

<copyright>Copyright: (C) The Money Converter, see </copyright>

<docs>

<ttl>15</ttl<image>

<title>Exchange Rates For US Dollar</title>

<url>

<link>

<item>

<title>AED/USD</title<link>

<guid>e4600198-9686-4cfa-b20d-fb8a31919420</guid>

<pubDate>Thu, 17 Feb 2011 21:15:39 GMT</pubDate>

<description>1 US Dollar = 3.6725 United Arab Emirates Dirham</description>

<category>Middle East</category>

</item>

<item>

<title>ARS/USD</title<link>

<guid>7d01193a-a366-4cde-ac37-caec09d6faae</guid>

<pubDate>Thu, 17 Feb 2011 21:15:39 GMT</pubDate>

<description>1 US Dollar = 4.02397 Argentine Peso</description>

<category>South America</category>

</item>

CONSUMING WEB SERVICES PLACED IN AN APACAHE TOMCAT 7.0 SERVER

This example assumes you have installed the Apache Tomcat 7.0 Server in your computer

(Download from: The server comes with a set of samples located in the folder C:\Program Files\Apache Software Foundation\Tomcat 7.0\webapps\examples\servlets

(assuming you installed on Windows, using Program Files directory).

In this sample the webservices are implemented in Java Servlets. One of them is the requestParamentersExample.

{[execute.gif]}{[return.gif]}

Source Code for Request Parameter Example

import java.io.*;

import java.util.*;

import javax.servlet.*;

import javax.servlet.http.*;

public class RequestParamExample extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws IOException, ServletException

{

response.setContentType("text/html");

PrintWriter out = response.getWriter();

out.println("<html>");

out.println("<head>");

out.println("<title>Request Parameters Example</title>");

out.println("</head>");

out.println("<body>");

out.println("<h3>Request Parameters Example</h3>");

out.println("Parameters in this request:<br>");

if (firstName != null || lastName != null) {

out.println("First Name:");

out.println(" = " + HTMLFilter.filter(firstName) + "<br>");

out.println("Last Name:");

out.println(" = " + HTMLFilter.filter(lastName));

} else {

out.println("No Parameters, Please enter some");

}

out.println("<P>");

out.print("<form action=\"");

out.print("RequestParamExample\" ");

out.println("method=POST>");

out.println("First Name:");

out.println("<input type=text size=20 name=firstname>");

out.println("<br>");

out.println("Last Name:");

out.println("<input type=text size=20 name=lastname>");

out.println("<br>");

out.println("<input type=submit>");

out.println("</form>");

out.println("</body>");

out.println("</html>");

}

public void doPost(HttpServletRequest request, HttpServletResponse response)

throws IOException, ServletException

{

doGet(request, response);

}

}

In the example we need to supply first and last name. The request object is sent to the service, the arguments are extracted and echoed back to the user in a response object. The response is a well formed HTML document. In our Android application we drop the response into a WebView for displaying.

For the sake of the example assume the web server’s IP address is 192.169.0.183. When using the Android emulator we cannot use the url neither (the connection will be refused because of collisions with the emulator). Insteac you will have to provide a ‘real’ IP url.

Layout

<?xmlversion="1.0"encoding="utf-8"?>

WebViewxmlns:android="

android:id="@+id/webkit"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

</WebView

Manifest needs Internet permission

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

Code

// Consuming a web-service residing in an local Apache Tomcat server

// WebService is a sample that comes with the installation package.

// The example asks for user's first & last name.

// The response is a valid HTML file that echoes the input values.

// ------

package ucr.netdemo1;

import. . .

publicclass Main extends Activity {

TextViewtextView;

WebViewbrowser;

publicenumRequestMethod {

GET, POST

}

@Override

publicvoidonCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

Toast.makeText(this,

"Warning!\nThis code needs your Apache server's current IP.", 1).show();

browser = (WebView) findViewById(R.id.webkit);

useMethod1();// try this method first

// useMethod2(); // try this method next

}// onCreate

// ======

// VERSION 1.

// You assemble the URL. Separate arguments with a '$' sign. Arguments are

// pair of name=value elements (eg. firstname=maria)

// Based on:

publicvoid useMethod1() {

// url consists of: link2WebServRepository?servletName&argument(s)

String url = "

+ "RequestParamExample?firstname=Maria1&lastname=Macarena1";

try {

DefaultHttpClient client = newDefaultHttpClient();

URI uri = newURI(url);

HttpGetmethodGet = newHttpGet(uri);

HttpResponse response = client.execute(methodGet);

InputStreamisResponseData = response.getEntity().getContent();