Showing posts with label Yahoo weather RSS feed code. Show all posts
Showing posts with label Yahoo weather RSS feed code. Show all posts

Monday, July 1, 2013

Yahoo Weather using RSS feed


Yahoo Weather using  RSS feed 

What is RSS feed ?
RSS. Short for Really Simple Syndication (at least now -- more on that later), RSS is a way to subscribe to a source of information, such as a Web site, and get brief updates delivered to you.RSS was designed to show selected data.Without RSS, users will have to check your site daily for new updates. This may be too time-consuming for many users. With an RSS feed (RSS is often called a News feed or RSS feed) they can check your site faster using an RSS aggregator (a site or program that gathers and sorts out RSS feeds).
Since RSS data is small and fast-loading, it can easily be used with services like cell phones or PDA's.
Web-rings with similar information can easily share data on their web sites to make them better and more useful.
Some commonly mentioned uses are:
  • Notification of the arrival of new products in a store
  • Listing and notifying you of newsletter issues, including email newsletters
  • Weather and other alerts of changing conditions
  • Notification of additions of new items to a database, or new members to a group

 Figure1 Shows How RSS aggregator and feeder works
RSS feed provider
RSS uses the World Wide Web Consortium's Resource Description Framework (RDF) as a guide to tell a feed aggregator how to read the file. RDF is based on extensible markup language (XML).The special XML-format file that makes up an RSS feed is usually created in one of a variety of ways.
Most large news websites and most weblogs are maintained using special "content management" programs. Authors add their stories and postings to the website by interacting with those programs and then use the program's "publish" facility to create the HTML files that make up the website. Those programs often also can update the RSS feed XML file at the same time, adding an item referring to the new story or post, and removing less recent items. Blog creation tools like Blogger, LiveJournal, Movable Type, and Radio automatically create feeds.Websites that are produced in a more custom manner, such as with Macromedia Dreamweaver or a simple text editor, usually do not automatically create RSS feeds. Authors of such websites either maintain the XML files by hand, just as they do the website itself, or use a tool such as Software Garden, Inc.'s ListGarden program to maintain it. There are also services that periodically read requested websites themselves and try to automatically determine changes (this is most reliable for websites with a somewhat regular news-like format), or that let you create RSS feed XML files that are hosted by that service provider.

RSS Reader
Reading RSS feed through aggregators.Aggregators collect and interpret RSS feeds in one location from many
subscribed web sites.many mordern browser provide readers/aggregators Depending on what kind of site you're visiting, you may even see a link with a whole list of feeds. Once you click on a link to the feed, you'll get the option to subscribe. Different browsers handle feeds differently, but you'll probably be given a choice of options for handling the subscription.
An example of rss feed format
<?xml version="1.0" encoding="ISO-8859-1" ?>
<rss version="2.0">

<channel>
  <title>W3Schools Home Page</title>
  <link>http://navinsandroidtutorial.blogspot.in</link>
  <description>Android tutorials</description>
  <item>
    <title>Android rss Tutorial</title>
    <description>New Android RSS Tutorial</description>
  </item>
  <item>
    <title>Content provider in Android complete tutorial</title>
    <description>New Content provider in Android</description>
  </item>
</channel>
</rss>
Yahoo Weather RSS feed
The Weather RSS feed enables you to get up-to-date weather information for your location. You can save this feed in My Yahoo! or your favorite feed aggregator, or incorporate the RSS data into your own web site or client application. The Weather RSS feed is a dynamically-generated feed based on WOEID.
The base URL for the Weather RSS feed is http://weather.yahooapis.com/forecastrss
For the Weather RSS feed there are two parameters:
·         w for WOEID.
·         u for degrees units (Fahrenheit or Celsius).
The WOEID parameter w is required. Use this parameter to indicate the location for the weather forecast as a WOEID.
http://weather.yahooapis.com/forecastrss?w=location
For example, to get weather for Yahoo! Headquarters in Sunnyvale, CA, use the WOEID code for Sunnyvale (2502265):
http://weather.yahooapis.com/forecastrss?w=2502265
The location parameter needs to be a WOEID. To find your WOEID, browse or search for your city from the Weather home page.The following is the URL for fetching weather condition for chennai
http://weather.yahooapis.com/forecastrss?w=2295424&u=c
This demonstrative application fetches chennai city temperature and weather condition from Yahoo weather RSS feed and  displays it in presentable manner to the user.
1.Create  Android project with details as listed in table below
Property name
Property value
Project name
SRM_YahooWeather
Package name
in.ac.srmuniv
Activity name
MainActivity
Layout xml name
main

2.Copy the code  to the file main.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:layout_alignParentLeft="true"
    android:layout_alignParentTop="true"
    android:background="#FFFEF6"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/main_condition_value"
        android:layout_gravity="center"
        android:text="Chennai Temperature"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:textColor="@color/textcolor" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:orientation="horizontal" >

        <TextView
            android:id="@+id/main_date_label"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/date"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:textColor="@color/textcolor2" />

        <TextView
            android:id="@+id/main_date_value"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:textColor="@color/textcolor2" >
        </TextView>
    </LinearLayout>

    <FrameLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" >

        <ImageView
            android:id="@+id/imageView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="right" />

        <RelativeLayout
            android:id="@+id/layout"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:layout_marginTop="10dp"
            android:orientation="vertical" >

            <TextView
                android:id="@+id/main_temperature_label"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@+id/main_date_label"
                android:text="@string/temperature"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:textColor="@color/textcolor2"/>

            <TextView
                android:id="@+id/main_temperature_value"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@+id/main_date_label"
                android:layout_marginLeft="10dp"
                android:layout_toRightOf="@+id/main_temperature_label"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:textColor="@color/textcolor3"/>

            <TextView
                android:id="@+id/main_condition_label"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@+id/main_temperature_label"
                android:text="@string/condition"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:textColor="@color/textcolor2"/>

            <TextView
                android:id="@+id/main_condition_value"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignLeft="@+id/main_temperature_value"
                android:layout_below="@+id/main_temperature_label"
                android:layout_toRightOf="@+id/main_condition_label"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:textColor="@color/textcolor3"/>
        </RelativeLayout>
    </FrameLayout>

    <ImageView
        android:id="@+id/imageView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/yahooweather" />

</LinearLayout>
2.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_YahooWeather</string>
    <string name="action_settings">Settings</string>
    <string name="hello_world">Hello world!</string>
    <string name="temperature">Temperature:</string>
    <string name="date">Date:</string>
    <string name="condition">Condition:</string>

    <color name="textcolor">#0000f0</color>
    <color name="textcolor2">#00ffaa</color>
    <color name="textcolor3">#ff5a00</color>


</resources>
4.Copy the code  to the file main.xml in res/menu folder 

<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:id="@+id/item1"
        android:icon="@drawable/yahoo_weather"
        android:title="Refresh">
    </item>

</menu>
5.Copy the code in MainActivty.java. Activity.
package in.ac.srmuniv;

import java.util.HashMap;
import java.util.Map;
importandroid.annotation.SuppressLint;
importandroid.app.Activity;
import android.content.*;
importandroid.os.AsyncTask;
import android.os.Bundle;
import android.os.IBinder;
importandroid.view.MenuItem;
importandroid.widget.ImageView;
importandroid.widget.TextView;
importandroid.widget.Toast;
importin.ac.srmuniv.model.WeatherObject;
importin.ac.srmuniv.tools.DatabaseHandler;
importin.ac.srmuniv.tools.UpdateService;

@SuppressLint("NewApi")
public class MainActivity extends Activity {
    public final static String NEW_WEATHER_EVENT = "in.ac.srmuniv.NEW_WEATHER_ADDED";
    private final static String REFRESH_MENU_ITEM = "Refresh";
    private UpdateService mService;
    private boolean mBound;
    private Map<String, Integer> wImages;
    private ImageView v;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);
        wImages=new HashMap<String, Integer>();
        wImages.put("Mostly Cloudy",R.drawable.mostly_cloudy);
        wImages.put("Fair",R.drawable.fair);
        wImages.put("Partly Cloudy",R.drawable.partly_cloudy);
        wImages.put("Sunny",R.drawable.sunny);
        wImages.put("not applicable",R.drawable.not_applicable);
        wImages.put("Haze",R.drawable.haze);



    }

    @Override
    public booleanonCreateOptionsMenu(android.view.Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        /*menu.add(REFRESH_MENU_ITEM).setIcon(android.R.drawable.ic_input_get)
                .setShowAsAction(android.view.Menu.CATEGORY_ALTERNATIVE);*/
        return true;
    }
    @Override
    public booleanonOptionsItemSelected(MenuItem item)
    {

        switch (item.getItemId())
        {
        case R.id.item1:
            // Single menu item is selected do something
            // Ex: launching new activity/screen or show alert message
            Toast.makeText(MainActivity.this, "Refresh is Selected", Toast.LENGTH_SHORT).show();
            if (mBound) {
                mService.loadWeatherData();
            }
  
        }
        return true;
    }

    @Override
    protected void onStart() {
        super.onStart();

        Intent intent = new Intent(this, UpdateService.class);
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
        IntentFilter filter = new IntentFilter(MainActivity.NEW_WEATHER_EVENT);
        registerReceiver(mBroadcastReceiver, filter);

    }

    @Override
    protected void onStop() {
        super.onStop();
        if (mBound) {
            unbindService(mConnection);
            mBound = false;
        }

        unregisterReceiver(mBroadcastReceiver);
    }

    private ServiceConnection mConnection = new ServiceConnection() {

        @Override
        public voidonServiceConnected(ComponentName className, IBinder service) {
            UpdateService.LocalBinder binder = (UpdateService.LocalBinder) service;
            mService = binder.getService();
            mBound = true;
        }

        @Override
        public voidonServiceDisconnected(ComponentName arg0) {
            mBound = false;
        }
    };

    private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            newUpdateUI().execute();
        }
    };

    private class UpdateUI extends AsyncTask<Void, Void, WeatherObject> {

        @Override
        protected WeatherObject doInBackground(Void... params) {
            return DatabaseHandler.getInstance(MainActivity.this).getWeather();
        }

        @Override
        protected voidonPostExecute(WeatherObject object) {
            super.onPostExecute(object);
            v=(ImageView)findViewById(R.id.imageView1);
            if (object != null) {
                ((TextView) findViewById(R.id.main_date_value)).setText(object.getDate());
                ((TextView) findViewById(R.id.main_temperature_value)).setText(object.getTemp());
                ((TextView) findViewById(R.id.main_condition_value)).setText(object.getCondition());
            }

            try {
                v.setBackgroundResource((Integer)wImages.get(object.getCondition()));
            } catch(NullPointerException e) {
                v.setBackgroundResource((Integer)wImages.get("not applicable"));

            }

        }
    }
}
6.Create a new java class file from eclipse named WeatherObject.java with package name in.ac.srmuniv.model
package in.ac.srmuniv.model;

public class WeatherObject {
    String condition;
    String temp ;
    String date;

    public WeatherObject(String condition, String temp, String date) {
        this.condition = condition;
        this.temp = temp;
        this.date = date;
    }

    public String getCondition() {
        return condition;
    }

    public void setCondition(String condition) {
        this.condition = condition;
    }

    public String getTemp() {
        return temp;
    }

    public void setTemp(String temp) {
        this.temp = temp;
    }

    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }
}
7.Create a new java interface file from eclipse named Consts.java with package name in.ac.srmuniv.tools
package in.ac.srmuniv.tools;

public interface Consts {
     public static final String API_URL = "http://weather.yahooapis.com/forecastrss?w=2295424&u=c";
        public static final String ROOT = "yweather:condition";
        public static final String CONDITION_TEXT = "text";
        public static final String CONDITION_TEMP = "temp";
        public static final String CONDITION_DATE = "date";
       

}

8.Create a new java class file from eclipse named DatabaseHandler.java with package name in.ac.srmuniv.tools
package in.ac.srmuniv.tools;

importandroid.content.ContentValues;
importandroid.content.Context;
importandroid.database.Cursor;
importandroid.database.sqlite.SQLiteDatabase;
importandroid.database.sqlite.SQLiteOpenHelper;
importin.ac.srmuniv.model.WeatherObject;

public class DatabaseHandler extends SQLiteOpenHelper {

    private static final int DATABASE_VERSION = 1;
    private static final String DATABASE_NAME = "weather";
    private static final String TABLE_CURRENT_WEATHER = "currentWeather";
    private static final String KEY_ID = "id";
    private static final String KEY_CONDITION = "condition";
    private static final String KEY_TEMP = "temperature";
    private static final String KEY_DATE = "date";
    private static final String KEY_SIZE = "count(*)";

    private static final String SIZE_QUERY = "SELECT "+ KEY_SIZE +" FROM " + TABLE_CURRENT_WEATHER;
    private static final String SELECT_QUERY = "SELECT * FROM " + TABLE_CURRENT_WEATHER;
    private static final String DROP_QUERY = "DROP TABLE IF EXISTS " + TABLE_CURRENT_WEATHER;
    private static final String CREATE_WEATHER_TABLE_QUERY = "CREATE TABLE " + TABLE_CURRENT_WEATHER + "("
            + KEY_ID + " INTEGER PRIMARY KEY," + KEY_CONDITION + " TEXT," + KEY_TEMP + " TEXT," + KEY_DATE + " TEXT" + ")";

    private static DatabaseHandler mInstance = null;

    privateDatabaseHandler(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    public static DatabaseHandler getInstance(Context context) {
        if (mInstance == null) {
            synchronized (DatabaseHandler.class) {
                if (mInstance == null) {
                    mInstance = newDatabaseHandler(context);
                }
            }
        }
        return mInstance;
    }

    @Override
    public voidonCreate(SQLiteDatabase db) {
        db.execSQL(CREATE_WEATHER_TABLE_QUERY);
    }

    @Override
    public voidonUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL(DROP_QUERY);
        onCreate(db);
    }


    public voidaddWeather(WeatherObject object) {
        SQLiteDatabase db = mInstance.getWritableDatabase();

        ContentValues values = new ContentValues();
        values.put(KEY_CONDITION, object.getCondition());
        values.put(KEY_TEMP, object.getTemp());
        values.put(KEY_DATE, object.getDate());

        if (getDBSize() == 0) {
            db.insert(TABLE_CURRENT_WEATHER, null, values);
        } else {
            db.update(TABLE_CURRENT_WEATHER, values, KEY_ID + "=1", null);
        }
        db.close();
    }


    private int getDBSize() {
        SQLiteDatabase db = mInstance.getReadableDatabase();
        Cursor cursor = db.rawQuery(SIZE_QUERY, null);

        if(cursor.moveToFirst()) {
            return Integer.parseInt(cursor.getString(cursor.getColumnIndex(KEY_SIZE)));
        }
        cursor.close();
        return 0;

    }


    public WeatherObject getWeather() {
        WeatherObject weatherObject = null;
        SQLiteDatabase db = this.getReadableDatabase();
        Cursor cursor = db.rawQuery(SELECT_QUERY, null);

        if(cursor.moveToFirst()) {
            int condition = cursor.getColumnIndex(KEY_CONDITION);
            int temp = cursor.getColumnIndex(KEY_TEMP);
            int date = cursor.getColumnIndex(KEY_DATE);
            weatherObject = newWeatherObject(cursor.getString(condition), cursor.getString(temp), cursor.getString(date));
        }
        cursor.close();
        return weatherObject;
    }
}

8.Create a new java class file from eclipse named UpdateService.java with package name in.ac.srmuniv.tools
package in.ac.srmuniv.tools;

import android.app.Service;
importandroid.content.Intent;
importandroid.os.AsyncTask;
import android.os.Binder;
import android.os.IBinder;
importin.ac.srmuniv.MainActivity;
importin.ac.srmuniv.tools.Consts;
importin.ac.srmuniv.model.WeatherObject;

importorg.w3c.dom.Document;
import org.w3c.dom.Element;
importorg.w3c.dom.NodeList;
importorg.xml.sax.SAXException;

importjavax.xml.parsers.DocumentBuilder;
importjavax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import java.io.IOException;

public class UpdateService extends Service implements Consts {
    private final IBinder mBinder = new LocalBinder();
    private boolean mIsLoading;

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    public class LocalBinder extends Binder {
        public UpdateService getService() {
            return UpdateService.this;
        }
    }

    public void loadWeatherData() {
        if (!mIsLoading) {
            newManageWeatherData().execute();
        }
    }

    private class ManageWeatherData extends AsyncTask<Void, Void, Void> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            mIsLoading = true;
        }

        @Override
        protected Void doInBackground(Void... params) {
            getWeather();
            return null;
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);
            Intent intent = new Intent(MainActivity.NEW_WEATHER_EVENT);
            sendBroadcast(intent);
            mIsLoading = false;
        }
    }

    private void getWeather() {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        try {
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document dom = db.parse(API_URL);
            parseDocument(dom);
        } catch(ParserConfigurationException pce) {
            pce.printStackTrace();

        } catch (SAXException se) {
            se.printStackTrace();

        } catch (IOException ioe) {
            ioe.printStackTrace();

        }
    }

    private voidparseDocument(Document dom) {
        Element docEle = dom.getDocumentElement();

        NodeList nl = docEle.getElementsByTagName(ROOT);
        if (nl != null && nl.getLength() > 0) {
            for (int i = 0; i < nl.getLength(); i++) {
                Element el = (Element) nl.item(i);
                WeatherObject weatherObject = parseWeather(el);
                writeToDB(weatherObject);
            }
        }
    }

    private WeatherObject parseWeather(Element el) {
        String condition = el.getAttribute(CONDITION_TEXT);
        String temp = el.getAttribute(CONDITION_TEMP);
        String date = el.getAttribute(CONDITION_DATE);
        //  String date = el.getAttribute(CONDITION_CODE);
        return newWeatherObject(condition, temp, date);
    }

    private voidwriteToDB(WeatherObject weatherObject) {
        DatabaseHandler.getInstance(getApplicationContext()).addWeather(weatherObject);
    }

}
9.Modify the Androidmanifest.xml with necessary entries highlighted 
<?xml version="1.0"
encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="in.ac.srmuniv"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.INTERNET"/>
    <application android:label="@string/app_name"
       
        >

        <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>
        <service android:enabled="true"android:name=".tools.UpdateService"/>
    </application>
</manifest>

Figure2 Shows anatomy of yahoo weather App with yahoo weather condition icons added to drawable folder


10.Run the application in the emulator/device with internet enabled. 



Figure 3 Shows when App is Loaded                                          Figure 4 Shows menu  with menu                                                                                option "Refresh"  pressed which in turn calls service                                                                                               to update weather.


 Figure 5 shows weather condition values fetched from yahoo weather RSS feed.Appropriate weather icon is selected
Code Explanation:



Code Explanation:
The demonstation project uses android's  main buiding blocks Activity,Services,Broadcast receivers and also handles  SQLite data base  and background running task using  AsyncTask .The project gives an idea on how and when to use these components.
      The above diagram "Android component collabaration diagram" shows flow of program execution happening between android component classes which comprises of various call back methods.
 The MainActivity is the main activity started first when app is invoked.It would display the current weather condition when user presses refresh menu button.onCreate( ) method in activity inflates UI from main.xml and HashMap is also initialized with resource ID for  images from res/drawable repsenting wheather condtion.onStart( ) method is used to bind the UpdateService( ) and get the instance of the service using iBinder.loadWheatherData( ) is the method the activity will be using to get the updated weather condition.onStop( ) method of  the activity will unbind the service.When refresh menu button is pressed  onOptionItemselected( ) is called which inturn calls the binded service method loadWheatherData( ).
       The binded method loadWheatherData( ) spawns seperate thread through AsyncTask ManageWheatherData which do internet Connection  the doIn Background( ) method performs RSS parsing. SAX parser is used to fetch  yweather:condition attributes from RSS feed and  update SQLite "wheather" Database.Databasehandler class handles SQLite database.onPostExecute() method is used to send broadcast message to MainActivity (this is one of the way to send message from service to activity when a message or data needs to be send on a particular event happened during long running service).Broadcast reciver used as inner class in MainActivity is invoked to fetch the weather data date ,Temperature and Weather condition  from SQLite database.since onRecive( ) method of  BroadcastReciver
cannot handle time consuming  code it deputes UpdateUI AsyncTask to fetch data from data base and update UI .Updates date and Temp parameter.Weather  condition parameter is taken as key and get() 
method in Hashmap is used to  retrieve R.id of image.The appropriate image  is displayed for the weather condition.Refer link http://developer.yahoo.com/weather/ for further details on using yahoo weather.