Android development blog
Tutorials about Android dev topics

Android Weather app using Yahoo weather provider and AutoCompleteTextView (Part 1)

Topics covered

Yahoo weather provider API


Remote item list in AutoCompleteTextView

Android XML Parser

I've released a new Weatherlib for Android that helps you to develop weather based app. If you are interested give a look here

This post is the first of a series where we will explore Yahoo Weather API. Our goal is building an app that gives us the actual weather condition using yahoo weather provider. In the next post we will see how to build a complete app using the knowledges described in this post. We already talked about other weather provider like openweathermap, in other two post. You can give a look here and here if you are interested.
In this first post, we want to analyze how we can retrieve city information using yahoo api. We will assume you have already an yahoo developer account, if not you can create it using this link. It is important you have your appid, that is totally free but it is necessary to use yahoo api. While we will explore yahoo api, we have the chance to describe some interesting Android UI component like AutoCompleteTextView and XML parsing in Android. Our goal is having an Android app that is shows by now the list of cities that matches a partial name entered by the user as shown below:



Yahoo Woeid

The first step to get weather information is retrieving woeid. This a spatial id that yahoo uses to identify city/region. We have, then, to find a way to get this woeid from the city name entered by the user.
From the UI perspective, we want that an user inserts just the name of the city or a partial name and we have to find a way to get a list of cities that matches the data entered by the user with the corresponding woeid:  we can use the api shown below to get a list of cities matching a pattern we entered:;count=MAX_RESULT_SIZE?appid=your_app_id

If you use this api in your browser you will get an XML file with a list of information about cities that match the city_name_pattern.

Android Yahoo XML data Parser

It is time we create an XML parser so that we can extract information from the data we get when using the api shown above. The first step is creating a data model that holds the city information, in our case it is quite simple:
public class CityResult {

    private String woeid;
    private String cityName;
    private String country;

    public CityResult() {}

    public CityResult(String woeid, String cityName, String country) {
        this.woeid = woeid;
        this.cityName = cityName; = country;

     // get and set methods

    public String toString() {
        return cityName + "," + country;

Now we create a parser class that we call YahooClient. This class is in charge of retrieving XML data and parse it. It has a simple static method that accepts the pattern we have to use to get the city list. At the beginning, we open an HTTP connection and pass the stream to the XML parser:
yahooHttpConn= (HttpURLConnection) (new URL(query)).openConnection();
XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
parser.setInput(new InputStreamReader(yahooHttpConn.getInputStream()));

then, we start parsing the data, looking for some tags we are interested on. By now, considering our data model too, we are just interested on the woeid, city name and country. There are other information in the XML but we don’t want to extract them by now.
int event = parser.getEventType();

CityResult cty = null;
String tagName = null;
String currentTag = null;

// We start parsing the XML
while (event != XmlPullParser.END_DOCUMENT) {
    tagName = parser.getName();

    if (event == XmlPullParser.START_TAG) {
       if (tagName.equals("place")) {
          // place Tag Found so we create a new CityResult
          cty = new CityResult();
           Log.d("Swa", "New City found");
        currentTag = tagName;
        Log.d("Swa", "Tag ["+tagName+"]");
    else if (event == XmlPullParser.TEXT) {
        // We found some text. let's see the tagName to know the tag related to the text
        if ("woeid".equals(currentTag))
        else if ("name".equals(currentTag))
        else if ("country".equals(currentTag))

        // We don't want to analyze other tag at the moment
    else if (event == XmlPullParser.END_TAG) {
        if ("place".equals(tagName))

    event =;

The code below is very simple, at line 1 we simply get the first XML event and we start traversing the XML document until we reach the end.  At the method end, we have a list of cities with the woied that is the information we were looking for.

AutoCompleteTextView and ArrayAdapter with Filter

Once we know how to get data from the XML we have to show to the user a list of items we get using yahoo api. There are several way to get this goal, we will use AutoCompleteTextView. This component is defined in Android doc as “An editable text view that shows completion suggestions automatically while the user is typing. The list of suggestions is displayed in a drop down menu from which the user can choose an item to replace the content of the edit box with.”. It satisfies our needs! Using this component is trivial but a little more complex is using the array adapter and how we filter the result. Usually this component is used with a static item list, in our case we have to retrieve it from a remote server. First we implement a custom adapter that extends the ArrayAdapter and this is very simple:
private class CityAdapter extends ArrayAdapter<CityResult>  {

private Context ctx;
private List<CityResult> cityList = new ArrayList<CityResult>();

public CityAdapter(Context ctx, List<CityResult> cityList) {
    super(ctx, R.layout.cityresult_layout, cityList);
    this.cityList = cityList;
    this.ctx = ctx;

public CityResult getItem(int position) {
    if (cityList != null)
        return cityList.get(position);

    return null;

public int getCount() {
    if (cityList != null)
        return cityList.size();

    return 0;

public View getView(int position, View convertView, ViewGroup parent) {
    View result = convertView;

    if (result == null) {
        LayoutInflater inf = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        result = inf.inflate(R.layout.cityresult_layout, parent, false);


    TextView tv = (TextView) result.findViewById(;
    tv.setText(cityList.get(position).getCityName() + "," + cityList.get(position).getCountry());

    return result;

public long getItemId(int position) {
    if (cityList != null)
        return cityList.get(position).hashCode();

    return 0;

Much more interesting is how we can retrieve the data from a remote server. If we implement the Filterable interface in our custom adapter we can get the result we are looking for. So we have:
 private class CityAdapter extends ArrayAdapter<CityResult> implements Filterable {
        public Filter getFilter() {
            Filter cityFilter = new Filter() {

                protected FilterResults performFiltering(CharSequence constraint) {
                    FilterResults results = new FilterResults();
                    if (constraint == null || constraint.length() < 2)
                        return results;

                    List<CityResult> cityResultList = YahooClient.getCityList(constraint.toString());
                    results.values = cityResultList;
                    results.count = cityResultList.size();
                    return results;

                protected void publishResults(CharSequence constraint, FilterResults results) {
                    cityList = (List) results.values;

            return cityFilter;

At line 4, we implement our Filter, that has two other methods we have to implement. In performFiltering method we make the HTTP call and retrieve the data (line 12). Apparently we could have ANR problem, and we know very well we shouldn’t do an HTTP call in the main thread. But if you read the documentation about performFiltering you will find out that this method runs in a separate thread so we won’t have any problem.

Finally, we can set the adapter in our UI component and handle the even when user clicks on an item:
AutoCompleteTextView edt = (AutoCompleteTextView) rootView.findViewById(;
CityAdapter adpt = new CityAdapter(this.getActivity(), null);
edt.setOnClickListener(new View.OnClickListener() {
   public void onClick(View v) {
       // We handle the onclick event and select the city chosen by the user

In the next post we will retrieve weather information using the woied, so stay tuned!

Source code available @ github


  1. Pls upload the source

  2. can you post the code please :)

  3. survivingwithandroidApril 23, 2014 at 1:03 PM

    Source code uploaded at github


Related Posts with Thumbnails