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