Friday 30 April 2010

A simple RSS reader, in ListView

In the last exercise, "A simple RSS reader, using Android's org.xml.sax package", the RSS's titles are displayed as a single String. For sure it's not a good presentation in this way.

In this article, it will be modified to display it in ListView.



AndroidManifest.xml to grant "android.permission.INTERNET" to the application. (Refer to last article "A simple RSS reader, using Android's org.xml.sax package")

In order to use ListView, create a new file, /res/layout/rsslist.xml
<?xml version="1.0" encoding="utf-8"?>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/rowtext"
android:layout_width="fill_parent"
android:layout_height="25px"
android:textSize="10sp" />


Modify main.xml to have a ListView
<?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"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello" />
<ListView
android:id="@android:id/list"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@android:id/empty"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="No Data" />
</LinearLayout>


Modify AndroidRssReder.java
package com.exercise.AndroidRssReader;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

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 android.app.ListActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;

public class AndroidRssReader extends ListActivity {

private List<String> item = new ArrayList<String>();

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

try {
URL rssUrl = new URL("http://feeds.feedburner.com/Android-er?format=xml");
SAXParserFactory mySAXParserFactory = SAXParserFactory.newInstance();
SAXParser mySAXParser = mySAXParserFactory.newSAXParser();
XMLReader myXMLReader = mySAXParser.getXMLReader();
RSSHandler myRSSHandler = new RSSHandler();
myXMLReader.setContentHandler(myRSSHandler);
InputSource myInputSource = new InputSource(rssUrl.openStream());
myXMLReader.parse(myInputSource);

} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

ArrayAdapter<String> itemList = new ArrayAdapter<String>(this, R.layout.rsslist, item);
setListAdapter(itemList);
}

private class RSSHandler extends DefaultHandler
{
final int stateUnknown = 0;
final int stateTitle = 1;
int state = stateUnknown;

@Override
public void startDocument() throws SAXException {
// TODO Auto-generated method stub
}

@Override
public void endDocument() throws SAXException {
// TODO Auto-generated method stub
}

@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
// TODO Auto-generated method stub
if (localName.equalsIgnoreCase("title"))
{
state = stateTitle;
}
else
{
state = stateUnknown;
}
}

@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
// TODO Auto-generated method stub
state = stateUnknown;
}

@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
// TODO Auto-generated method stub
String strCharacters = new String(ch, start, length);
if (state == stateTitle)
{
item.add(strCharacters);

}
}

}
}


Download the files.


Check out Stargate Universe

If you haven't been watching it, I highly recommend the Stargate Universe series on the SyFy channel.



The basic premise is, a small band of military folks and civilians get stranded half way across the Universe. But instead of having a group of highly trained elite space travelers, most of the people are just thrown together.  Only a few have any kind of training for the situation.



The show is a lot more gritty than a lot of scifi in recent years. Definitely worth checking out.

Wednesday 28 April 2010

Paging Data with CodeIgniter

I was looking into how one would page table data using CodeIgniter. So I didn't find one answer, but found a PHP answer and the CodeIgniter documentation to answer my own question.



The PHP technique is to add a LIMIT statement to your SQL request. So if you have a table size and a location, you can page through the data easily. The php-mysql-tutorial.com has the details here. Marry this to the CodeIgniter active record documentation, and that should be all I need.

Friday 23 April 2010

How to Copy a Object in Java

Duke Waving

What is an easy way to copy a Java object? This example over at StackOverflow shows how to copy an object with a copy constructor or or a copy factory. Both approaches essentially use the new operator and the object's properties to make the copy. Simple yet effective.

Thursday 22 April 2010

A simple RSS reader, using Android's org.xml.sax package.

In the last article, "Read XML Resources in Android, using XmlResourceParser: XML parsing interface", Android application read XML resource inside application. In the current article, a external XML will be read using Android SAX APIs.

The source of XML is "http://feeds.feedburner.com/Android-er?format=xml", which is RSS feed of my blog.

SAX is the Simple API for XML, originally a Java-only API. SAX was the first widely adopted API for XML in Java, and is a �de facto� standard. The current version is SAX 2.0.1, and there are versions for several programming language environments other than Java.

org.xml.sax is a Android's package provides the core SAX APIs.

In order to make it simple, only the contents under "title" tag will be retrieved and appended as a string.



To allow the Android application, "android.permission.INTERNET" have to be granted to the application. Modify AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.exercise.AndroidRssReader"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".AndroidRssReader"
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>
<uses-sdk android:minSdkVersion="4" />
<uses-permission android:name="android.permission.INTERNET" />
</manifest>


Modify main.xml to add a TextView to display the result.
<?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"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello" />
<ScrollView
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/result" />
</ScrollView>
</LinearLayout>


Java source code.
package com.exercise.AndroidRssReader;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

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 android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class AndroidRssReader extends Activity {

String streamTitle = "";

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

TextView result = (TextView)findViewById(R.id.result);

try {
URL rssUrl = new URL("http://feeds.feedburner.com/Android-er?format=xml");
SAXParserFactory mySAXParserFactory = SAXParserFactory.newInstance();
SAXParser mySAXParser = mySAXParserFactory.newSAXParser();
XMLReader myXMLReader = mySAXParser.getXMLReader();
RSSHandler myRSSHandler = new RSSHandler();
myXMLReader.setContentHandler(myRSSHandler);
InputSource myInputSource = new InputSource(rssUrl.openStream());
myXMLReader.parse(myInputSource);

result.setText(streamTitle);

} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
result.setText("Cannot connect RSS!");
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
result.setText("Cannot connect RSS!");
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
result.setText("Cannot connect RSS!");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
result.setText("Cannot connect RSS!");
}


}

private class RSSHandler extends DefaultHandler
{
final int stateUnknown = 0;
final int stateTitle = 1;
int state = stateUnknown;

int numberOfTitle = 0;
String strTitle = "";
String strElement = "";

@Override
public void startDocument() throws SAXException {
// TODO Auto-generated method stub
strTitle = "--- Start Document ---\n";
}

@Override
public void endDocument() throws SAXException {
// TODO Auto-generated method stub
strTitle += "--- End Document ---";
streamTitle = "Number Of Title: " + String.valueOf(numberOfTitle) + "\n"
+ strTitle;
}

@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
// TODO Auto-generated method stub
if (localName.equalsIgnoreCase("title"))
{
state = stateTitle;
strElement = "Title: ";
numberOfTitle++;
}
else
{
state = stateUnknown;
}
}

@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
// TODO Auto-generated method stub
if (localName.equalsIgnoreCase("title"))
{
strTitle += strElement + "\n";
}
state = stateUnknown;
}

@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
// TODO Auto-generated method stub
String strCharacters = new String(ch, start, length);
if (state == stateTitle)
{
strElement += strCharacters;
}
}

}
}


Download the files.

Further Reading: A simple RSS reader, in ListView



Wednesday 21 April 2010

HTML5 Features You Should use Right Now

The folks at NetTuts created a video on HTML5 features you can use right now.  I would like to focus on 4 of them.



HTML DocType

Instead of including a long link to a DTD in each of your HTML documents, you can simple replace it with:

<!DOCTYPE html>


Character Set

You can define a character set much more simply.

<meta charset="utf-8"/>


No More Type Attributes

You are no longer required to add type attributes to the <style> or <script> tags. For example:

<script>
// your code here
</script>


or



<style>
p{ margin:0; }
</style>


I plan to test this a bit myself, but according to the author, Google is already using the DocType setting.

Tuesday 20 April 2010

Read XML Resources in Android, using XmlResourceParser: XML parsing interface

XmlResourceParser is the XML parsing interface returned for an XML resource. This is a standard XmlPullParser interface, as well as an extended AttributeSet interface and an additional close() method on this interface for the client to indicate when it is done reading the resource.

In this exercise, we read our own XML Resource (in /res/xml folder) using XmlResourceParser, and display the contents on screen.



First of all, create a folder /res/xml, and our own XML file myxml.xml
<?xml version="1.0" encoding="utf-8"?>
<rootelement1>
<subelement>
Hello XML Sub-Element 1
</subelement>
<subelement>
Hello XML Sub-Element 2
<subsubelement>Sub Sub Element</subsubelement>
</subelement>
</rootelement1>


Modify main.xml
<?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"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/my_xml"
/>
</LinearLayout>


Finally, modify java code
package com.exercise.AndroidXmlResource;

import java.io.IOException;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import android.app.Activity;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.os.Bundle;
import android.widget.TextView;

public class AndroidXmlResource extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

TextView myXmlContent = (TextView)findViewById(R.id.my_xml);
String stringXmlContent;
try {
stringXmlContent = getEventsFromAnXML(this);
myXmlContent.setText(stringXmlContent);
} catch (XmlPullParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

private String getEventsFromAnXML(Activity activity)
throws XmlPullParserException, IOException
{
StringBuffer stringBuffer = new StringBuffer();
Resources res = activity.getResources();
XmlResourceParser xpp = res.getXml(R.xml.myxml);
xpp.next();
int eventType = xpp.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT)
{
if(eventType == XmlPullParser.START_DOCUMENT)
{
stringBuffer.append("--- Start XML ---");
}
else if(eventType == XmlPullParser.START_TAG)
{
stringBuffer.append("\nSTART_TAG: "+xpp.getName());
}
else if(eventType == XmlPullParser.END_TAG)
{
stringBuffer.append("\nEND_TAG: "+xpp.getName());
}
else if(eventType == XmlPullParser.TEXT)
{
stringBuffer.append("\nTEXT: "+xpp.getText());
}
eventType = xpp.next();
}
stringBuffer.append("\n--- End XML ---");
return stringBuffer.toString();
}
}


Download the files.

Related Article: A simple RSS reader, using Android's org.xml.sax package.



Monday 19 April 2010

Turning a Blogger Blog into a Website

Google LogoAnother quick note. The dudes at Magic with Blogs have created a site with a number of Blogger video tutorials. If you look down at the bottom of their home page, you will notice a section on how to convert of a Blogger blog into a web site. The post on making your home page static is key.



This is an idea that will be useful for a lot of people. A quick way to setup a Website site using the best site/blog creation software on the net. Expect a few posts from me on the subject. :)

Changing Your Blogger Account and Housekeeping

Over the weekend, I did a little housekeeping on this site. I discovered that you can actually change the Google account you use to host your blog. I have done that so I will be updating the about pages and stuff with the new information. Now my twitter and buzz accounts should have a little be more consistent branding. In addition, my about and contact information will be moving to my blogger account using the new static pages feature of Blogger.



Update: Note that once you do this, you have to go to Settings -> Basic and change to the new editor if you were using that on the old blog. The same goes for any other updated features I assume.

Friday 16 April 2010

How to define dimension in Android using XML

You can create common dimensions to use for various screen elements by defining dimension values in XML.

Here is some examples to define dimension using XML.

<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="one_pixels">1px</dimen>
<dimen name="five_dp">5dp</dimen>
<dimen name="1_inch">1in</dimen>
<dimen name="1_cm">10mm</dimen>
</resources>


Thursday 15 April 2010

Media Wiki on a Stick

Want to run Media Wiki on your local machine?  Well the basic steps are described here. You basically have to download and install the MoWeS Portable server along with Media Wiki. You run the installer on your usb drive. Boom, you have MediaWiki on a USB Drive.



As a caveat, this sort of thing is not for the feint of heart. :) A basic understanding of the Apache web server is required.

Wednesday 14 April 2010

Wanna Learn Chinese?

Wanna learn Chinese?  Get started learning Chinese with Peggy Lee's You Tube channel. She also does private Chinese tutoring via skype.



What a great idea for a business!

Android - Apps can easily embed the web


Watch Android engineers demonstrate that applications on Android can easily embed the web. Apps can easily embed HTML, Javascript, and style sheets. An app can render web content through a WebView.

Sunday 11 April 2010

Steve Jobs goes Crazy and the Net Freaks Out!

While many people were watching the return of Tiger Woods and Phil Mickelson's awesome win at the Masters, the Internets were freaking out about Apple's new license agreement for iPhone development.



The story was originally broken by Daring Fireball here. And has been commented on and expanded at the following sites. All three posts are awesome and I recommend you read each.

Adobe has been developing a tool to allow Flash developers to compile Flash applications for the iPhone OS.  Thus, Flash developers could completely bypass Apple tools or compilers to create their apps. By changing the license agreement, Apple has made this Adobe tool illegal on the iPhone platform. It also limits development to Objective C, C, C++, and HTML/Javascript on Webkit. So any cross platform compiler written in Ruby, or .Net would also be illegal. So as you might imagine, this has angered developers who were planning to use these 3rd party tools.



In my mind Apple has a point. They are trying to provide a simple, stable device with consistent interfaces. Nontechie's do not care if the platform is open or closed. Regular folks don't care about multitasking. They just want their phone to work all the time. PCs crash, phones don't. By tightly controlling design and development, Apple can meet their stability and design goals.



Google Android provides the open alternative to Apple's approach. Right now it is messier and probably not as good. But it is open, and that allows developers to iterate and improve. Over time, it seems possible that it will match or surpass its closed adversary.



Developers, customers, and the market will determine which approach is best. It is going to be an interesting fight.



Thursday 8 April 2010

CSS: Center an Image with CSS

CSS ButtonI have created a short write up on how to center an image using CSS. Two methods are covered, using a div and defining rules for the img tag directly. Enjoy!

Wednesday 7 April 2010

CodeIgniter Unit Testing

CodeIgniter includes a unit test library as part of the framework. Documentation is included with the standard docs. If you follow the instructions, you can set it up and use it quite easily. However, the default output format leaves a little bit to be desired. Each test generates a separate table. This quickly becomes unwieldy and not very useful as the more tests added create longer and longer pages.



To solve the problem modified the template a little so once a table is produced with a row for each test. Here is my code.



   1:  <h2>Unit Test Page</h2>
2: <p>This is the test page for the application.</p>
3:<?php
4:$str = '
5: <tr>
6: {rows}
7: <td style="border:1pt solid black;">{result}</td>
8: {/rows}
9: </tr>';
10:
11:$this->unit->set_template($str);
12:
13:// Sample Test 1
14:$test = 1 + 1;
15:$expected_result = 2;
16:$test_name = 'Adds one plus one';
17:$this->unit->run($test, $expected_result, $test_name);
18:
19:
20:?>
21:<table cellpadding="4" cellspacing="1" style="border:1pt solid black; font-size:9pt; width:625px">
22: <tr><th width="35%">Test Name</th><th>In Type</th><th>Test Type</th><th width="15%">Result</th><th width="0%">Path</th><th>No</th></tr>
23:<?php
24:// Create Report
25:echo $this->unit->report();
26:?>
27:</table>
28:
29:</body>
30:</html>


My template is defined on lines 4-9. Basically, we only want to output a row for each test. So lines 20-27 defines the table that contains the rows. This produces much more compressed output.

Tuesday 6 April 2010

Hands on iPad

Well I finally got my hands on an iPad. It looks to be a very nice device for surfing. Plus I checked out some of the applications like the constellation app which is very cool.



I didn't care for the screen much. It has a very glossy finish and in the store it was hard to ignore all the glare. So that said, I think I'm gonna wait. I want to see some of the Google tablets before I make any decision.



The tablets are here to stay methinks. Now let the tablet wars begin!

Saturday 3 April 2010

iPad finally Released!



After much hoopla, the Apple iPad was released today. Since I'm visiting my parents in Alamosa, I'm nowhere near any Apple store. I can't find any coverage online and such, but I did find this story from the Chicago Tribune with techies commenting on the impact of the new device.



The conversation seems to be clustering around the Apple closed store and single tasking OS versus Google Android and its open store and multitasking operating system. I tend to side with the open tribe. In the long run, more open systems and software win out. Is this the PC versus Mac battle all over again? But this time, it is smart phones and tablets. With a new iPhone coming out this summer and dozens of Android devices on the way, it is going to be an interesting next couple of years.

Friday 2 April 2010

New Blogger Template Designer

Google LogoThe Google Blogger site is testing a new blog designer tool. I just noticed the announcement is a little old, but its new to me. So what's new about this design tool?



First a bunch of new templates for your blog. Very cool looking templates. In addition, the new template designer gives nondevelopers a lot more control over their templates. The main caveat? The new designs will not work on IE 6. But that is not really a big deal, because it is time to move beyond IE 6.

Thursday 1 April 2010

Generate random number in Android

To generate random number in Android, class java.util.Random can be used.

This class java.util.Random provides methods that generates pseudo-random numbers of different types, such as int, long, double, and float.

It support two public constructor:
Random() - Construct a random generator with the current time of day in milliseconds as the initial state.
Random(long seed) - Construct a random generator with the given seed as the initial state.

Generate random number in Android

main.xml
<?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"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
/>
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Generate Random number"
android:id="@+id/generate"
/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/generatenumber"
/>
</LinearLayout>


AndroidRandom.java
package com.exercise.AndroidRandom;

import java.util.Random;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class AndroidRandom extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

final Random myRandom = new Random();

Button buttonGenerate = (Button)findViewById(R.id.generate);
final TextView textGenerateNumber = (TextView)findViewById(R.id.generatenumber);

buttonGenerate.setOnClickListener(new OnClickListener(){

@Override
public void onClick(View v) {
// TODO Auto-generated method stub
textGenerateNumber.setText(String.valueOf(myRandom.nextInt()));
}});
}
}


Related:
- Generate sequence of Random number.