In my old posts, demonstrate how to "
Search WOEID from http://query.yahooapis.com/" and "
Get weather info from Yahoo! Weather RSS Feed". This exercise merge both together.
User enter location to be searched for WOEID, then clicked the WOEID to start another activity querying Yahoo for the weather.
And also, the code to read from internet have been moved to AsyncTask to prevent from
NetworkOnMainThreadException.
Main activity, MainActivity.java.
package com.example.androidwoeidweather;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.http.HttpEntity;
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.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;
import android.app.Activity;
import android.content.Intent;
public class MainActivity extends Activity {
//Example for "New York"
//http://query.yahooapis.com/v1/public/yql?q=select*from geo.places where text="New York"&format=xml
final String yahooPlaceApisBase = "http://query.yahooapis.com/v1/public/yql?q=select*from%20geo.places%20where%20text=";
final String yahooapisFormat = "&format=xml";
String yahooPlaceAPIsQuery;
EditText place;
Button search;
ListView listviewWOEID;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
place = (EditText)findViewById(R.id.place);
search = (Button)findViewById(R.id.search);
listviewWOEID = (ListView)findViewById(R.id.woeidlist);
search.setOnClickListener(searchOnClickListener);
}
Button.OnClickListener searchOnClickListener
= new Button.OnClickListener(){
@Override
public void onClick(View arg0) {
if(place.getText().toString().equals("")){
Toast.makeText(getBaseContext(),
"Enter place!",
Toast.LENGTH_LONG).show();
}else{
new MyQueryYahooPlaceTask().execute();
}
}
};
private class MyQueryYahooPlaceTask extends AsyncTask<Void, Void, Void>{
ArrayList<String> l;
@Override
protected Void doInBackground(Void... arg0) {
l = QueryYahooPlaceAPIs();
return null;
}
@Override
protected void onPostExecute(Void result) {
ArrayAdapter<String> aa = new ArrayAdapter<String>(
getBaseContext(), android.R.layout.simple_list_item_1, l);
listviewWOEID.setAdapter(aa);
listviewWOEID.setOnItemClickListener(new OnItemClickListener(){
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
String selWoeid = parent.getItemAtPosition(position).toString();
/*
Toast.makeText(getApplicationContext(),
selWoeid,
Toast.LENGTH_LONG).show();
*/
Intent intent = new Intent();
intent.setClass(MainActivity.this, GetWeather.class);
Bundle bundle = new Bundle();
bundle.putCharSequence("SEL_WOEID", selWoeid);
intent.putExtras(bundle);
startActivity(intent);
}});
super.onPostExecute(result);
}
}
private ArrayList<String> QueryYahooPlaceAPIs(){
String uriPlace = Uri.encode(place.getText().toString());
yahooPlaceAPIsQuery = yahooPlaceApisBase
+ "%22" + uriPlace + "%22"
+ yahooapisFormat;
String woeidString = QueryYahooWeather(yahooPlaceAPIsQuery);
Document woeidDoc = convertStringToDocument(woeidString);
return parseWOEID(woeidDoc);
}
private ArrayList<String> parseWOEID(Document srcDoc){
ArrayList<String> listWOEID = new ArrayList<String>();
NodeList nodeListDescription = srcDoc.getElementsByTagName("woeid");
if(nodeListDescription.getLength()>=0){
for(int i=0; i<nodeListDescription.getLength(); i++){
listWOEID.add(nodeListDescription.item(i).getTextContent());
}
}else{
listWOEID.clear();
}
return listWOEID;
}
private Document convertStringToDocument(String src){
Document dest = null;
DocumentBuilderFactory dbFactory =
DocumentBuilderFactory.newInstance();
DocumentBuilder parser;
try {
parser = dbFactory.newDocumentBuilder();
dest = parser.parse(new ByteArrayInputStream(src.getBytes()));
} catch (ParserConfigurationException e1) {
e1.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return dest;
}
private String QueryYahooWeather(String queryString){
String qResult = "";
HttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(queryString);
try {
HttpEntity httpEntity = httpClient.execute(httpGet).getEntity();
if (httpEntity != null){
InputStream inputStream = httpEntity.getContent();
Reader in = new InputStreamReader(inputStream);
BufferedReader bufferedreader = new BufferedReader(in);
StringBuilder stringBuilder = new StringBuilder();
String stringReadLine = null;
while ((stringReadLine = bufferedreader.readLine()) != null) {
stringBuilder.append(stringReadLine + "\n");
}
qResult = stringBuilder.toString();
}
} catch (ClientProtocolException e) {
e.printStackTrace();;
} catch (IOException e) {
e.printStackTrace();
}
return qResult;
}
}
Layout of the main activity, activity_main.xml.
<LinearLayout 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:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world"
tools:context=".MainActivity" />
<EditText
android:id="@+id/place"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/search"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Search WOEID by place" />
<ListView
android:id="@+id/woeidlist"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
The activity to query weather from Yahoo, GetWeather.java.
package com.example.androidwoeidweather;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.http.HttpEntity;
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.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;
public class GetWeather extends Activity {
TextView weather;
class MyWeather{
String description;
String city;
String region;
String country;
String windChill;
String windDirection;
String windSpeed;
String sunrise;
String sunset;
String conditiontext;
String conditiondate;
public String toString(){
String s;
s = description + " -\n\n" + "city: " + city + "\n"
+ "region: " + region + "\n"
+ "country: " + country + "\n\n"
+ "Wind\n"
+ "chill: " + windChill + "\n"
+ "direction: " + windDirection + "\n"
+ "speed: " + windSpeed + "\n\n"
+ "Sunrise: " + sunrise + "\n"
+ "Sunset: " + sunset + "\n\n"
+ "Condition: " + conditiontext + "\n"
+ conditiondate +"\n";
return s;
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_weather);
weather = (TextView)findViewById(R.id.weather);
Bundle bundle = this.getIntent().getExtras();
String sel_woeid = (String)bundle.getCharSequence("SEL_WOEID");
new MyQueryYahooWeatherTask(sel_woeid).execute();
Toast.makeText(getApplicationContext(),
sel_woeid,
Toast.LENGTH_LONG).show();
}
private class MyQueryYahooWeatherTask extends AsyncTask<Void, Void, Void>{
String woeid;
String weatherResult;
String weatherString;
MyQueryYahooWeatherTask(String w){
woeid = w;
}
@Override
protected Void doInBackground(Void... arg0) {
weatherString = QueryYahooWeather();
Document weatherDoc = convertStringToDocument(weatherString);
if(weatherDoc != null){
weatherResult = parseWeather(weatherDoc).toString();
}else{
weatherResult = "Cannot convertStringToDocument!";
}
return null;
}
@Override
protected void onPostExecute(Void result) {
weather.setText(weatherResult);
super.onPostExecute(result);
}
private String QueryYahooWeather(){
String qResult = "";
String queryString = "http://weather.yahooapis.com/forecastrss?w=" + woeid;
HttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(queryString);
try {
HttpEntity httpEntity = httpClient.execute(httpGet).getEntity();
if (httpEntity != null){
InputStream inputStream = httpEntity.getContent();
Reader in = new InputStreamReader(inputStream);
BufferedReader bufferedreader = new BufferedReader(in);
StringBuilder stringBuilder = new StringBuilder();
String stringReadLine = null;
while ((stringReadLine = bufferedreader.readLine()) != null) {
stringBuilder.append(stringReadLine + "\n");
}
qResult = stringBuilder.toString();
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return qResult;
}
private Document convertStringToDocument(String src){
Document dest = null;
DocumentBuilderFactory dbFactory =
DocumentBuilderFactory.newInstance();
DocumentBuilder parser;
try {
parser = dbFactory.newDocumentBuilder();
dest = parser.parse(new ByteArrayInputStream(src.getBytes()));
} catch (ParserConfigurationException e1) {
e1.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return dest;
}
private MyWeather parseWeather(Document srcDoc){
MyWeather myWeather = new MyWeather();
//<description>Yahoo! Weather for New York, NY</description>
NodeList descNodelist = srcDoc.getElementsByTagName("description");
if(descNodelist != null && descNodelist.getLength() > 0){
myWeather.description = descNodelist.item(0).getTextContent();
}else{
myWeather.description = "EMPTY";
}
//<yweather:location city="New York" region="NY" country="United States"/>
NodeList locationNodeList = srcDoc.getElementsByTagName("yweather:location");
if(locationNodeList != null && locationNodeList.getLength() > 0){
Node locationNode = locationNodeList.item(0);
NamedNodeMap locNamedNodeMap = locationNode.getAttributes();
myWeather.city = locNamedNodeMap.getNamedItem("city").getNodeValue().toString();
myWeather.region = locNamedNodeMap.getNamedItem("region").getNodeValue().toString();
myWeather.country = locNamedNodeMap.getNamedItem("country").getNodeValue().toString();
}else{
myWeather.city = "EMPTY";
myWeather.region = "EMPTY";
myWeather.country = "EMPTY";
}
//<yweather:wind chill="60" direction="0" speed="0"/>
NodeList windNodeList = srcDoc.getElementsByTagName("yweather:wind");
if(windNodeList != null && windNodeList.getLength() > 0){
Node windNode = windNodeList.item(0);
NamedNodeMap windNamedNodeMap = windNode.getAttributes();
myWeather.windChill = windNamedNodeMap.getNamedItem("chill").getNodeValue().toString();
myWeather.windDirection = windNamedNodeMap.getNamedItem("direction").getNodeValue().toString();
myWeather.windSpeed = windNamedNodeMap.getNamedItem("speed").getNodeValue().toString();
}else{
myWeather.windChill = "EMPTY";
myWeather.windDirection = "EMPTY";
myWeather.windSpeed = "EMPTY";
}
//<yweather:astronomy sunrise="6:52 am" sunset="7:10 pm"/>
NodeList astNodeList = srcDoc.getElementsByTagName("yweather:astronomy");
if(astNodeList != null && astNodeList.getLength() > 0){
Node astNode = astNodeList.item(0);
NamedNodeMap astNamedNodeMap = astNode.getAttributes();
myWeather.sunrise = astNamedNodeMap.getNamedItem("sunrise").getNodeValue().toString();
myWeather.sunset = astNamedNodeMap.getNamedItem("sunset").getNodeValue().toString();
}else{
myWeather.sunrise = "EMPTY";
myWeather.sunset = "EMPTY";
}
//<yweather:condition text="Fair" code="33" temp="60" date="Fri, 23 Mar 2012 8:49 pm EDT"/>
NodeList conditionNodeList = srcDoc.getElementsByTagName("yweather:condition");
if(conditionNodeList != null && conditionNodeList.getLength() > 0){
Node conditionNode = conditionNodeList.item(0);
NamedNodeMap conditionNamedNodeMap = conditionNode.getAttributes();
myWeather.conditiontext = conditionNamedNodeMap.getNamedItem("text").getNodeValue().toString();
myWeather.conditiondate = conditionNamedNodeMap.getNamedItem("date").getNodeValue().toString();
}else{
myWeather.conditiontext = "EMPTY";
myWeather.conditiondate = "EMPTY";
}
return myWeather;
}
}
}
Layout of GetWeather, layout_weather.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="fill_parent"
android:orientation="vertical" >
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:id="@+id/weather"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</ScrollView>
</LinearLayout>
Modify AndroidManifest.xml to add activity ".GetWeather" and permission of "android.permission.INTERNET".
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.androidwoeidweather"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="15" />
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/title_activity_main" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".GetWeather">
</activity>
</application>
</manifest>
Download the files.