1. Data Feed / RSS 예제

요즘 많은 종류의 데이터를 인터넷에서 공짜로 받을수있습니다. 이는 일반적으로 RSS 를 통해서 이루어지는데 여기서 데이터를 뽑아내는 핵심은 URL 을 던진후 돌아오는 문자의 스트림을 어떻게 XML parse 할수있느냐에 달려있습니다. 이 XML parser 는 몇가지가 있는데 여기에서는 org.xml.sax 에 있는 parser 를 이용해 봅니다.
1. 일단 이런 인터넷상에서 데이터를 가져오는 작업은 시간이 좀 걸리기에 이 예제에서는 ProgressDialog 를 무조건 화면에 뿌렸습니다.
2. 이후 데이타가 도착하고 parsing 이 끝나 화면에 뿌릴준비가되면 ProgressDialog 를 걷어내라는 신호를 Handler 에 보내고
3. Handler 는 이를 받아 ProgressDialog 를 없애고 화면을 뿌립니다.
private final Handler handler = new Handler() {
@Override
public void handleMessage(final Message msg) {
progressDialog.dismiss();
tv_nodata = (TextView) findViewById(R.id.tv_nodata);
if ((mChannelItems == null) || (mChannelItems.size() == 0)) {
tv_nodata.setText("No Data");
}
else {
tv_nodata.setText(mURL);
listview = (ListView) findViewById(R.id.listview01);
ChannelBaseAdapter cba =
new ChannelBaseAdapter(RSSTester1.this,
R.layout.channel_view_detail,
mChannelItems);
listview.setAdapter(cba);
listview.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView parent, View v, int position, long id) {
}
});
}
}
};
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.channel_view);
progressDialog = ProgressDialog.show(this, " Working...", " Retrieving RSS feed", true, false);
new Thread() {
@Override
public void run() {
//mURL = "http://feeds.feedburner.com/usccb/zHqS";
//mURL = "http://www.thetechtrader.com/rss/closing_commentary.rss";
mURL = "http://blogs.wsj.com/marketbeat/feed/";
getData(mURL);
handler.sendEmptyMessage(0);
}
}.start();
}
public void getData(String urlString) {
try {
URL url = new URL(urlString);
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
XMLReader xmlreader = parser.getXMLReader();
ChannelHandler theRssHandler = new ChannelHandler();
xmlreader.setContentHandler(theRssHandler);
InputSource is = new InputSource(url.openStream());
is.setEncoding("ISO-8859-1"); // just for WSJ.
xmlreader.parse(is);
mChannelItems = theRssHandler.getChannelItems();
}
catch (Exception e) {
e.printStackTrace();
}
}
.
여기서 getData 를 주시해서 보기바랍니다.
이 부분이 밖의 인터넷에서 데이터를 요구하고 받아오는 부분입니다.
xmlreader.parse(is) 에 의해 parse 가 된 데이터는 ChannelHandler 로 보내집니다. 이 내부에서 저는 필요한 데이터만 뽑아내게 됩니다. ChannelHandler 는 DefaultHandler 를 상속받아만드는데, 이안에는 중요한 5개의 메소드가 있습니다.
1. startDocument
2. startElement
3. endElement
4. endDocument
5. characters
.
startDocument 는 들어오는 XML 의 시작입니다. 그러면 끝은 endDocument 이겠죠.
startElement 는 XML tag 의 시작입니다. 끝은 endElement 가 될겁니다.
character 는 문자 스트립을 받을수있는곳입니다.
.
startELement 에서 만약 title 이라는 tag 가 보이면 isTitle 를 true 로 셋합니다.
character 에서는 isTitle 이 true 인동안은 문자를 받아 mChannelItem.title 에 저장합니다.
endElement 에서 현재의 tag 가 title 인데 isTitle 이 true 라면 당연히 isTitle 을 false 로 만들어 character 가 Title쪽 문자를 받는일을 더이상하지 않도록 합니다.
.이와같은 일을 다른 tag 에 대해서도하면 원하는 tag 의 내용을 다받을수있습니다. 여기서는 간단히 title 과 날짜, link 정보만을 받아 화면에 뿌렸습니다.
.
그럼 이 다섯가지 메소드를 감상해보시죠.
@Override
public void startDocument() throws SAXException {
}
@Override
public void startElement(final String namespaceURI, final String localName, final String qName,
final Attributes atts) throws SAXException {
if (localName.equals(ITEM)) {
inItem = true;
mChannelItem = new ChannelData();
}
if (inItem) {
if (localName.equals(TITLE)) inTitle = true;
else if (localName.equals(LINK)) inLink = true;
else if (localName.equals(PUBDATE)) inPubDate = true;
//else if (localName.equals(DESC)) inDesc = true;
else if (localName.equals(LINK2)) inLink2 = true;
else if (localName.equals(DURATION)) inDuration = true;
}
}
@Override
public void endDocument() throws SAXException {
}
@Override
public void endElement(final String namespaceURI, final String localName, final String qName) throws SAXException {
if (localName.equals(ITEM)) {
inItem = false;
mChannelItems.add(mChannelItem);
}
if (inItem) {
if (localName.equals(TITLE)) inTitle = false;
else if (localName.equals(LINK)) inLink = false;
else if (localName.equals(PUBDATE)) inPubDate = false;
else if (localName.equals(LINK2)) inLink2 = false;
else if (localName.equals(DURATION)) inDuration = false;
}
}
@Override
public void characters(final char ch[], final int start, final int length) {
String chString = "";
if (ch != null) {
chString = new String(ch, start, length);
}
if (inTitle) {
mChannelItem.title = chString;
}
if (inLink) {
mChannelItem.link = chString;
}
if (inPubDate) {
// hack to replace "UT" with GMT (UT won't parse)
if (chString.contains("UT")) {
chString = chString.replace("UT", "GMT");
}
mChannelItem.pubDate2 = chString;
// try to handle the various date formats
Date pubDate = null;
try {
pubDate = ChannelHandler.DATE_FORMAT_A.parse(chString);
}
catch (ParseException e) {
// swallow
}
if (pubDate == null) {
try {
pubDate = ChannelHandler.DATE_FORMAT_B.parse(chString);
}
catch (ParseException e) {
// swallow
}
}
mChannelItem.pubDate1 = pubDate;
}
if (inLink2) {
mChannelItem.link2 = chString;
}
if (inDuration) {
mChannelItem.duration = chString;
}
출처 : http://rsequence.com/android_blog/node/125