04.Anddoid2010. 6. 15. 09:35
반응형

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
Posted by 1010