Yahoo Weather using RSS feed - Hallo sahabat Google Android Developer Tutorial, Pada Artikel yang anda baca kali ini dengan judul Yahoo Weather using RSS feed , kami telah mempersiapkan artikel ini dengan baik untuk anda baca dan ambil informasi didalamnya. mudah-mudahan isi postingan
Artikel Yahoo weather RSS feed code, yang kami tulis ini dapat anda pahami. baiklah, selamat membaca.
Judul : Yahoo Weather using RSS feed
link : Yahoo Weather using RSS feed
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:
Anda sekarang membaca artikel Yahoo Weather using RSS feed dengan alamat link https://googleandroiddevelopertutorial.blogspot.com/2013/07/yahoo-weather-using-rss-feed.html
Judul : Yahoo Weather using RSS feed
link : Yahoo Weather using RSS feed
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>
<link>http:///navinsandroidtutorial.blogspot.in/2013/07/yahoo-weather-using-rss-feed.html</link>
<description>New Android RSS Tutorial</description>
</item>
<item>
<title>Content provider in Android complete tutorial</title>
<link>http://navinsandroidtutorial.blogspot.in/2013/07/content-providers-in-android-complete.html</link>
<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=cThis 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
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.
Demikianlah Artikel Yahoo Weather using RSS feed
Sekianlah artikel Yahoo Weather using RSS feed kali ini, mudah-mudahan bisa memberi manfaat untuk anda semua. baiklah, sampai jumpa di postingan artikel lainnya.
Anda sekarang membaca artikel Yahoo Weather using RSS feed dengan alamat link https://googleandroiddevelopertutorial.blogspot.com/2013/07/yahoo-weather-using-rss-feed.html
Yahoo Weather using RSS feed
4/
5
Oleh
Unknown