Webservices are one of the effective way of transferring information from server to mobile apps. The webservices may use XML or JSON formats for the purpose.
This tutorial is about parsing information available at http://pcsalt.com/postservice/?format=xml. And, the end result will be an Android app having a list of posts on Android, and clicking on the list item will open the linked page.
Following XML is an abstract from above URL. First we determine what tags are there in XML and then we would parse to extract and display this information.
Add EditText Programmatically - Android http://pcsalt.com/?p=249 2013-01-26 01:05:35 Android SQLite Database - Part 1/2 http://pcsalt.com/?p=442 2013-04-18 23:48:59
So, this service have posts as main tag, i.e., complete XML is enclosed inside this tag. And, the post tag has all information related with each post. The information enclosed are:
- Post Title (post_title),
- Guid (guid), and
- Publish Date (post_date).
First create Android Application project by following the steps in Create Andriod Application Project in Android Studio Continued with following values
Application Name | CustomListViewDemo |
Package Name | pcsalt.example.xmlparsingsaxdemo |
Minimum SDK for Android App | 8 |
Activity Name | MainActivity |
Layout Name | activity_main |
(adsbygoogle = window.adsbygoogle || []).push({});
Directory structure of project would be
-
java
pcsalt.example.xmlparsingsaxdemo- MainActivity.java
- PostBaseAdapter.java
- PostValue.java
- XMLHelper.java
-
res
layout- activity_main.xml
- list_item_post.xml
In order to parse the XML, two JAVA classes would be needed, namely
- PostValue.java – Value holder class (consists of getters and setters) to hold the values of each post tag, and
- XMLHelper.java – Helper class to open a stream, parse XML and store value in PostValue type object.
PostValue.java: It is a model class consists of getters/setters for title, guid, and date. The information from XML is stored in instance of this class. So, these methods will be helpful in storing and retrieving information to/from instance of this class.
package pcsalt.example.xmlparsingsaxdemo; /** * A class for getters and setters for post * */ public class PostValue { String title, guid, date; public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getGuid() { return guid; } public void setGuid(String guid) { this.guid = guid; } public String getDate() { return date; } public void setDate(String date) { this.date = date; } }
XMLHelper.java: This class sends request to the URL and when it gets XML in response SAXParser helps parse the XML.
package pcsalt.example.xmlparsingsaxdemo; import android.util.Log; import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.XMLReader; import org.xml.sax.helpers.DefaultHandler; import java.io.InputStream; import java.net.URL; import java.util.ArrayList; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; public class XMLHelper extends DefaultHandler { /** * The URL to be parsed */ private String URL_MAIN = "http://pcsalt.com/postservice/?format=xml"; String TAG = "XMLHelper"; Boolean currTag = false; String currTagVal = ""; private PostValue post = null; private ArrayList posts = new ArrayList(); public ArrayList getPostsList() { return this.posts; } /** * Method to read XML from {@link pcsalt.example.xmlparsingsaxdemo.XMLHelper#URL_MAIN} */ public void get() { try { SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser mSaxParser = factory.newSAXParser(); XMLReader mXmlReader = mSaxParser.getXMLReader(); mXmlReader.setContentHandler(this); InputStream mInputStream = new URL(URL_MAIN).openStream(); mXmlReader.parse(new InputSource(mInputStream)); } catch (Exception e) { // Exceptions can be handled for different types // But, this is about XML Parsing not about Exception Handling Log.e(TAG, "Exception: " + e.getMessage()); } } // This method receives notification character data inside an element // e.g. Add EditText Pragmatically - Android // It will be called to read "Add EditText Pragmatically - Android" @Override public void characters(char[] ch, int start, int length) throws SAXException { if (currTag) { currTagVal = currTagVal + new String(ch, start, length); currTag = false; } } // Receives notification of end of element // e.g. Add EditText Pragmatically - Android // It will be called when is encountered @Override public void endElement(String uri, String localName, String qName) throws SAXException { currTag = false; if (localName.equalsIgnoreCase("post_title")) post.setTitle(currTagVal); else if (localName.equalsIgnoreCase("guid")) post.setGuid(currTagVal); else if (localName.equalsIgnoreCase("post_date")) post.setDate(currTagVal); else if (localName.equalsIgnoreCase("post")) posts.add(post); } // Receives notification of start of an element // e.g. Add EditText Pragmatically - Android // It will be called when is encountered @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { Log.i(TAG, "TAG: " + localName); currTag = true; currTagVal = ""; // Whenever element is encountered it will create new object of PostValue if (localName.equals("post")) post = new PostValue(); } }
MainActivity.java: This is used for displaying the parsed XML response. Since, the network operations must not be performed on main-thread, that’s why we are using AsyncTask to request the XML and parse information in the AsyncTask. After successful parsing we will be displaying result in a ListView.
package pcsalt.example.xmlparsingsaxdemo; import android.app.ProgressDialog; import android.content.Intent; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; import android.view.View; import android.widget.AdapterView; import android.widget.ListView; import java.util.ArrayList; public class MainActivity extends ActionBarActivity { ListView lvPcsPost; ArrayList postValueArrayList; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); lvPcsPost = (ListView) findViewById(R.id.lvPcsPost); lvPcsPost.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View view, int position, long id) { if (postValueArrayList != null && postValueArrayList.size() > 0) { Intent intentShowPost = new Intent(Intent.ACTION_VIEW, Uri.parse(postValueArrayList.get(position).getGuid())); startActivity(intentShowPost); } } }); new PostAsync().execute(); } class PostAsync extends AsyncTask { ProgressDialog pd; XMLHelper helper; @Override protected void onPreExecute() { pd = ProgressDialog.show(MainActivity.this, "PCSalt", "Loading posts for PCSalt.com ...", true, false); } @Override protected Void doInBackground(Void... arg0) { helper = new XMLHelper(); helper.get(); postValueArrayList = helper.getPostsList(); return null; } @Override protected void onPostExecute(Void result) { PostBaseAdapter postBaseAdapter = new PostBaseAdapter(MainActivity.this, postValueArrayList); lvPcsPost.setAdapter(postBaseAdapter); pd.dismiss(); } } }
PostBaseAdapter: It is an adapter class to initialise and maintain the list items. It’s getView() method is responsible for instantiating new list item on scroll. We are going to reuse the already created list item to display new post.
When ListView is scrolled up or down, new list item needs to be created. It will consume memory to always create a new list item on scroll. So, we are going to create only those list item which are visible at a time (say 6 list items), and reuse these list items during scroll. It is handled by checking if convertView is null or not. If it is not null then list item view already exists, then we will reuse that view, in lieu of creating new list item view.
package pcsalt.example.xmlparsingsaxdemo; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; import java.util.ArrayList; /** * Created by Krrishnaaaa on Jan 01, 2015 */ public class PostBaseAdapter extends BaseAdapter { private LayoutInflater layoutInflater; private ArrayList postValueArrayList; public PostBaseAdapter(Context context, ArrayList postValueArrayList) { this.layoutInflater = LayoutInflater.from(context); this.postValueArrayList = postValueArrayList; } @Override public int getCount() { return postValueArrayList.size(); } @Override public PostValue getItem(int position) { return postValueArrayList.get(position); } @Override public long getItemId(int position) { return 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder viewHolder; if (convertView == null) { convertView = layoutInflater.inflate(R.layout.list_item_post, parent, false); viewHolder = new ViewHolder(convertView); convertView.setTag(viewHolder); } else { viewHolder = (ViewHolder) convertView.getTag(); } PostValue postValue = getItem(position); viewHolder.tvTitle.setText(postValue.getTitle()); viewHolder.tvPublishDate.setText(postValue.getDate()); return convertView; } private class ViewHolder { TextView tvTitle, tvPublishDate; public ViewHolder(View item) { tvTitle = (TextView) item.findViewById(R.id.tvTitle); tvPublishDate = (TextView) item.findViewById(R.id.tvPublishDate); } } }
activity_main.xml: This is the layout for MainActivity class. It contains a ListView. In this ListView, the XML response will be displayed. Clicking on list item will open the selected post in web browser.
list_item_post.xml: This layout is for displaying the post list, after parsing the XML. It contains two TextView. First will display the title of post, and second will display the publish date.
This application would need permission to connect to Internet. So, the manifest file should be modified
AndroidManifest.xml
build.gradle
apply plugin: 'com.android.application' android { compileSdkVersion 22 buildToolsVersion "22.0.1" defaultConfig { applicationId "pcsalt.example.xmlparsingsaxdemo" minSdkVersion 8 targetSdkVersion 22 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat-v7:22.2.0' }
Download Source:
Video Tutorial : This tutorial was created with Eclipse and to display the XML response in a TextView inside ScrollView. The video is still valid.
In case you have any trouble, feel free to post comment. I will try my best to response at the earliest.