Archive

Posts Tagged ‘create’

Android XML Adventure – Create & Write XML Data

October 27, 2011 7 comments

Article Series: Android XML Adventure

Author: Pete Houston (aka. `xjaphx`)

TABLE OF CONTENTS

  1. What is the “Thing” called XML?
  2. Parsing XML Data w/ SAXParser
  3. Parsing XML Data w/ DOMParser
  4. Parsing XML Data w/ XMLPullParser
  5. Create & Write XML Data
  6. Compare: XML Parsers
  7. Parsing XML using XPath
  8. Parsing HTML using HtmlCleaner
  9. Parsing HTML using JSoup
  10. Sample Project 1: RSS Parser – using SAXParser
  11. Sample Project 1: RSS Parser – using DOM Parser
  12. Sample Project 1: RSS Parser – using XMLPullParser
  13. Sample Project 2: HTML Parser – using HtmlCleaner
  14. Sample Project 2: HTML Parser – using JSoup
  15. Finalization on the “Thing” called XML!

=========================================

Have you mastered with parsing XML stuffs well?

Today, I’d like to talk about writing XML file, just like a normal Java program, there’s no differences.

Our steps are going to be:

+ First, create XML string (which is residing in memory for later use).

+ Second, write the XML string to a file, which belongs to internal storage of an Android application.

About the second step, I assume that you’ve already known how to do it. Shortly, `Context.openFileOutput()` will do the job.

For the first thing, there various ways to do; however, I’d like to introduce only most three common ways.

1. A normal String format

Understand what I mean?

	public static String writeUsingNormalOperation(Study study) {
		String format =
				"<?xml version='1.0' encoding='UTF-8'?>" +
				"<record>" +
				"	<study id='%d'>" +
				"		<topic>%s</topic>" +
				"		<content>%s</content>" +
				"		<author>%s</author>" +
				"		<date>%s</date>" +
				"	</study>" +
				"</record>";
		return String.format(format, study.mId, study.mTopic, study.mContent, study.mAuthor, study.mDate);
	}

The Good:

  • Very quick and easy.
  • Not much code or custom objects required.

The Bad:

  • Straightforwardly static string, if you want to output a list of XML tags, this way doesn’t work.
  • Easy to make mistake while making the format for output.

2. Using DOM

	public static String writeUsingDOM(Study study) throws Exception {
		Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
		// create root: <record>
		Element root = doc.createElement(Study.RECORD);
		doc.appendChild(root);

		// create: <study>
		Element tagStudy = doc.createElement(Study.STUDY);
		root.appendChild(tagStudy);
		// add attr: id =
		tagStudy.setAttribute(Study.ID, String.valueOf(study.mId));

		// create: <topic>
		Element tagTopic = doc.createElement(Study.TOPIC);
		tagStudy.appendChild(tagTopic);
		tagTopic.setTextContent(study.mTopic);

		// create: <content>
		Element tagContent = doc.createElement(Study.CONTENT);
		tagStudy.appendChild(tagContent);
		tagContent.setTextContent(study.mContent);

		// create: <author>
		Element tagAuthor = doc.createElement(Study.AUTHOR);
		tagStudy.appendChild(tagAuthor);
		tagAuthor.setTextContent(study.mAuthor);

		// create: <date>
		Element tagDate = doc.createElement(Study.DATE);
		tagStudy.appendChild(tagDate);
		tagDate.setTextContent(study.mDate);

		// create Transformer object
		Transformer transformer = TransformerFactory.newInstance().newTransformer();
		StringWriter writer = new StringWriter();
		StreamResult result = new StreamResult(writer);
		transformer.transform(new DOMSource(doc), result);

		// return XML string
		return writer.toString();
	}

The Good:

  • Implementable for dynamic data output.
  • Flexible XML configuration.

The Bad:

  • Too much object creations, using a lot.
  • Performance gets worse if XML document is large.

3. Using XMLSerializer

	public static String writeUsingXMLSerializer(Study study) throws Exception {
		XmlSerializer xmlSerializer = Xml.newSerializer();
		StringWriter writer = new StringWriter();

		xmlSerializer.setOutput(writer);
		// start DOCUMENT
		xmlSerializer.startDocument("UTF-8", true);
		// open tag: <record>
		xmlSerializer.startTag("", Study.RECORD);
		// open tag: <study>
		xmlSerializer.startTag("", Study.STUDY);
		xmlSerializer.attribute("", Study.ID, String.valueOf(study.mId));

		// open tag: <topic>
		xmlSerializer.startTag("", Study.TOPIC);
		xmlSerializer.text(study.mTopic);
		// close tag: </topic>
		xmlSerializer.endTag("", Study.TOPIC);

		// open tag: <content>
		xmlSerializer.startTag("", Study.CONTENT);
		xmlSerializer.text(study.mContent);
		// close tag: </content>
		xmlSerializer.endTag("", Study.CONTENT);

		// open tag: <author>
		xmlSerializer.startTag("", Study.AUTHOR);
		xmlSerializer.text(study.mAuthor);
		// close tag: </author>
		xmlSerializer.endTag("", Study.AUTHOR);

		// open tag: <date>
		xmlSerializer.startTag("", Study.DATE);
		xmlSerializer.text(study.mDate);
		// close tag: </date>
		xmlSerializer.endTag("", Study.DATE);

		// close tag: </study>
		xmlSerializer.endTag("", Study.STUDY);
		// close tag: </record>
		xmlSerializer.endTag("", Study.RECORD);

		// end DOCUMENT
		xmlSerializer.endDocument();

		return writer.toString();
	}

The Good:

  • Not like DOM, it requires only at least two objects to create XML document.
  • The syntax is so damn easy to work with.
  • The performance is pretty good.

The Bad:

  • At this point, I’ve not faced any drawback of using this.

4. Simple Framework

Homepage: http://simple.sourceforge.net/

This is an amazing XML Serialization/De-serialization, it is really easy to use and having quite good performance on XML data structure.

However, I’m not going to talk about it here, so you might want to discover about it yourselves. Or maybe, I will give a quick look over this framework in another article.

Well, it’s end for today post, and happy learning!

Be await for the next article on the series.

Cheers,

Pete Houston

Advertisements

Create and use a Compound Control

July 9, 2011 11 comments

What is Compound Control?

Basically, it is a widget/control that containing a group of other controls, something like: an ImageView and a TextView can be used as one instead of two separate controls….

Today, I will guide you on creating a Compound Control like below (one part in my next release Android Application)

Compound Control: HeroInfo Control

Compound Control: HeroInfo Control

I named it HeroInfoControl. As you see on the screenshot, there are three same compound controls I created.

Each HeroInfoControl will display information of one hero in DotA :D, my favorite game!

A – Design the layout

The control contains:

+ a hero icon on the very left of the layout, I define all image displayed here with size 48×48 in pixels.

+ on the top right is also one image that displays hero title

+ on the bottom right is a text which displays hero name.

Generally, a parent ViewGroup appropriate for this one is LinearLayout and a sub LinearLayout to contain the part on the right.

There should a space between the left and the right of the main layout, so a marginRight needs to defined, I guess “5-10dip” is good enough.

The hero name needs to be bold somehow.

The hero name and hero title somehow need to be padded on top and bottom to make it a little center horizontal aligning to the hero icon. It looks a bit nicer then.

That’s all I have for sketching the layout, let’s define it into XML:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:orientation="horizontal"
	android:layout_width="fill_parent"
	android:layout_height="wrap_content">

	<ImageView
		android:id="@+id/ivIcon"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:scaleType="fitCenter"
		android:layout_marginRight="5dip"
	/>

	<LinearLayout
		android:orientation="vertical"
		android:layout_width="fill_parent"
		android:layout_height="fill_parent"
	>

		<ImageView
			android:id="@+id/ivTitle"
			android:layout_width="fill_parent"
			android:layout_height="wrap_content"
			android:scaleType="fitStart"
			android:paddingTop="5dip"
			android:paddingLeft="10dip"
		/>

		<TextView
			android:id="@+id/tvName"
			android:layout_width="fill_parent"
			android:layout_height="wrap_content"
			android:layout_weight="1"
			android:gravity="left|bottom"
			android:paddingBottom="5dip"
			android:paddingLeft="10dip"
			android:textStyle="bold"
			android:textSize="15sp"
		/>

	</LinearLayout>

</LinearLayout>

B – Code for Layout

The next part is to define the layout and create the real control to use.

Since the parent layout used is LinearLayout, I will extend my compound control to LinearLayout class.

package pete.android.study;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

public class HeroInfoControl extends LinearLayout {

	private ImageView mHeroIcon;
	private ImageView mHeroTitle;
	private TextView mHeroName;

	public HeroInfoControl(Context context) {
		super(context);

		loadViews();
	}

	public HeroInfoControl(Context context, AttributeSet attrs) {
		super(context, attrs);

		LayoutInflater inflater = LayoutInflater.from(context);
		inflater.inflate(R.layout.hero_info, this);

		loadViews();
	}

	private void loadViews() {
		mHeroIcon = (ImageView)findViewById(R.id.ivIcon);
		mHeroTitle = (ImageView)findViewById(R.id.ivTitle);
		mHeroName = (TextView)findViewById(R.id.tvName);
	}

	public void setHeroIcon(Drawable icon) {
		mHeroIcon.setImageDrawable(icon);
	}

	public void setHeroTitle(Drawable title) {
		mHeroTitle.setImageDrawable(title);
	}

	public void setHeroName(String name) {
		mHeroName.setText("::" + name + "::");
	}

}

You need the constructor with AttributeSet in order to use it in XML layout. Well, it’s quite simple, I guess no need to explain the above code.

So, we’ve done creating our control, it’s time to use it!

C – Use the Control

As sample, I will put three controls in layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >

	<pete.android.study.HeroInfoControl
		android:id="@+id/heroLuna"
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"
		android:layout_marginTop="5dip"
		android:layout_marginBottom="5dip"
	>
	</pete.android.study.HeroInfoControl>

	<pete.android.study.HeroInfoControl
		android:id="@+id/heroTiny"
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"
		android:layout_marginTop="5dip"
		android:layout_marginBottom="5dip"
	>
	</pete.android.study.HeroInfoControl>

	<pete.android.study.HeroInfoControl
		android:id="@+id/heroKael"
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"
		android:layout_marginTop="5dip"
		android:layout_marginBottom="5dip"
	>
	</pete.android.study.HeroInfoControl>

</LinearLayout>

You probably need to put all images into resources folder.

Remember to use your control with fully qualified tag like above, otherwise, it won’t work.

Make code and set their values:

package pete.android.study;

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

public class MainActivity extends Activity {
    HeroInfoControl heroLuna;
    HeroInfoControl heroTiny;
    HeroInfoControl heroKael;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        heroLuna = (HeroInfoControl)findViewById(R.id.heroLuna);
        heroLuna.setHeroIcon(getResources().getDrawable(R.drawable.luna));
        heroLuna.setHeroTitle(getResources().getDrawable(R.drawable.luna_title));
        heroLuna.setHeroName("Luna Moonfang");

        heroTiny = (HeroInfoControl)findViewById(R.id.heroTiny);
        heroTiny.setHeroIcon(getResources().getDrawable(R.drawable.tiny));
        heroTiny.setHeroTitle(getResources().getDrawable(R.drawable.tiny_title));
        heroTiny.setHeroName("Tiny");

        heroKael = (HeroInfoControl)findViewById(R.id.heroKael);
        heroKael.setHeroIcon(getResources().getDrawable(R.drawable.kael));
        heroKael.setHeroTitle(getResources().getDrawable(R.drawable.kael_title));
        heroKael.setHeroName("Kael");
    }
}

There you go, your compound control is done with the sample.
You can make any kind of control you want 🙂
Hope you like it!

Cheers,
Pete Houston