This App has been developed as part of the Udacity Android Basics Nanodegree Course for the Exercise Project "News Feed App". App connects to the Guardian News API to retrieve the News Feed based on the particular endpoint used and then displays them as a list.
Android device running with Android OS 4.0.4 (API Level 15) or above. Best experienced on Android Nougat 7.1 and above. Designed for Phones and NOT for Tablets.
- Register for the Developer API Key from the Guardian Open Platform. Registration is free of cost.
- Create a Properties File named application.properties in the Project's root folder.
- Define a property named GUARDIAN_API_KEY_VAL and assign it the value of the API Key obtained from the Registration process.
- If the above API Key is not defined, then the App will use the default "test" API Key which is heavily rate-limited. Whenever the rate-limit is hit, the app may crash or not display proper results.
- The Developer API Key is also rate-limited, but not as limited as the default "test" API Key.
- App queries the
content.guardianapis.com
API to fetch news stories and properly parses the JSON Response. - Each List item displayed by the App for the News stories should contain relevant text and information about the story. This includes -
- Name of the Section.
- Title of the article.
- Author Name if present.
- Published date of the article if present.
- Default text is shown when any of the above parsed information is not available.
- Networking operations are to be done using Loaders.
- Clicking on a story should open the story in the user's browser.
- No external libraries to be used.
- On device rotation
- The layout remains scrollable.
- The app saves state and restores the list back to the previously scrolled position.
- The UI properly adjusts so that all contents of each list item is still visible and not truncated/overlapped.
- When new News data is fetched, the main screen should update properly with the new data.
- Check whether connected to internet or not. Also, validate for any occurrence of bad server response or lack of response.
- Used
RecyclerView
in place ofListView
(to display the News stories) for its advantages in performance and easy placeholders for custom item decoration. - Custom RecyclerView.ItemDecoration for adding space between the News List items.
CardView
for displaying the News stories content for each News List items.- Custom Navigation Drawer Items implemented using
RecyclerView
. - Explored FragmentStatePagerAdapter that displays the Fragments (retaining their state) for the
ViewPager
. Also, mocks the dynamic adding of additional tab content to theViewPager
. - Implemented Settings using
android.support.v7.preference.Preference
. - No external libraries are used for communicating with the REST API and also for loading the images.
AsyncTaskLoader
has been used for downloading the data and images in the background thread. Images are downloaded using a Headless Fragment. - Developed BitmapImageCache utility that uses
android.util.LruCache
to cache the recent Bitmap Images downloaded. - Most layouts are designed using
ConstraintLayout
to flatten the layout hierarchy as far as possible. - TextAppearanceUtility for decorating
TextViews
using Spannables, for image within text and html content in text. - Custom Fonts for
TextViews
usingResourceCompat
. - Explored
CoordinatorLayout
. - Used
RecyclerView
in aSwipeRefreshLayout
to use the integrated Progress/Refresh indicator. - Used
DiffUtil
inRecyclerView
to help rebind only the item views that have changed.
App consists of a Drawer for Navigating between News related Fragments.
The Drawer consists of -
- Headlines
- Random News
- Bookmarked News
- Favorited News
Apart from the above which are Fragments by themselves, the Drawer also has a menu for Settings and About which are Activities.
The Activity that inflates this Drawer Layout is the NewsActivity. The Drawer Layout is custom built using a RecyclerView
whose items are loaded by the NavRecyclerAdapter. This Drawer is completely managed by the NewsActivity.
This is the Default Fragment loaded when the App is launched. This Fragment inflates the layout which consists of a ViewPager
with FragmentStatePagerAdapter for displaying each of the Subscribed News Sections/Topics. HeadlinesFragment
acts as the Parent Fragment for all the Child Fragments shown by the ViewPager (i.e., the ViewPager
's Adapter is set up using the ChildFragmentManager
)
The layout used here is a CoordinatorLayout
which hides the custom toolbar when scrolled to bottom. On launch, this loads the first tab of the ViewPager
which is the Highlights tab shown by the Child Fragment - HighlightsFragment. This tab is responsible for showing a list of Subscribed News Topics with the current News Article count on each topic. Three News Topics are always presubscribed as shown -
- Top Stories
- Top Stories shows a list of Editor Picked News items. Content is only affected by the start date (
from-date
query parameter) of the News feed mentioned in the Request URL. Results appear only in a single page. Sample URL used is http://content.guardianapis.com/international?show-editors-picks=true&from-date=2017-12-01&show-fields=trailText,byline,thumbnail&api-key=test
- Top Stories shows a list of Editor Picked News items. Content is only affected by the start date (
- Most Visited
- Most Visited shows a list of Most Viewed News Items. Content is only affected by the start date (
from-date
query parameter) of the News feed mentioned in the Request URL. Results appear only in a single page. Sample URL used is http://content.guardianapis.com/international?show-most-viewed=true&from-date=2017-12-01&show-fields=trailText,byline,thumbnail&api-key=test
- Most Visited shows a list of Most Viewed News Items. Content is only affected by the start date (
- World News
- World News shows a list of News Items that falls under the World section. This is also a type Paginated News as the Results can appear in more than a single page. Content is affected by the change in start date, current page number, number of items in a page and the sort order of the results. Sample URL used is http://content.guardianapis.com/world?from-date=2017-12-01&show-fields=trailText,byline,thumbnail&order-by=relevance&order-date=published&page-size=10&page=1&api-key=test
Clicking on any of the Subscribed News Item in the HighlightsFragment, will take the user to the corresponding ViewPager
Tab.
Each of these tabs as described above, displays the parsed News Article Items in a RecyclerView
of CardView item views. These Item Views, inflated by the ArticlesAdapter, supports Card expand/collapse to reveal more content on expansion as shown below.
Clicking on any of the News Articles Card Items, will navigate the user to the corresponding News Article in the user's selected browser. These News Article Card items also supports Popup Menu options.
- Share News
- Uses
ShareCompat
's Intent Builder for sharing the Web URL of the News Article Item to any app, when clicked.
- Uses
- Read Later
- On click of this, the corresponding News Article Item will be added to the "Bookmarked News" for reading later. At present, this only shows the acknowledgement of the Action but does nothing since this is not implemented yet. The corresponding Action is managed by the Presenter BookmarkActionPresenter
- Favorite This
- On click of this, the corresponding News Article Item will be added to the "Favorited News" as your Favorite. At present, this only shows the acknowledgement of the Action but does nothing since this is not implemented yet. The corresponding Action is managed by the Presenter FavoriteActionPresenter
- Open News Section
- Clicking this, will Navigate the user to the Tab of the requested News Topic if already subscribed; if not subscribed then it will show the "+" Tab which is the MoreNewsFragment that allows the user to subscribe to the requested News Topic.
The MoreNewsFragment
is always the last tab of the ViewPager
shown by the HeadlinesFragment
. It allows subscribing to additional News Topics. When Navigated by the Open News Section, user can only subscribe to the requested News Topic provided that topic was previously not subscribed. If user wants to subscribe to multiple topics, then the user needs to navigate to the last tab using the "Subscribe More" menu button shown in the "Highlights Tab and then use the button to subscribe.
Subscription to multiple topics is currently not implemented/supported as this will require the use of Database for storing the subscribed list. Also, once a user is subscribed to a particular requested topic, it will stay subscribed only till the lifetime of the HeadlinesFragment
as this data is maintained in the instance bundle of the Parent Fragment HeadlinesFragment
.
All additional subscribed News Topics are paginated and are affected by the various parameters, that also affects the "World News Topic. All these topics talk to the Guardian News with the Sample URL http://content.guardianapis.com/sectionId?from-date=2017-12-01&show-fields=trailText,byline,thumbnail&order-by=relevance&order-date=published&page-size=10&page=1&api-key=test where sectionId path will be replaced the sectionId of the Subscribed News Topic.
Pagination is managed through a custom panel interface that is shown only when the scroll reaches the last few items in the RecyclerView
. If the items in the RecyclerView
is very less for scroll, then the panel will be always shown. This is implemented by extending RecyclerView.OnScrollListener
which is done by the class BaseRecyclerViewScrollListener. This is an abstract class which provides an event callback when the scroll reaches the last 3 items in the list, to reveal the pagination buttons for the user to navigate to different pages in the current News Topic Tab. The Pagination work is always delegated to the Presenter - PaginationPresenter by the Fragment requiring the Pagination.
RandomNewsFragment is the second fragment shown in the Drawer of NewsActivity
. It provides the user with the ability to Search for any content supported by the Guardian News API. It uses the Search endpoint (https://content.guardianapis.com/search) for retrieving the results on the search query entered by the user. Pagination Panel will always be shown since Search endpoint returns results that support pagination. Content is affected by the Search Query entered, start date of the News, current page number, number of items in a page and the sort order of the results.
News Article card items supports the same set of features as available in HeadlinesFragment
(since it employs the same ArticlesAdapter
), with an exception that "Open News Section" will be programmatically removed since it is not supported.
BookmarksFragment is the third fragment shown in the Drawer of NewsActivity
. It is meant for displaying a list of News Article items that were Bookmarked by the user, in other News Fragments through the "Read Later" Popup menu option on the News Article Item Card. Currently, this is not implemented, hence no items will be shown. This is just a placeholder for future ideas/implementation.
FavoritesFragment is the fourth fragment shown in the Drawer of NewsActivity
. It is meant for displaying a list of News Article items that were Favorited by the user, in other News Fragments through the "Favorite This" Popup menu option on the News Article Item Card. Currently, this is not implemented, hence no items will be shown. This is just a placeholder for future ideas/implementation.
The Results shown in the Fragments of HeadlinesFragment
and RandomNewsFragment
can be controlled by varying certain parameters embedded in the Request URL. This is defined by the Guardian News API which this application is based on and is acting as a client that receives the data for the request executed.
All the parameters affecting the results can be altered by the "Settings" menu item available in each of the News Fragments and also on the Drawer menu. The Settings menu item, opens up the preferences.xml loaded by the activity SettingsActivity. It implements the android.support.v7.preference.Preference
Preferences. As such all the values are stored in the default SharedPreferences
. These preferences provides options to override the parameters used in the news feed request, and following are the ones that can be changed -
order-by
parameter defines the sorting order of results. This is controlled by the "Sort by" ListPreference.order-date
parameter defines on how the sorting needs to be done. This is controlled by the "Sort based on" ListPreference.page-size
parameter defines the number of news items to be displayed in a page. This is controlled by the "News items per page" NumberPickerPreference. This Preference is a custom NumberPickerPreference implemented by extending theDialogPreference
.from-date
parameter defines the start date for the News feed request. This is controlled by the "Specify Start Period" DatePickerPreference. This Preference is a custom DatePickerPreference implemented by extending theDialogPreference
.
The from-date
parameter is also controlled by other preferences, that provides the user to preset the start date to a particular date based on certain criteria. Unchecking the "Start Period Preset/Manual" CheckBoxPreference, will cause the start date to be set automatically based on the other two dependent preferences that gets enabled -
- "Preset Start Period" preference is a ListPreference, that allows the user to preset the start date to say 'today'/'start of the week'/'start of the month'.
- "Buffer to Start Period" preference is a custom NumberPickerPreference, that allows the user to specify some number of buffer days to the "Preset Start Period" specified. Example, if "Preset Start Period" is set to "Start of the Week" and the predetermined date falls to (01/01/2018); and if "Buffer to Start Period" is set to 4 days buffer, then the final start date calculated will be (28/03/2018).
The date determined in the above settings will be written to the from-date
key in the SharedPreferences
.
There is also another preference setting displayed as "Reset Settings", which resets all the preferences to their default values. This is implemented by ConfirmationPreference.
- Loading of Subscribed News Articles' Count is carried out in a background thread using NewsHighlightsLoader that extends
AsyncTaskLoader
. - Loading of News Articles Data is carried out in a background thread using NewsArticlesLoader that extends
AsyncTaskLoader
. - Request and Response is carried out via a REST call (GET Method) to the Guardian News API.
- The data format used for Response communication is the JSON format.
- Talking to the REST API and parsing the response for the content is done by the utility codes.
- JsonUtility for sending request and receiving the response.
- NewsSectionInfoParserUtility for parsing the response to extract the Subscribed News Articles' Count, as defined by the model NewsSectionInfo.
- NewsArticleInfoParserUtility for parsing the response to extract the News Articles' Data, as defined by the model NewsArticleInfo.
As per the Rubric, no third party library is used for communicating with the REST API and for parsing the data.
Loading of Images for the News Articles are carried out in a background thread through a viewless Fragment ImageDownloaderFragment. Functioning of this fragment is as follows -
- It first checks whether the image to be loaded is present in the Bitmap Cache, implemented by BitmapImageCache
- If present in the cache, it updates the image to the corresponding
ImageView
passed. - If not present in cache, then the image is downloaded in a background thread using ImageDownloader that extends an
AsyncTaskLoader
. Once successfully downloaded, it updates the image to the correspondingImageView
passed, and also saves the same in the Bitmap Cache.
The identifier for the Fragment and its Loader is maintained to be unique to the item being displayed such that each item displays the correct image to be shown, without resulting in any duplication. If duplication still happens, the loader will take care of loading the correct one when the item is being displayed the second time in the screen.
As per the Rubric, no third party library is used for loading images.
-
After scrolling to certain extent in the
RecyclerView
of theViewPager
ofHeadlinesFragment
-- If the user swipes across the tabs, then the new Fragment being displayed will auto scroll to the topmost item in that Fragment.
- If the user swipes across the tabs that have paginated content, then the new Paginated Fragment being displayed will reset the current page to first page and auto scrolls to the topmost item in that Fragment.
- Clicking on the active tab again, will cause the scroll to move over to the topmost item in that Fragment.
- If the user switches the orientation, the Fragment will auto scroll to the item that was last shown.
-
Back button has different behaviors while on different screens -
- If the user is viewing any of the Tabs other than the "Highlights Tab in the
Headlines
Fragment, clickingback
key will bring the user to the "Highlights Tab. Clickingback
key again, will quit the App. - If the user is viewing any of the Drawer Items other than the
Headlines
, clickingback
key will bring the user to the "Headlines Fragment and the "Highlights Tab will be shown. Clickingback
key again, will quit the App.
- If the user is viewing any of the Tabs other than the "Highlights Tab in the
-
The
RecyclerView
used in the app is embedded in a SwipeRefreshLayout. Hence, one can refresh the content with Swipe-To-Pull Refresh. -
If the Search entered in the
RandomNewsFragment
did not yield any result, (or) if the request from theHeadlinesFragment
did not return any News items, then a "No Feed Available" page will be shown with severalCardView
s that provide information on how to resolve the issue. This is displayed by the Fragment NoFeedResolutionFragment that inflates the layout no_feed_layout.xml.
- While initiating a request, if a network connectivity issue is encountered, then a "Network Error" page will be shown, with information on how to resolve the issue. This is displayed by the Fragment NetworkErrorFragment that inflates the layout network_error_layout.xml.
This can be viewed by going into the Drawer menu item "About" of the NewsActivity
. This page describes in brief about the app, and has links to my bio and the course details hosted by Udacity. This is shown by the activity AboutActivity that inflates the layout activity_about.xml.
- Any News Article with the Topic "Global" when subscribed is currently causing a crash, since "Global" is not found to be there in any of the Sections supported by the Guardian News API. We do have something called as "Global development", but this is different.
- udacity
- Contains the code submitted for review.
- Updated Gradle version, made related changes and applied valid lint corrections.
- Added Copyright info.
- Regenerated App Icons.
- release_v1.0
- Used
ConstrainedWidth
/ConstrainedHeight
to enforceWRAP_CONTENT
constraints for certain Item Views and Dialog Layouts - (commit). - "Handling of Null Image links", and "Reading from and Writing Bitmaps to Memory cache" is now taken care by the
ImageDownloader
AsyncTaskLoader - (commit). - Enabled logging for debuggable build types only, through the use of custom Logger which is a wrapper to the
android.util.Log
- (commit). - Changed certain inner classes to static nested classes to prevent memory leaks - (commit).
- Configured an Activity Alias to launch the
NewsActivity
- (commit).
- Used
- Some of the Icons used are from Icons8 and from Material Design Icons.
- App Icon and Navigation Header Image were self made.
Copyright 2018 Kaushik N. Sanji
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.