We
will create an android rss feed example app that get RSS Feed news from REUTERS, CNN and BBC.
Create
a project name getnet, package name is com.example.getnet,
add permission in to file Manifest.xml.
<uses-permission android:name="android.permission.INTERNET"
/>
MinSDK
from 8.
Add
these lines in to class Main declaration.
android:screenOrientation="portrait"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
Use
this link to download http client package.
In
Eclipse, right click on to project, Build Path, Configure Build Path, Add
External JARs, open download folder, lib, choose all jars file, OK.
Create
a class name NewsItemFactory.
import org.xmlpull.v1.XmlPullParser;
import
org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class NewsItemFactory {
public static class NewsItem {
public String title;
public String link;
public String description;
@Override
public String toString() {
return title;
}
}
public static List<NewsItem>
parseFeed(XmlPullParser parser)
throws XmlPullParserException,
IOException {
List<NewsItem> items = new ArrayList<NewsItem>();
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
if (parser.getName().equals("rss") ||
parser.getName().equals("channel")) {
//Skip these items, but allow to drill inside
} else if (parser.getName().equals("item")) {
NewsItem newsItem = readItem(parser);
items.add(newsItem);
} else {
//Skip any other elements and their children
skip(parser);
}
}
return items;
}
private static NewsItem readItem(XmlPullParser parser) throws XmlPullParserException,
IOException {
NewsItem newsItem = new NewsItem();
//Must start with an <item> element to be valid
parser.require(XmlPullParser.START_TAG, null, "item");
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
String name = parser.getName();
if (name.equals("title")) {
parser.require(XmlPullParser.START_TAG, null, "title");
newsItem.title = readText(parser);
parser.require(XmlPullParser.END_TAG, null, "title");
} else if (name.equals("link")) {
parser.require(XmlPullParser.START_TAG, null, "link");
newsItem.link = readText(parser);
parser.require(XmlPullParser.END_TAG, null, "link");
} else if (name.equals("description")) {
parser.require(XmlPullParser.START_TAG, null, "description");
newsItem.description = readText(parser);
parser.require(XmlPullParser.END_TAG, null, "description");
} else {
//Skip any other elements, and their children
skip(parser);
}
}
return newsItem;
}
private static String readText(XmlPullParser parser) throws IOException,
XmlPullParserException {
String result = "";
if (parser.next() == XmlPullParser.TEXT) {
result = parser.getText();
parser.nextTag();
}
return result;
}
private static void skip(XmlPullParser parser) throws XmlPullParserException,
IOException {
if (parser.getEventType() != XmlPullParser.START_TAG) {
throw new IllegalStateException();
}
int depth = 1;
while (depth != 0) {
switch (parser.next()) {
case XmlPullParser.END_TAG:
depth--;
break;
case XmlPullParser.START_TAG:
depth++;
break;
}
}
}
}
Create
a class name RestTask.
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.lang.ref.WeakReference;
import java.net.HttpURLConnection;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.List;
import android.os.AsyncTask;
import android.util.Log;
import org.apache.http.NameValuePair;
import
org.apache.http.client.HttpResponseException;
public class RestTask extends AsyncTask<Void, Integer,
Object> {
private static final String TAG = "RestTask";
public interface ResponseCallback {
public void onRequestSuccess(String response);
public void onRequestError(Exception error);
}
public interface ProgressCallback {
public void onProgressUpdate(int progress);
}
private HttpURLConnection mConnection;
private String mFormBody;
private File mUploadFile;
private String mUploadFileName;
private WeakReference<ResponseCallback> mResponseCallback;
private WeakReference<ProgressCallback> mProgressCallback;
public RestTask(HttpURLConnection connection) {
mConnection = connection;
}
public void
setFormBody(List<NameValuePair> formData) {
if (formData == null) {
mFormBody = null;
return;
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < formData.size(); i++) {
NameValuePair item = formData.get(i);
sb.append( URLEncoder.encode(item.getName()) );
sb.append("=");
sb.append( URLEncoder.encode(item.getValue()) );
if (i != (formData.size() - 1)) {
sb.append("&");
}
}
mFormBody = sb.toString();
}
public void setUploadFile(File file, String fileName) {
mUploadFile = file;
mUploadFileName = fileName;
}
public void
setResponseCallback(ResponseCallback callback) {
mResponseCallback = new
WeakReference<ResponseCallback>(callback);
}
public void
setProgressCallback(ProgressCallback callback) {
mProgressCallback = new
WeakReference<ProgressCallback>(callback);
}
private void writeMultipart(String boundary, String charset, OutputStream output, boolean writeContent) throws IOException {
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new OutputStreamWriter(output, Charset.forName(charset)), 8192);
// Post Form Data Component
if (mFormBody != null) {
writer.write("--" + boundary);
writer.write("\r\n");
writer.write("Content-Disposition:
form-data; name=\"parameters\"");
writer.write("\r\n");
writer.write("Content-Type:
text/plain; charset=" + charset);
writer.write("\r\n");
writer.write("\r\n");
if (writeContent) {
writer.write(mFormBody);
}
writer.write("\r\n");
writer.flush();
}
// Send binary file.
writer.write("--" + boundary);
writer.write("\r\n");
writer.write("Content-Disposition:
form-data; name=\"" + mUploadFileName
+ "\";
filename=\""
+ mUploadFile.getName() + "\"");
writer.write("\r\n");
writer.write("Content-Type:
"
+ URLConnection.guessContentTypeFromName(mUploadFile
.getName()));
writer.write("\r\n");
writer.write("Content-Transfer-Encoding:
binary");
writer.write("\r\n");
writer.write("\r\n");
writer.flush();
if (writeContent) {
InputStream input = null;
try {
input = new FileInputStream(mUploadFile);
byte[] buffer = new byte[1024];
for (int length = 0; (length = input.read(buffer)) > 0;) {
output.write(buffer, 0, length);
}
// Don't close the OutputStream
yet
output.flush();
} catch (IOException e) {
Log.w(TAG, e);
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
}
}
}
}
// This CRLF signifies the end of the binary data
chunk
writer.write("\r\n");
writer.flush();
// End of multipart/form-data.
writer.write("--" + boundary + "--");
writer.write("\r\n");
writer.flush();
} finally {
if (writer != null) {
writer.close();
}
}
}
private void writeFormData(String charset, OutputStream output) throws IOException {
try {
output.write(mFormBody.getBytes(charset));
output.flush();
} finally {
if (output != null) {
output.close();
}
}
}
@Override
protected Object doInBackground(Void... params) {
//Generate random string for boundary
String boundary = Long.toHexString(System.currentTimeMillis());
String charset = Charset.defaultCharset().displayName();
try {
// Set up output if applicable
if (mUploadFile != null) {
//We must do a multipart request
mConnection.setRequestProperty("Content-Type",
"multipart/form-data;
boundary=" + boundary);
//Calculate the size of the extra metadata
ByteArrayOutputStream bos = new ByteArrayOutputStream();
writeMultipart(boundary, charset, bos, false);
byte[] extra = bos.toByteArray();
int contentLength = extra.length;
//Add the file size to the length
contentLength += mUploadFile.length();
//Add the form body, if it exists
if (mFormBody != null) {
contentLength += mFormBody.length();
}
mConnection.setFixedLengthStreamingMode(contentLength);
} else if (mFormBody != null) {
//In this case, it is just form data to post
mConnection.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded;
charset=" + charset);
mConnection.setFixedLengthStreamingMode(mFormBody.length());
}
//This is the first call on URLConnection that
actually
// does Network IO. Even openConnection() is still just
// doing local operations.
mConnection.connect();
// Do output if applicable (for a POST)
if (mUploadFile != null) {
OutputStream out = mConnection.getOutputStream();
writeMultipart(boundary, charset, out, true);
} else if (mFormBody != null) {
OutputStream out = mConnection.getOutputStream();
writeFormData(charset, out);
}
// Get response data
int status = mConnection.getResponseCode();
if (status >= 300) {
String message = mConnection.getResponseMessage();
return new HttpResponseException(status, message);
}
InputStream in = mConnection.getInputStream();
String encoding = mConnection.getContentEncoding();
int contentLength = mConnection.getContentLength();
if (encoding == null) {
encoding = "UTF-8";
}
byte[] buffer = new byte[1024];
int length = contentLength > 0 ? contentLength : 0;
ByteArrayOutputStream out = new ByteArrayOutputStream(length);
int downloadedBytes = 0;
int read;
while ((read = in.read(buffer)) != -1) {
downloadedBytes += read;
publishProgress((downloadedBytes * 100) / contentLength);
out.write(buffer, 0, read);
}
return new String(out.toByteArray(), encoding);
} catch (Exception e) {
Log.w(TAG, e);
return e;
} finally {
if (mConnection != null) {
mConnection.disconnect();
}
}
}
@Override
protected void onProgressUpdate(Integer... values) {
// Update progress UI
if (mProgressCallback != null && mProgressCallback.get() != null) {
mProgressCallback.get().onProgressUpdate(values[0]);
}
}
@Override
protected void onPostExecute(Object result) {
if (mResponseCallback != null && mResponseCallback.get() != null) {
if (result instanceof String) {
mResponseCallback.get().onRequestSuccess((String) result);
} else if (result instanceof Exception) {
mResponseCallback.get().onRequestError((Exception) result);
} else {
mResponseCallback.get().onRequestError(new IOException("Unknown Error Contacting
Host"));
}
}
}
}
Create a class name RestUtil.
import java.io.File;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import org.apache.http.NameValuePair;
import android.util.Base64;
public class RestUtil {
public static RestTask obtainGetTask(String url)
throws MalformedURLException, IOException {
HttpURLConnection connection = (HttpURLConnection) (new URL(url))
.openConnection();
connection.setReadTimeout(10000);
connection.setConnectTimeout(15000);
connection.setDoInput(true);
RestTask task = new RestTask(connection);
return task;
}
public static RestTask
obtainAuthenticatedGetTask(String url,
String username, String password) throws MalformedURLException,
IOException {
HttpURLConnection connection = (HttpURLConnection) (new URL(url))
.openConnection();
connection.setReadTimeout(10000);
connection.setConnectTimeout(15000);
connection.setDoInput(true);
attachBasicAuthentication(connection, username, password);
RestTask task = new RestTask(connection);
return task;
}
public static RestTask
obtainFormPostTask(String url,
List<NameValuePair> formData) throws MalformedURLException,
IOException {
HttpURLConnection connection = (HttpURLConnection) (new URL(url))
.openConnection();
connection.setReadTimeout(10000);
connection.setConnectTimeout(15000);
connection.setDoOutput(true);
RestTask task = new RestTask(connection);
task.setFormBody(formData);
return task;
}
public static RestTask
obtainAuthenticatedFormPostTask(String url,
List<NameValuePair> formData, String username, String password) throws MalformedURLException,
IOException {
HttpURLConnection connection = (HttpURLConnection) (new URL(url))
.openConnection();
connection.setReadTimeout(10000);
connection.setConnectTimeout(15000);
connection.setDoOutput(true);
attachBasicAuthentication(connection, username, password);
RestTask task = new RestTask(connection);
task.setFormBody(formData);
return task;
}
public static RestTask
obtainMultipartPostTask(String url,
List<NameValuePair> formPart, File file, String fileName)
throws MalformedURLException, IOException {
HttpURLConnection connection = (HttpURLConnection) (new URL(url))
.openConnection();
connection.setReadTimeout(10000);
connection.setConnectTimeout(15000);
connection.setDoOutput(true);
RestTask task = new RestTask(connection);
task.setFormBody(formPart);
task.setUploadFile(file, fileName);
return task;
}
private static void
attachBasicAuthentication(URLConnection connection, String username, String password) {
//Add Basic Authentication Headers
String userpassword = username + ":" + password;
String encodedAuthorization = Base64.encodeToString(userpassword.getBytes(), Base64.NO_WRAP);
connection.setRequestProperty("Authorization", "Basic
"+
encodedAuthorization);
}
}
In
layout folder, create a file name lim.xml like
this.
<?xml version="1.0"
encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ads="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="40sp"
android:orientation="horizontal"
>
<TextView
android:id="@+id/tem"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="3sp"
android:gravity="center_vertical"
android:textColor="#4B4542"
android:textSize="15sp"
/>
</RelativeLayout>
File
activity_main.xml look like this.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:background="#ffffff"
tools:context="com.example.getnet.MainActivity"
>
<LinearLayout
android:id="@+id/tem"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="horizontal"
>
<TextView
android:id="@+id/t"
android:layout_width="80dp"
android:layout_height="45dp"
android:layout_gravity="center"
android:clickable="true"
android:gravity="center"
android:onClick="on"
android:textColor="#00f"
android:textSize="17sp"
/>
<TextView
android:id="@+id/t2"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:clickable="true"
android:gravity="center"
android:onClick="on2"
android:textColor="#0000cd"
android:textSize="17sp"
/>
</LinearLayout>
<ListView
android:id="@+id/li"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_below="@+id/tem"
android:layout_gravity="center"
>
</ListView>
</RelativeLayout>
Class
MainActivity like this.
import java.io.StringReader;
import org.xmlpull.v1.XmlPullParser;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.util.Xml;
import android.view.View;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import com.example.getnet.NewsItemFactory.NewsItem;
import com.example.getnet.RestTask.ResponseCallback;
public class MainActivity extends Activity implements ResponseCallback {
private static final String TAG = "FeedReader";
String FEED_URI = "http://feeds.reuters.com/reuters/entertainment";
private ListView mList;
private ArrayAdapter<NewsItem> mAdapter;
private ProgressDialog mProgress;
TextView t,t2;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
t = (TextView) findViewById(R.id.t3);
t.setText("CNN");
t2 =
(TextView) findViewById(R.id.t4);
t2.setText("BBC");
mList
= (ListView) findViewById(R.id.li);
mAdapter = new ArrayAdapter<NewsItem>(this, R.layout.lim, R.id.tem);
mList.setAdapter(
mAdapter);
mList.setOnItemClickListener(new
AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?>
parent, View v, int
position, long id) {
NewsItem item = mAdapter.getItem(position);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(item.link));
startActivity(intent);
}
});
}
public void on2(View v){
FEED_URI = "http://feeds.bbci.co.uk/vietnamese/rss.xml";
try{
RestTask task = RestUtil.obtainGetTask(FEED_URI);
task.setResponseCallback(this);
task.execute();
mProgress = ProgressDialog.show(this, "Searching", "Waiting For Results...", true);
}
catch (Exception e) {
Log.w(TAG, e);
}
}
public void on(View v){
FEED_URI = "http://rss.cnn.com/rss/cnn_latest.rss";
try{
RestTask task = RestUtil.obtainGetTask(FEED_URI);
task.setResponseCallback(this);
task.execute();
mProgress = ProgressDialog.show(this, "Searching", "Waiting For Results...", true);
}
catch (Exception e) {
Log.w(TAG, e);
}
}
@Override
public void onResume() {
super.onResume();
//Retrieve the RSS feed
try{
RestTask task = RestUtil.obtainGetTask(FEED_URI);
task.setResponseCallback(this);
task.execute();
mProgress = ProgressDialog.show(this, "Searching", "Waiting For Results...", true);
} catch (Exception e) {
Log.w(TAG, e);
}
}
@Override
public void onRequestSuccess(String response) {
if (mProgress != null) {
mProgress.dismiss();
mProgress = null;
}
//Process the response data
try {
XmlPullParser parser = Xml.newPullParser();
parser.setInput(new
StringReader(response));
//Jump to the first tag
parser.nextTag();
mAdapter.clear();
for(NewsItem item
: NewsItemFactory.parseFeed(parser))
{
mAdapter.add(item);
}
mAdapter.notifyDataSetChanged();
} catch (Exception e) {
Log.w(TAG, e);
}
}
@Override
public void onRequestError(Exception error) {
if (mProgress != null) {
mProgress.dismiss();
mProgress = null;
}
//Display the error
mAdapter.clear();
mAdapter.notifyDataSetChanged();
Toast.makeText(this, error.getMessage(), Toast.LENGTH_SHORT).show();
}
}