android rss
In this tutorial, we’ll be discussing Android RSS Reader and develop an RSS Feed Reader app in android studio.
The Android RSS Feed Reader app would showcase Movie Reviews from two popular websites.
在本教程中,我们将讨论Android RSS Reader并在android studio中开发RSS Feed Reader应用。
Android RSS Feed Reader应用程序将展示来自两个热门网站的电影评论。
Android RSS阅读器 (Android RSS Reader)
RSS stands for Really Simple Syndication. Websites generally provide RSS Feeds for their content. It’s in XML format and is typically used to access the latest contents fed in the website.
RSS代表Really Simple Syndication。 网站通常会为其内容提供RSS Feed。 它采用XML格式,通常用于访问网站中提供的最新内容。
An RSS Feed xml document looks like this:
RSS Feed xml文档如下所示:
<channel>
<title></title>
<link></link>
<description></description>
<item>
<title></title>
<link></link>
<pubDate></pubDate>
<description></description>
</item>
<item>
.
.
.
.
</item>
</channel>
channel is the root element used to hold the below-mentioned elements.
title is the title of the website.
link contains the url of the website
item element consists of contents of the website. Each item describes the title, url, publication date and description(body) of the respective content.
channel是用于容纳以下元素的根元素。
title是网站的标题。
链接包含网站的网址
item元素包含网站内容。 每个项目均描述相应内容的标题,URL,发布日期和描述(正文)。
In our following Android Project, we’ll use DocumentBuilderFactory instance to parse the xml document.
We’ll be using HttpClient and jsoup jar library to fetch the XML feed contents of the websites in an AsyncTask.
We’ll be developing an application that fetches the movies reviews from two of the websites: Rediff.com and Cinemablend.com using their RSS Feed and display the items in the form of a ListView. Clicking any of the ListView would open its content inside a WebView. Let’s get started.
在下面的Android项目中,我们将使用DocumentBuilderFactory实例来解析xml文档。
我们将使用HttpClient和jsoup jar库在AsyncTask中获取网站的XML feed内容。
我们将开发一个应用程序,使用其RSS Feed从两个网站(Rediff.com和Cinemablend.com)获取电影评论,并以ListView的形式显示项目。 单击任何ListView将在WebView中打开其内容。 让我们开始吧。
Android RSS Feed阅读器项目结构 (Android RSS Feed Reader Project Structure)
The project consists of three activities.
The First contains two Buttons that’ll act as links to the RSS Feeds of the two websites.
The second would display the latest RSS Feeds containing the Movie Reviews in the form of a ListView.
The third would open up the link from any of the List Row selected in the previous activity and load the URL in a WebView.
We’ve imported the jsoup.jar in our libs folder.
We need to set useLibrary 'org.apache.http.legacy'
in our android{} block in the build.gradle as shown below:
该项目包括三个活动。
第一个包含两个按钮,将充当两个网站的RSS源的链接。
第二个将以ListView的形式显示包含电影评论的最新RSS Feed。
第三个将打开上一个活动中选择的任何“列表行”中的链接,并将URL加载到WebView中。
我们已经将jsoup.jar导入了我们的libs文件夹。
我们需要在useLibrary 'org.apache.http.legacy'
android {}块中设置useLibrary 'org.apache.http.legacy'
,如下所示:
This is done to allow HtttpClient and HttpUrlConnection classes to be imported in our activities.
这样做是为了允许在我们的活动中导入HtttpClient和HttpUrlConnection类。
Android RSS阅读器代码 (Android RSS Reader Code)
The code for the activity_main.xml layout class is given below:
下面给出了activity_main.xml布局类的代码:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<Button
android:id="@+id/btnRediff"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="REDIFF.COM RSS FEED" />
<Button
android:id="@+id/btnCinemaBlend"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="CINEMA BLEND RSS FEED" />
</LinearLayout>
The code for the MainActivity.java class is given below:
MainActivity.java类的代码如下:
package com.journaldev.androidrssfeedtutorial;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
ArrayList<String> rssLinks = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btnRediff = findViewById(R.id.btnRediff);
Button btnCinemaBlend = findViewById(R.id.btnCinemaBlend);
btnRediff.setOnClickListener(this);
btnCinemaBlend.setOnClickListener(this);
rssLinks.add("https://www.rediff.com/rss/moviesreviewsrss.xml");
rssLinks.add("https://www.cinemablend.com/rss_review.php");
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.btnRediff:
startActivity(new Intent(MainActivity.this, RSSFeedActivity.class).putExtra("rssLink", rssLinks.get(0)));
break;
case R.id.btnCinemaBlend:
startActivity(new Intent(MainActivity.this, RSSFeedActivity.class).putExtra("rssLink", rssLinks.get(1)));
break;
}
}
}
In this, we pass over the RSS Url links via Intents to the RSSFeedActivity.java class that we’ll see next.
在此,我们通过Intents将RSS Url链接传递到我们将在下面看到的RSSFeedActivity.java类。
The code for the activity_rss_feed.xml layout is given below:
下面给出了activity_rss_feed.xml布局的代码:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/relativeLayout"
android:orientation="vertical">
<ListView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:dividerHeight="1dp" />
</RelativeLayout>
The code for the RSSFeedActivity.java class which extends a ListActivity is given below.
下面给出了扩展ListActivity的RSSFeedActivity.java类的代码。
package com.journaldev.androidrssfeedtutorial;
import android.app.ListActivity;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
public class RSSFeedActivity extends ListActivity {
private ProgressBar pDialog;
ArrayList<HashMap<String, String>> rssItemList = new ArrayList<>();
RSSParser rssParser = new RSSParser();
Toolbar toolbar;
List<RSSItem> rssItems = new ArrayList<>();
private static String TAG_TITLE = "title";
private static String TAG_LINK = "link";
private static String TAG_PUB_DATE = "pubDate";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_rss_feed);
String rss_link = getIntent().getStringExtra("rssLink");
new LoadRSSFeedItems().execute(rss_link);
ListView lv = getListView();
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Intent in = new Intent(getApplicationContext(), BrowserActivity.class);
String page_url = ((TextView) view.findViewById(R.id.page_url)).getText().toString().trim();
in.putExtra("url", page_url);
startActivity(in);
}
});
}
public class LoadRSSFeedItems extends AsyncTask<String, String, String> {
@Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressBar(RSSFeedActivity.this, null, android.R.attr.progressBarStyleLarge);
RelativeLayout relativeLayout = findViewById(R.id.relativeLayout);
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT
);
lp.addRule(RelativeLayout.CENTER_IN_PARENT);
pDialog.setLayoutParams(lp);
pDialog.setVisibility(View.VISIBLE);
relativeLayout.addView(pDialog);
}
@Override
protected String doInBackground(String... args) {
// rss link url
String rss_url = args[0];
// list of rss items
rssItems = rssParser.getRSSFeedItems(rss_url);
// looping through each item
for (RSSItem item : rssItems) {
// creating new HashMap
if (item.link.toString().equals(""))
break;
HashMap<String, String> map = new HashMap<String, String>();
// adding each child node to HashMap key => value
String givenDateString = item.pubdate.trim();
SimpleDateFormat sdf = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z");
try {
Date mDate = sdf.parse(givenDateString);
SimpleDateFormat sdf2 = new SimpleDateFormat("EEEE, dd MMMM yyyy - hh:mm a", Locale.US);
item.pubdate = sdf2.format(mDate);
} catch (ParseException e) {
e.printStackTrace();
}
map.put(TAG_TITLE, item.title);
map.put(TAG_LINK, item.link);
map.put(TAG_PUB_DATE, item.pubdate); // If you want parse the date
// adding HashList to ArrayList
rssItemList.add(map);
}
// updating UI from Background Thread
runOnUiThread(new Runnable() {
public void run() {
ListAdapter adapter = new SimpleAdapter(
RSSFeedActivity.this,
rssItemList, R.layout.rss_item_list_row,
new String[]{TAG_LINK, TAG_TITLE, TAG_PUB_DATE},
new int[]{R.id.page_url, R.id.title, R.id.pub_date});
// updating listview
setListAdapter(adapter);
}
});
return null;
}
protected void onPostExecute(String args) {
pDialog.setVisibility(View.GONE);
}
}
}
In this, we instantiate an instance of RSSParser class.
Inside the LoadRSSFeedItems AsyncTask method we call getRSSFeedItems()
to get the RSSItems from the URL which are then stored inside an ArrayList of rssItems. The RSSItems ArrayList is then eventually loaded into the ListView rows.
在此,我们实例化RSSParser类的实例。
在LoadRSSFeedItems AsyncTask方法内部,我们调用getRSSFeedItems()
从URL获取getRSSFeedItems()
,然后将其存储在rssItems的ArrayList中。 然后,将RSSItems ArrayList最终加载到ListView行中。
The code for the rss_item_list_row.xml layout is given below:
rss_item_list_row.xml布局的代码如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="8dip">
<TextView
android:id="@+id/page_url"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:visibility="gone" />
<TextView
android:id="@+id/title"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingBottom="1dip"
android:textColor="#212121"
android:textSize="18sp"
android:textStyle="bold" />
<TextView
android:id="@+id/pub_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/title"
android:paddingBottom="3dip"
android:textColor="#9b737775"
android:textSize="14sp" />
</RelativeLayout>
On ListView row click listener we pass the current item’s url to the next Activity in the key url
. Before we look at the next activity let’s see the RSSItem.java and RSSParser.java classes.
在ListView行单击侦听器上,我们将当前项目的url传递给键url
的下一个Activity。 在查看下一个活动之前,让我们看一下RSSItem.java和RSSParser.java类。
RSSItem.java
RSSItem.java
package com.journaldev.androidrssfeedtutorial;
/
public class RSSItem {
public String title;
public String link;
public String description;
public String pubdate;
public String guid;
public RSSItem(String title, String link, String description, String pubdate, String guid) {
this.title = title;
this.link = link;
this.description = description;
this.pubdate = pubdate;
this.guid = guid;
}
}
RSSParser.java
This is responsible for parsing the xml feed document.
RSSParser.java
这负责解析xml feed文档。
package com.journaldev.androidrssfeedtutorial;
import android.util.Log;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import java.io.IOException;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
public class RSSParser {
// RSS XML document CHANNEL tag
private static String TAG_CHANNEL = "channel";
private static String TAG_TITLE = "title";
private static String TAG_LINK = "link";
private static String TAG_DESRIPTION = "description";
private static String TAG_ITEM = "item";
private static String TAG_PUB_DATE = "pubDate";
private static String TAG_GUID = "guid";
// constructor
public RSSParser() {
}
public List<RSSItem> getRSSFeedItems(String rss_url) {
List<RSSItem> itemsList = new ArrayList<RSSItem>();
String rss_feed_xml;
rss_feed_xml = this.getXmlFromUrl(rss_url);
if (rss_feed_xml != null) {
try {
Document doc = this.getDomElement(rss_feed_xml);
NodeList nodeList = doc.getElementsByTagName(TAG_CHANNEL);
Element e = (Element) nodeList.item(0);
NodeList items = e.getElementsByTagName(TAG_ITEM);
for (int i = 0; i < items.getLength(); i++) {
Element e1 = (Element) items.item(i);
String title = this.getValue(e1, TAG_TITLE);
String link = this.getValue(e1, TAG_LINK);
String description = this.getValue(e1, TAG_DESRIPTION);
String pubdate = this.getValue(e1, TAG_PUB_DATE);
String guid = this.getValue(e1, TAG_GUID);
RSSItem rssItem = new RSSItem(title, link, description, pubdate, guid);
// adding item to list
itemsList.add(rssItem);
}
} catch (Exception e) {
// Check log for errors
e.printStackTrace();
}
}
// return item list
return itemsList;
}
public String getXmlFromUrl(String url) {
String xml = null;
try {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
HttpResponse httpResponse = httpClient.execute(httpGet);
HttpEntity httpEntity = httpResponse.getEntity();
xml = EntityUtils.toString(httpEntity);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// return XML
return xml;
}
public Document getDomElement(String xml) {
Document doc = null;
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try {
DocumentBuilder db = dbf.newDocumentBuilder();
InputSource is = new InputSource();
is.setCharacterStream(new StringReader(xml));
doc = db.parse(is);
} catch (ParserConfigurationException e) {
Log.e("Error: ", e.getMessage());
return null;
} catch (SAXException e) {
Log.e("Error: ", e.getMessage());
return null;
} catch (IOException e) {
Log.e("Error: ", e.getMessage());
return null;
}
return doc;
}
public final String getElementValue(Node elem) {
Node child;
if (elem != null) {
if (elem.hasChildNodes()) {
for (child = elem.getFirstChild(); child != null; child = child
.getNextSibling()) {
if (child.getNodeType() == Node.TEXT_NODE || (child.getNodeType() == Node.CDATA_SECTION_NODE)) {
return child.getNodeValue();
}
}
}
}
return "";
}
public String getValue(Element item, String str) {
NodeList n = item.getElementsByTagName(str);
return this.getElementValue(n.item(0));
}
}
getRSSFeedItems()
is what returns the RSSItem List to the RSSFeedActivity.java.
getRSSFeedItems()
是将RSSItem列表返回到RSSFeedActivity.java的内容。
The code for the activity_browser.xml layout is given below.
下面给出了activity_browser.xml布局的代码。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:id="@+id/relativeLayout"
android:layout_height="match_parent">
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<WebView
android:id="@+id/webView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.v4.widget.NestedScrollView>
</RelativeLayout>
The code for the BrowserActivity.java class is given below.
下面给出了BrowserActivity.java类的代码。
package com.journaldev.androidrssfeedtutorial;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.webkit.WebChromeClient;
import android.webkit.WebResourceError;
import android.webkit.WebResourceRequest;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;
public class BrowserActivity extends AppCompatActivity {
WebView webView;
String url;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_browser);
Intent in = getIntent();
url = in.getStringExtra("url");
if (TextUtils.isEmpty(url)) {
Toast.makeText(getApplicationContext(), "URL not found", Toast.LENGTH_SHORT).show();
finish();
}
webView = findViewById(R.id.webView);
initWebView();
webView.loadUrl(url);
}
private void initWebView() {
webView.setWebChromeClient(new MyWebChromeClient(this));
webView.clearCache(true);
webView.getSettings().setJavaScriptEnabled(true);
webView.setHorizontalScrollBarEnabled(false);
webView.setWebViewClient(new WebViewClient() {
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
webView.loadUrl(url);
return true;
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
}
@Override
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
super.onReceivedError(view, request, error);
invalidateOptionsMenu();
}
});
webView.clearCache(true);
webView.clearHistory();
webView.getSettings().setJavaScriptEnabled(true);
webView.setHorizontalScrollBarEnabled(false);
}
private class MyWebChromeClient extends WebChromeClient {
Context context;
public MyWebChromeClient(Context context) {
super();
this.context = context;
}
}
}
The url passed from the RSSFeedActivity.java Activity is loaded here.
从RSSFeedActivity.java Activity传递的url被加载到这里。
The output of the above application in action is given below.
This brings an end to this tutorial. You can download the Android RSSFeedTutorial from the link below.
本教程到此结束。 您可以从下面的链接下载Android RSSFeedTutorial。
android rss