Getting XML data by AsyncTask and parsing by using XMLPullParser

Hi readers,
XML stands for Extensible Markup Language. XML is a very popular format and commonly used for sharing data on the internet. This chapter explains how to parse the XML file and extract necessary information from it.
Android provides three types of XML parsers which are DOM, SAX and XMLPullParser. Among all of them, I recommend XMLPullParser because it is efficient and easy to use. In this post, I present a simple example to get XML data from an URL by AsyncTask and parse it using XMLPullParser.

1. Launch Eclipse and start a new Android Project (I use min-sdk is 14).
2. Create layout for activity (activity_weather.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:layout_margin="10dp"
    android:orientation="vertical"
    tools:context=".WeatherActivity" >

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:gravity="center"
        android:text="@string/notice"
        android:textSize="18sp" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:orientation="horizontal" >

        <TextView
            android:id="@+id/textView2"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="0.35"
            android:text="@string/country" />

        <TextView
            android:id="@+id/country"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="0.65"
            android:textColor="@android:color/holo_green_light" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:orientation="horizontal" >

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="0.35"
            android:text="@string/location" />

        <TextView
            android:id="@+id/location"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="0.65"
            android:textColor="@android:color/holo_blue_dark" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:orientation="horizontal" >

        <TextView
            android:id="@+id/textView3"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="0.35"
            android:text="@string/temperature"
            android:textAppearance="?android:attr/textAppearanceSmall" />

        <TextView
            android:id="@+id/temperature"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="0.65"
            android:textColor="@android:color/holo_orange_dark" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:orientation="horizontal" >

        <TextView
            android:id="@+id/textView4"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="0.35"
            android:text="@string/humidity"
            android:textAppearance="?android:attr/textAppearanceSmall" />

        <TextView
            android:id="@+id/humidity"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="0.65"
            android:textColor="@android:color/holo_purple" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:orientation="horizontal" >

        <TextView
            android:id="@+id/textView5"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="0.35"
            android:text="@string/pressure" />

        <TextView
            android:id="@+id/pressure"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="0.65"
            android:textColor="@android:color/holo_red_dark" />
    </LinearLayout>

</LinearLayout>

3. Create an AsyncTask to get XML data. This class deals with following operations:
  • Getting XML content by making HTTP request (in doInBackground() method).
  • Parsing XML content and getting element of xml (parseXML() method).

Getting XML content by making HTTP request


 @Override
 protected String[] doInBackground(String[]... params) {
  try {
   URL url = new URL(this.url);
   HttpURLConnection connection = (HttpURLConnection) url.openConnection();
   connection.setReadTimeout(10000 /* milliseconds */);
   connection.setConnectTimeout(15000 /* milliseconds */); 
   connection.setRequestMethod("GET");
   connection.setDoInput(true);
   connection.connect();
   InputStream stream = connection.getInputStream();

   xmlFactoryObject = XmlPullParserFactory.newInstance();
   XmlPullParser myParser = xmlFactoryObject.newPullParser(); 

   myParser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
   myParser.setInput(stream, null);
   String[] result = parseXML(myParser);
   stream.close();

   return result;

  } catch (Exception e) {
   e.printStackTrace();
   Log.e("AsyncTask", "exception");
   return null;
  }
 }


Parsing XML content and getting DOM element of xml


public String[] parseXML(XmlPullParser myParser) {

  int event;
  String text = null;
  String[] result = new String[5];

  try {
   event = myParser.getEventType();
   while (event != XmlPullParser.END_DOCUMENT) {
    String name = myParser.getName();

    switch (event) {
    case XmlPullParser.START_TAG:
     break;
    case XmlPullParser.TEXT:
     text = myParser.getText();
     break;

    case XmlPullParser.END_TAG:
     //get country name
     if (name.equals("country")) {
      result[4] = text;
     } else if (name.equals("humidity")) { //get humidity
      result[0] = myParser.getAttributeValue(null, "value");

     } else if (name.equals("pressure")) { //get pressure
      result[1] = myParser.getAttributeValue(null, "value");

     } else if (name.equals("temperature")) { //get temperature
      result[2] = myParser.getAttributeValue(null, "value");

     } else if (name.equals("coord")) { //get location
      result[3] = "(" + myParser.getAttributeValue(null, "lat") + " , "
        + myParser.getAttributeValue(null, "lon") + ")";
     }
     break;
    }
    event = myParser.next();
   }
   return result;

  } catch (Exception e) {
   e.printStackTrace();
   return null;
  }
 }

Full GetWeatherDataTask.java:

package com.blogspot.hongthaiit.xmlandasynctask;

import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;

import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.util.Log;

public class GetWeatherDataTask extends AsyncTask<String[], Void, String[]> {

 private WeatherActivity activity;
 private String url;
 private XmlPullParserFactory xmlFactoryObject;
 private ProgressDialog pDialog;

 public GetWeatherDataTask(WeatherActivity activity, String url) {
  this.activity = activity;
  this.url = url;
 }
 
 @Override
 protected void onPreExecute() {
  super.onPreExecute();
  pDialog = new ProgressDialog(activity);
  pDialog.setTitle("Get Weather Information from XML");
  pDialog.setMessage("Loading...");
  pDialog.show();
 }

 @Override
 protected String[] doInBackground(String[]... params) {
  try {
   URL url = new URL(this.url);
   HttpURLConnection connection = (HttpURLConnection) url.openConnection();
   connection.setReadTimeout(10000 /* milliseconds */);
   connection.setConnectTimeout(15000 /* milliseconds */); 
   connection.setRequestMethod("GET");
   connection.setDoInput(true);
   connection.connect();
   InputStream stream = connection.getInputStream();

   xmlFactoryObject = XmlPullParserFactory.newInstance();
   XmlPullParser myParser = xmlFactoryObject.newPullParser(); 

   myParser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
   myParser.setInput(stream, null);
   String[] result = parseXML(myParser);
   stream.close();

   return result;

  } catch (Exception e) {
   e.printStackTrace();
   Log.e("AsyncTask", "exception");
   return null;
  }
 }

 public String[] parseXML(XmlPullParser myParser) {

  int event;
  String text = null;
  String[] result = new String[5];

  try {
   event = myParser.getEventType();
   while (event != XmlPullParser.END_DOCUMENT) {
    String name = myParser.getName();

    switch (event) {
    case XmlPullParser.START_TAG:
     break;
    case XmlPullParser.TEXT:
     text = myParser.getText();
     break;

    case XmlPullParser.END_TAG:
     //get country name
     if (name.equals("country")) {
      result[4] = text;
     } else if (name.equals("humidity")) { //get humidity
      result[0] = myParser.getAttributeValue(null, "value");

     } else if (name.equals("pressure")) { //get pressure
      result[1] = myParser.getAttributeValue(null, "value");

     } else if (name.equals("temperature")) { //get temperature
      result[2] = myParser.getAttributeValue(null, "value");

     } else if (name.equals("coord")) { //get location
      result[3] = "(" + myParser.getAttributeValue(null, "lat") + " , "
        + myParser.getAttributeValue(null, "lon") + ")";
     }
     break;
    }
    event = myParser.next();
   }
   return result;

  } catch (Exception e) {
   e.printStackTrace();
   return null;
  }
 }

 @Override
 protected void onPostExecute(String[] result) {
  //call back data to main thread
  pDialog.dismiss();
  activity.callBackData(result);
  
 }
}

4. As you can see, at onPostExcute(), data were return to main thread. So we use them to set views.
Full WeatherActivity.java code simple like this:

package com.blogspot.hongthaiit.xmlandasynctask;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class WeatherActivity extends Activity {

 private final static String url = "http://api.openweathermap.org/data/2.5/weather?q=hanoi&mode=xml";
 private TextView location, country, temperature, humidity, pressure;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_weather);

  location = (TextView) findViewById(R.id.location);
  country = (TextView) findViewById(R.id.country);
  temperature = (TextView) findViewById(R.id.temperature);
  humidity = (TextView) findViewById(R.id.humidity);
  pressure = (TextView) findViewById(R.id.pressure);

  new GetWeatherDataTask(this, url).execute();
 }

 public void callBackData(String[] result) {
  temperature.setText((Float.parseFloat(result[2]) - 273) + " degree Celcius" );
  humidity.setText(result[0] + " %");
  pressure.setText(result[1] + " hPa");
  country.setText(result[4]);
  location.setText(result[3]);
 }
}

5. Open AndroidManifest.xml and add permission to access Internet:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.blogspot.hongthaiit.xmlandasynctask"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="14"
        android:targetSdkVersion="21" />

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

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".WeatherActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

6. Some application screens (click for full size):

pic name pic name

Share


Previous post
« Prev Post
Next post
Next Post »