How to Read Rss Feed in Java
For this Android developer tutorial, we are going to create a simple RSS reader app. This app would fetch RSS feeds from a single, user specified internet address, and display the contents using a RecyclerView. If you aren't familiar with the RecyclerView widget, check out our previous tutorial on using a RecyclerView.
RSS, or Rich Site Summary, is an easy and efficient way to share snippets of frequently updated data such equally blog entries or news items with subscribers. Nearly every news website today has an RSS feed, and these feeds can be accessed through dedicated readers or through your favorite browser. An RSS feed usually contains a summary of the new content, rather than the entire news (or blog) article. To answer your question, yes, Android Authority has an RSS feed, available at http://feed.androidauthority.com/, and y'all should subscribe, if you oasis't already. :D
Sample RSS Feed
An RSS feed is a obviously text document, formatted in XML. Beingness XML, it is relatively easy for humans to read, and likewise not difficult for programs to parse. A sample XML document is shown beneath.
Code
<?xml version="1.0" encoding="UTF-8" ?> <rss version="ii.0"> <aqueduct> <title>RSS Title</title> <clarification>This is an example of an RSS feed</description> <link>http://www.example.com/main.html</link> <lastBuildDate>Mon, 06 Sep 2010 00:01:00 +0000 </lastBuildDate> <pubDate>Dominicus, 06 Sep 2009 16:20:00 +0000</pubDate> <ttl>1800</ttl> <item> <championship>Example entry</championship> <description>Here is some text containing an interesting description.</description> <link>http://www.example.com/blog/mail service/1</link> <guid isPermaLink="true">7bd204c6-1655-4c27-aeee-53f933c5395f</guid> <pubDate>Sun, 06 Sep 2009 16:20:00 +0000</pubDate> </item> <detail> <championship>Second case entry</title> <description>More than text containing even more interesting description.</clarification> <link>http://world wide web.case.com/blog/mail service/2</link> <guid isPermaLink="true">7a4a56b6-1655-4c27-aeee-33e4453f2675</guid> <pubDate>Lord's day, 06 Sep 2009 18:14:00 +0000</pubDate> </particular> </channel> </rss>
We tin run into from the sample above, the feed has a title, a description, link, final build date, a publish date and a time to alive. For this tutorial, we are only interested in the title, description and link.
At that place are besides two items in the feed, and each has a title, a description and a link, along with a guid (globally unique identifier) and publish engagement. Nigh feed items take other tags, but, for our unproblematic RSS reader, we are only concerned with the title, description and link.
Preparing the projection
Of course, the kickoff thing we will exercise is create a new Android Studio projection with an empty activity, which we've named SimpleRSSReader. In the AndroidManifiest.xml file, we include the INTERNET permission. Since the rss reader volition fetch feeds from the internet, nosotros must declare this permission.
Lawmaking
<uses-permission android:name="android.permission.INTERNET" />
Lawmaking
compile 'com.android.support:appcompat-v7:25.0.1' compile 'com.android.support:recyclerview-v7:25.0.ane' compile 'com.android.back up:design:25.0.1'
Great. With the initial setup complete, let's get to work.
Pattern the layout
For our simple app, we desire the user to enter a target RSS feed url, and when he clicks a button, our rss reader app volition fetch the feed and display the feed items in a recyclerview.
Code
<?xml version="1.0" encoding="utf-eight"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.sample.foo.simplerssreader.MainActivity"> <Button android:id="@+id/fetchFeedButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentEnd="true" android:text="Fetch" /> <android.support.design.widget.TextInputLayout android:id="@+id/textInputLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginEnd="@dimen/activity_horizontal_margin" android:layout_toStartOf="@id/fetchFeedButton" android:hint="Rss feed source"> <EditText android:id="@+id/rssFeedEditText" android:layout_width="match_parent" android:layout_height="wrap_content" /> </android.support.pattern.widget.TextInputLayout> <TextView android:id="@+id/feedTitle" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/textInputLayout" android:text="Feed Championship: " /> <TextView android:id="@+id/feedDescription" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/feedTitle" android:text="Feed Description: " /> <TextView android:id="@+id/feedLink" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/feedDescription" android:text="Feed Link: " /> <android.support.v4.widget.SwipeRefreshLayout android:id="@+id/swipeRefreshLayout" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@id/feedLink" android:layout_marginTop="@dimen/activity_vertical_margin"> <android.support.v7.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent" /> </android.back up.v4.widget.SwipeRefreshLayout> </RelativeLayout>
Did yous observe that nosotros enclosed our recyclerview inside a SwipeRefreshLayout? A SwipeRefreshLayout is a pattern support library widget that allows users pull downwards to refresh, and shows a nice circular progress bar.
Creating the MainActivity
Within the MainActivity class, the kickoff thing we do is define references to the EditText, the Button, RecyclerView and SwipeLayout. We as well setup a click listener for the Button, and an OnRefreshListener for the SwipeRefreshLayout.
Lawmaking
public course MainActivity extends AppCompatActivity { private RecyclerView mRecyclerView; individual EditText mEditText; private Button mFetchFeedButton; individual SwipeRefreshLayout mSwipeLayout; individual TextView mFeedTitleTextView; private TextView mFeedLinkTextView; private TextView mFeedDescriptionTextView; private List<RssFeedModel> mFeedModelList; private Cord mFeedTitle; individual String mFeedLink; private Cord mFeedDescription; @Override protected void onCreate(Packet savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView); mEditText = (EditText) findViewById(R.id.rssFeedEditText); mFetchFeedButton = (Button) findViewById(R.id.fetchFeedButton); mSwipeLayout = (SwipeRefreshLayout) findViewById(R.id.swipeRefreshLayout); mFeedTitleTextView = (TextView) findViewById(R.id.feedTitle); mFeedDescriptionTextView = (TextView) findViewById(R.id.feedDescription); mFeedLinkTextView = (TextView) findViewById(R.id.feedLink); mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); mFetchFeedButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { new FetchFeedTask().execute((Void) null); } }); mSwipeLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { new FetchFeedTask().execute((Void) naught); } }); } }
Both the Button and SwipeRefreshLayout perform the same activeness, which is to starting time a new FetchFeedTask. The FetchFeedTask is an AsyncTask, which allows us perform possible long running tasks in a background thread. If you try to fetch feeds from a url on the main thread, your app volition get unresponsive, and can appear to the user to have stopped working. Ever since Ice-cream Sandwich, Android no longer allows apps make network calls on the main thread. For a refresher on using AsyncTask, you tin can check out our previous commodity that discussed how to use a web API from your Android app.
The FetchFeedTask has three simple methods:
- onPreExecute, which is called before the long running chore starts, and is executed on the calling thread.
- doInBackground, which is the long running task, and is executed in a new thread
- onPostExecute, which is called afterward the long running task is complete, and is executed on the calling thread.
Since Android allows manipulation of UI elements (Buttons, SwipeRefreshLayout, etc) just on the UI/Primary thread, we tin update the UI both in onPreExecute, and onPostExecute, merely non in doInBackground.
Lawmaking
individual course FetchFeedTask extends AsyncTask<Void, Void, Boolean> { individual String urlLink; @Override protected void onPreExecute() { mSwipeLayout.setRefreshing(true); urlLink = mEditText.getText().toString(); } @Override protected Boolean doInBackground(Void... voids) { if (TextUtils.isEmpty(urlLink)) return false; endeavor { if(!urlLink.startsWith("http://") && !urlLink.startsWith("https://")) urlLink = "http://" + urlLink; URL url = new URL(urlLink); InputStream inputStream = url.openConnection().getInputStream(); mFeedModelList = parseFeed(inputStream); render true; } catch (IOException e) { Log.eastward(TAG, "Error", e); } take hold of (XmlPullParserException e) { Log.due east(TAG, "Error", e); } return false; } @Override protected void onPostExecute(Boolean success) { mSwipeLayout.setRefreshing(simulated); if (success) { mFeedTitleTextView.setText("Feed Title: " + mFeedTitle); mFeedDescriptionTextView.setText("Feed Clarification: " + mFeedDescription); mFeedLinkTextView.setText("Feed Link: " + mFeedLink); // Fill up RecyclerView mRecyclerView.setAdapter(new RssFeedListAdapter(mFeedModelList)); } else { Toast.makeText(MainActivity.this, "Enter a valid Rss feed url", Toast.LENGTH_LONG).show(); } } }
In the code snippet above, y'all can run across that we only update the UI in onPreExecute and onPostExecute, while all the computation is done within doInBackground. We define FetchFeedTask as an inner class in MainActivity, then that we can admission the MainActivity layout widgets.
In doInBackground, we first confirm that the url entered is not empty, then we add together a 'http://' to the url if the user left it out. The adjacent step is to open a url connexion, using the url.getConnection().getInputStream() method. Finally, we call a method named parseFeed() to parse the resulting RSS feed.
Parsing the RSS feed
Thankfully, android contains some utility classes and interfaces to handle XML parsing. For our rss reader, we will use an XmlPullParser example to handle parsing the feed. XmlPullParser can have either an InputStream or a Reader every bit the source of data. Nosotros merely read each XML tag in the RSS feed until we become to the end of the certificate. You can run across in the code snippet below, that we are merely interested in the XML tag if information technology is either championship, description or link.
Code
public List<RssFeedModel> parseFeed(InputStream inputStream) throws XmlPullParserException, IOException { Cord title = null; String link = cypher; String clarification = null; boolean isItem = false; List<RssFeedModel> items = new ArrayList<>(); effort { XmlPullParser xmlPullParser = Xml.newPullParser(); xmlPullParser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, imitation); xmlPullParser.setInput(inputStream, naught); xmlPullParser.nextTag(); while (xmlPullParser.side by side() != XmlPullParser.END_DOCUMENT) { int eventType = xmlPullParser.getEventType(); String name = xmlPullParser.getName(); if(proper name == null) go along; if(eventType == XmlPullParser.END_TAG) { if(name.equalsIgnoreCase("detail")) { isItem = false; } go along; } if (eventType == XmlPullParser.START_TAG) { if(name.equalsIgnoreCase("item")) { isItem = truthful; go on; } } Log.d("MyXmlParser", "Parsing name ==> " + name); String upshot = ""; if (xmlPullParser.side by side() == XmlPullParser.TEXT) { result = xmlPullParser.getText(); xmlPullParser.nextTag(); } if (name.equalsIgnoreCase("title")) { title = upshot; } else if (proper noun.equalsIgnoreCase("link")) { link = result; } else if (name.equalsIgnoreCase("description")) { clarification = consequence; } if (title != cipher && link != zilch && description != null) { if(isItem) { RssFeedModel detail = new RssFeedModel(championship, link, description); items.add(item); } else { mFeedTitle = title; mFeedLink = link; mFeedDescription = description; } title = goose egg; link = null; description = zero; isItem = false; } } render items; } finally { inputStream.close(); } }
RssFeedModel is a simple helper class we created to hold title, description and link information for an RSS feed item.
Code
public class RssFeedModel { public String title; public Cord link; public String description; public RssFeedModel(Cord title, String link, Cord description) { this.championship = title; this.link = link; this.description = clarification; } }
Displaying the feeds
At this point, we are ready to fetch, and parse RSS feeds. However, nosotros still need to display the results in our rss reader RecyclerView. Call back that in the onPostExecute() method higher up, there is the line:
Code
mRecyclerView.setAdapter(new RssFeedListAdapter(mFeedModelList));
One time over again, if you haven't used a RecyclerView before, cheque out our previous tutorial on Using RecyclerView. It is very like shooting fish in a barrel and straightforward to use. To brandish each feed particular, we create a layout file, called item_rss_feed.xml.
Code
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:id="@+id/titleText" android:layout_width="match_parent" android:layout_height="wrap_content" android:textStyle="bold" /> <TextView android:id="@+id/descriptionText" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:id="@+id/linkText" android:layout_width="match_parent" android:layout_height="wrap_content" /> <View android:layout_width="match_parent" android:layout_height="1dp" android:background="@color/colorAccent" /> </LinearLayout>
And finally, the RssFeedListAdapter.
Code
public class RssFeedListAdapter extends RecyclerView.Adapter<RssFeedListAdapter.FeedModelViewHolder> { private List<RssFeedModel> mRssFeedModels; public static class FeedModelViewHolder extends RecyclerView.ViewHolder { private View rssFeedView; public FeedModelViewHolder(View v) { super(5); rssFeedView = v; } } public RssFeedListAdapter(List<RssFeedModel> rssFeedModels) { mRssFeedModels = rssFeedModels; } @Override public FeedModelViewHolder onCreateViewHolder(ViewGroup parent, int type) { View v = LayoutInflater.from(parent.getContext()) .inflate(R.layout.item_rss_feed, parent, faux); FeedModelViewHolder holder = new FeedModelViewHolder(v); return holder; } @Override public void onBindViewHolder(FeedModelViewHolder holder, int position) { terminal RssFeedModel rssFeedModel = mRssFeedModels.get(position); ((TextView)holder.rssFeedView.findViewById(R.id.titleText)).setText(rssFeedModel.title); ((TextView)holder.rssFeedView.findViewById(R.id.descriptionText)) .setText(rssFeedModel.description); ((TextView)holder.rssFeedView.findViewById(R.id.linkText)).setText(rssFeedModel.link); } @Override public int getItemCount() { return mRssFeedModels.size(); } }
Wrap up
Equally always, the consummate source is bachelor on github. Y'all can look into styling your item_rss_feed.xml, displaying more content than simply the item title, description and link, and/or, for the adventurous, writing your own RSS news aggreagator with multiple feeds from multiple sources.
Happy coding.
Source: https://www.androidauthority.com/simple-rss-reader-full-tutorial-733245/
0 Response to "How to Read Rss Feed in Java"
Post a Comment