├── .gitignore
├── project
├── settings.gradle
├── app
│ ├── app-release.apk
│ ├── src
│ │ └── main
│ │ │ ├── res
│ │ │ ├── drawable-hdpi
│ │ │ │ ├── ic_back.png
│ │ │ │ ├── ic_plus.png
│ │ │ │ ├── ic_share.png
│ │ │ │ ├── ic_webview.png
│ │ │ │ ├── iven_icon.png
│ │ │ │ ├── ic_back_dark.png
│ │ │ │ ├── ic_plus_dark.png
│ │ │ │ ├── ic_share_dark.png
│ │ │ │ ├── ic_webview_dark.png
│ │ │ │ ├── internet_alert.png
│ │ │ │ └── iven_logo_dark.png
│ │ │ ├── drawable-mdpi
│ │ │ │ ├── ic_back.png
│ │ │ │ ├── ic_plus.png
│ │ │ │ ├── ic_share.png
│ │ │ │ ├── ic_webview.png
│ │ │ │ ├── iven_icon.png
│ │ │ │ ├── ic_back_dark.png
│ │ │ │ ├── ic_plus_dark.png
│ │ │ │ ├── ic_share_dark.png
│ │ │ │ ├── ic_webview_dark.png
│ │ │ │ ├── internet_alert.png
│ │ │ │ └── iven_logo_dark.png
│ │ │ ├── drawable-xhdpi
│ │ │ │ ├── ic_back.png
│ │ │ │ ├── ic_plus.png
│ │ │ │ ├── ic_share.png
│ │ │ │ ├── iven_icon.png
│ │ │ │ ├── ic_webview.png
│ │ │ │ ├── ic_back_dark.png
│ │ │ │ ├── ic_plus_dark.png
│ │ │ │ ├── ic_share_dark.png
│ │ │ │ ├── internet_alert.png
│ │ │ │ ├── iven_logo_dark.png
│ │ │ │ └── ic_webview_dark.png
│ │ │ ├── drawable-xxhdpi
│ │ │ │ ├── ic_back.png
│ │ │ │ ├── ic_plus.png
│ │ │ │ ├── ic_share.png
│ │ │ │ ├── ic_webview.png
│ │ │ │ ├── iven_icon.png
│ │ │ │ ├── ic_back_dark.png
│ │ │ │ ├── ic_plus_dark.png
│ │ │ │ ├── ic_share_dark.png
│ │ │ │ ├── ic_webview_dark.png
│ │ │ │ ├── internet_alert.png
│ │ │ │ └── iven_logo_dark.png
│ │ │ ├── drawable-xxxhdpi
│ │ │ │ ├── ic_back.png
│ │ │ │ ├── ic_plus.png
│ │ │ │ ├── ic_share.png
│ │ │ │ ├── iven_icon.png
│ │ │ │ ├── ic_back_dark.png
│ │ │ │ ├── ic_plus_dark.png
│ │ │ │ ├── ic_webview.png
│ │ │ │ ├── ic_share_dark.png
│ │ │ │ ├── internet_alert.png
│ │ │ │ ├── iven_logo_dark.png
│ │ │ │ └── ic_webview_dark.png
│ │ │ ├── mipmap-hdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-mdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── values-xxhdpi
│ │ │ │ └── dimens.xml
│ │ │ ├── drawable
│ │ │ │ ├── ripple.xml
│ │ │ │ ├── background_splash_connection.xml
│ │ │ │ ├── progress_background.xml
│ │ │ │ └── background_splash.xml
│ │ │ ├── values-w820dp
│ │ │ │ └── dimens.xml
│ │ │ ├── layout
│ │ │ │ ├── splash.xml
│ │ │ │ ├── recycler_view.xml
│ │ │ │ ├── recycler_view_dynamic.xml
│ │ │ │ ├── splash_no_internet.xml
│ │ │ │ ├── article_activity.xml
│ │ │ │ ├── dynamic_list.xml
│ │ │ │ ├── toolbar.xml
│ │ │ │ ├── checkbox_wb.xml
│ │ │ │ ├── articles_list.xml
│ │ │ │ ├── article_page_layout.xml
│ │ │ │ ├── home.xml
│ │ │ │ ├── preference_activity.xml
│ │ │ │ ├── dynamic_items.xml
│ │ │ │ ├── action_buttons.xml
│ │ │ │ ├── add_feed_layout.xml
│ │ │ │ ├── items.xml
│ │ │ │ ├── article_fragment.xml
│ │ │ │ └── activity_about.xml
│ │ │ ├── values-sw600dp
│ │ │ │ └── dimens.xml
│ │ │ ├── values
│ │ │ │ ├── attrs.xml
│ │ │ │ ├── dimens.xml
│ │ │ │ ├── colors.xml
│ │ │ │ ├── arrays.xml
│ │ │ │ ├── strings.xml
│ │ │ │ └── styles.xml
│ │ │ ├── menu
│ │ │ │ ├── wb_menu.xml
│ │ │ │ └── activity_main.xml
│ │ │ ├── xml
│ │ │ │ └── info_pref.xml
│ │ │ ├── values-v23
│ │ │ │ └── styles.xml
│ │ │ └── values-it
│ │ │ │ └── strings.xml
│ │ │ ├── java
│ │ │ └── com
│ │ │ │ └── iven
│ │ │ │ └── lfflfeedreader
│ │ │ │ ├── utils
│ │ │ │ ├── broadcastReceiver.java
│ │ │ │ ├── HomeUtils.java
│ │ │ │ ├── GlideUtils.java
│ │ │ │ ├── saveUtils.java
│ │ │ │ ├── ArticleUtils.java
│ │ │ │ ├── notifyService.java
│ │ │ │ └── Preferences.java
│ │ │ │ ├── domparser
│ │ │ │ ├── RSSFeed.java
│ │ │ │ ├── RSSItem.java
│ │ │ │ └── DOMParser.java
│ │ │ │ ├── mainact
│ │ │ │ ├── SplashActivity.java
│ │ │ │ ├── ArticleActivity.java
│ │ │ │ ├── FeedsAdapter.java
│ │ │ │ ├── ArticlePage.java
│ │ │ │ └── ArticleFragment.java
│ │ │ │ └── infoact
│ │ │ │ ├── InfoActivity.java
│ │ │ │ └── AboutActivity.java
│ │ │ └── AndroidManifest.xml
│ ├── proguard-rules.pro
│ └── build.gradle
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── build.gradle
├── gradle.properties
├── gradlew.bat
└── gradlew
├── COPYRIGHT
├── art
├── round.png
├── solid.png
└── screens4.png
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | *.db
--------------------------------------------------------------------------------
/project/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/COPYRIGHT:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/COPYRIGHT
--------------------------------------------------------------------------------
/art/round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/art/round.png
--------------------------------------------------------------------------------
/art/solid.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/art/solid.png
--------------------------------------------------------------------------------
/art/screens4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/art/screens4.png
--------------------------------------------------------------------------------
/project/app/app-release.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/app-release.apk
--------------------------------------------------------------------------------
/project/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-hdpi/ic_back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-hdpi/ic_back.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-hdpi/ic_plus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-hdpi/ic_plus.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-mdpi/ic_back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-mdpi/ic_back.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-mdpi/ic_plus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-mdpi/ic_plus.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-hdpi/ic_share.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-hdpi/ic_share.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-hdpi/ic_webview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-hdpi/ic_webview.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-hdpi/iven_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-hdpi/iven_icon.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-mdpi/ic_share.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-mdpi/ic_share.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-mdpi/ic_webview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-mdpi/ic_webview.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-mdpi/iven_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-mdpi/iven_icon.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-xhdpi/ic_back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-xhdpi/ic_back.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-xhdpi/ic_plus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-xhdpi/ic_plus.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-xhdpi/ic_share.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-xhdpi/ic_share.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-xhdpi/iven_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-xhdpi/iven_icon.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-xxhdpi/ic_back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-xxhdpi/ic_back.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-xxhdpi/ic_plus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-xxhdpi/ic_plus.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-xxhdpi/ic_share.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-xxhdpi/ic_share.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-xxxhdpi/ic_back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-xxxhdpi/ic_back.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-xxxhdpi/ic_plus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-xxxhdpi/ic_plus.png
--------------------------------------------------------------------------------
/project/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/project/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/project/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-hdpi/ic_back_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-hdpi/ic_back_dark.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-hdpi/ic_plus_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-hdpi/ic_plus_dark.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-mdpi/ic_back_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-mdpi/ic_back_dark.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-mdpi/ic_plus_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-mdpi/ic_plus_dark.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-xhdpi/ic_webview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-xhdpi/ic_webview.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-xxhdpi/ic_webview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-xxhdpi/ic_webview.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-xxhdpi/iven_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-xxhdpi/iven_icon.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-xxxhdpi/ic_share.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-xxxhdpi/ic_share.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-xxxhdpi/iven_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-xxxhdpi/iven_icon.png
--------------------------------------------------------------------------------
/project/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/project/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-hdpi/ic_share_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-hdpi/ic_share_dark.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-hdpi/ic_webview_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-hdpi/ic_webview_dark.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-hdpi/internet_alert.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-hdpi/internet_alert.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-hdpi/iven_logo_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-hdpi/iven_logo_dark.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-mdpi/ic_share_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-mdpi/ic_share_dark.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-mdpi/ic_webview_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-mdpi/ic_webview_dark.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-mdpi/internet_alert.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-mdpi/internet_alert.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-mdpi/iven_logo_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-mdpi/iven_logo_dark.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-xhdpi/ic_back_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-xhdpi/ic_back_dark.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-xhdpi/ic_plus_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-xhdpi/ic_plus_dark.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-xhdpi/ic_share_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-xhdpi/ic_share_dark.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-xhdpi/internet_alert.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-xhdpi/internet_alert.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-xhdpi/iven_logo_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-xhdpi/iven_logo_dark.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-xxhdpi/ic_back_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-xxhdpi/ic_back_dark.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-xxhdpi/ic_plus_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-xxhdpi/ic_plus_dark.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-xxhdpi/ic_share_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-xxhdpi/ic_share_dark.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-xxxhdpi/ic_back_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-xxxhdpi/ic_back_dark.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-xxxhdpi/ic_plus_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-xxxhdpi/ic_plus_dark.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-xxxhdpi/ic_webview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-xxxhdpi/ic_webview.png
--------------------------------------------------------------------------------
/project/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/project/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-xhdpi/ic_webview_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-xhdpi/ic_webview_dark.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-xxhdpi/ic_webview_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-xxhdpi/ic_webview_dark.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-xxhdpi/internet_alert.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-xxhdpi/internet_alert.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-xxhdpi/iven_logo_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-xxhdpi/iven_logo_dark.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-xxxhdpi/ic_share_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-xxxhdpi/ic_share_dark.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-xxxhdpi/internet_alert.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-xxxhdpi/internet_alert.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-xxxhdpi/iven_logo_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-xxxhdpi/iven_logo_dark.png
--------------------------------------------------------------------------------
/project/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/project/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable-xxxhdpi/ic_webview_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/drawable-xxxhdpi/ic_webview_dark.png
--------------------------------------------------------------------------------
/project/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enricocid/iven-feed-reader/HEAD/project/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/project/app/src/main/res/values-xxhdpi/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 96.0dip
7 |
8 |
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable/ripple.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 |
--------------------------------------------------------------------------------
/project/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 64dp
7 | 24sp
8 |
9 |
--------------------------------------------------------------------------------
/project/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sat Jun 10 22:06:49 CEST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
7 |
--------------------------------------------------------------------------------
/project/app/src/main/res/layout/splash.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/project/app/src/main/res/layout/recycler_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/project/app/src/main/res/layout/recycler_view_dynamic.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/project/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | -keep class !android.support.v7.view.menu.*MenuBuilder*, android.support.v7.** { *; }
2 | -keep interface android.support.v7.* { *; }
3 | -keep public class * implements com.bumptech.glide.module.GlideModule
4 | -keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
5 | **[] $VALUES;
6 | public *;
7 | }
8 | -dontwarn
9 | -ignorewarnings
--------------------------------------------------------------------------------
/project/app/src/main/res/layout/splash_no_internet.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/project/app/src/main/res/values-sw600dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 24dp
7 | 80dp
8 | 12dp
9 | 22sp
10 |
11 |
--------------------------------------------------------------------------------
/project/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 | buildscript {
3 | System.properties['com.android.build.gradle.overrideVersionCheck'] = 'true'
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:2.3.3'
9 | }
10 | }
11 |
12 | allprojects {
13 | repositories {
14 | jcenter()
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/project/app/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/project/app/src/main/res/menu/wb_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable/background_splash_connection.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 |
8 | -
9 |
12 |
13 |
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable/progress_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | -
7 |
8 |
9 |
10 |
11 |
12 | -
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/project/app/src/main/res/layout/article_activity.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
10 |
11 |
12 |
16 |
17 |
--------------------------------------------------------------------------------
/project/app/src/main/res/layout/dynamic_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/project/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 16dp
7 | 16dp
8 | 16dp
9 | 72dp
10 | 4dp
11 | 18sp
12 | 16.0dip
13 | 48.0dip
14 | 8dp
15 | 4dp
16 |
17 |
--------------------------------------------------------------------------------
/project/app/src/main/res/layout/toolbar.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/project/app/src/main/java/com/iven/lfflfeedreader/utils/broadcastReceiver.java:
--------------------------------------------------------------------------------
1 | package com.iven.lfflfeedreader.utils;
2 |
3 |
4 | import android.content.BroadcastReceiver;
5 | import android.content.Context;
6 | import android.content.Intent;
7 |
8 |
9 | public class broadcastReceiver extends BroadcastReceiver {
10 |
11 | @Override
12 | public void onReceive(Context context, Intent intent) {
13 |
14 | Intent restartService = new Intent(context, notifyService.class);
15 |
16 | //send last date to restart notify service
17 | restartService.putExtra(notifyService.PARAM_IN_MSG, saveUtils.getLastDate(context));
18 |
19 | context.startService(restartService);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/project/app/src/main/res/drawable/background_splash.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 |
8 | -
9 |
12 |
13 | -
14 |
17 |
18 |
--------------------------------------------------------------------------------
/project/app/src/main/res/layout/checkbox_wb.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
10 |
11 |
17 |
18 |
--------------------------------------------------------------------------------
/project/app/src/main/java/com/iven/lfflfeedreader/utils/HomeUtils.java:
--------------------------------------------------------------------------------
1 | package com.iven.lfflfeedreader.utils;
2 |
3 | import android.app.Activity;
4 | import android.view.MenuItem;
5 |
6 | public class HomeUtils {
7 |
8 | public static void hideAddFeed(MenuItem menuItem) {
9 |
10 | //show addfeed menu item
11 | menuItem.setVisible(false);
12 | }
13 |
14 | public static void showAddFeed(MenuItem menuItem) {
15 |
16 | //show addfeed menu item
17 | menuItem.setVisible(true);
18 | }
19 |
20 | //method to set the feed string on feed click
21 | public static String setFeedString(Activity activity, String feed_string) {
22 |
23 | saveUtils.saveFeedUrl(activity, feed_string);
24 | return feed_string;
25 |
26 | }
27 |
28 | }
--------------------------------------------------------------------------------
/project/app/src/main/res/layout/articles_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
10 |
11 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/project/app/src/main/res/layout/article_page_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
10 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
24 |
25 |
--------------------------------------------------------------------------------
/project/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Settings specified in this file will override any Gradle settings
5 | # configured through the IDE.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
19 |
--------------------------------------------------------------------------------
/project/app/src/main/res/layout/home.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
10 |
11 |
12 |
13 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/project/app/src/main/res/layout/preference_activity.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
19 |
20 |
25 |
26 |
--------------------------------------------------------------------------------
/project/app/src/main/res/menu/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/project/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 25
5 | buildToolsVersion "25.0.3"
6 |
7 | lintOptions {
8 | checkReleaseBuilds true
9 | abortOnError false
10 | }
11 |
12 | defaultConfig {
13 | applicationId "com.iven.lfflfeedreader"
14 | minSdkVersion 21
15 | targetSdkVersion 25
16 | versionCode 66
17 | versionName "3.2"
18 | }
19 |
20 | buildTypes {
21 | release {
22 | zipAlignEnabled true
23 | proguardFiles getDefaultProguardFile('proguard-android.txt'),
24 | 'proguard-rules.pro'
25 | }
26 | debug {
27 | zipAlignEnabled true
28 | }
29 | }
30 | }
31 |
32 | repositories {
33 | maven { url "https://jitpack.io" }
34 | }
35 |
36 | dependencies {
37 | compile 'com.android.support:appcompat-v7:25.3.1'
38 | compile 'org.jsoup:jsoup:1.10.2'
39 | compile 'com.android.support:support-v4:25.3.1'
40 | compile 'com.github.bumptech.glide:glide:3.7.0'
41 | compile 'com.android.support:recyclerview-v7:25.3.1'
42 | compile 'com.android.support:cardview-v7:25.3.1'
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/project/app/src/main/java/com/iven/lfflfeedreader/utils/GlideUtils.java:
--------------------------------------------------------------------------------
1 | package com.iven.lfflfeedreader.utils;
2 |
3 | import android.app.Activity;
4 | import android.graphics.Bitmap;
5 | import android.support.v4.graphics.drawable.RoundedBitmapDrawable;
6 | import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory;
7 | import android.widget.ImageView;
8 |
9 | import com.bumptech.glide.Glide;
10 | import com.bumptech.glide.load.engine.DiskCacheStrategy;
11 | import com.bumptech.glide.request.target.BitmapImageViewTarget;
12 |
13 | public class GlideUtils {
14 |
15 | public static void loadImage(final Activity activity, final String who, final ImageView where) {
16 |
17 | activity.runOnUiThread(new Runnable() {
18 | @Override
19 | public void run() {
20 |
21 | Glide.with(activity).load(who)
22 |
23 | //load images as bitmaps to get fixed dimensions
24 | .asBitmap()
25 |
26 | //disable cache to avoid garbage collection that may produce crashes
27 | .diskCacheStrategy(DiskCacheStrategy.NONE)
28 |
29 | .into(where);
30 | }
31 | });
32 |
33 | }
34 | }
--------------------------------------------------------------------------------
/project/app/src/main/res/layout/dynamic_items.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
10 |
11 |
12 |
21 |
22 |
23 |
35 |
--------------------------------------------------------------------------------
/project/app/src/main/java/com/iven/lfflfeedreader/domparser/RSSFeed.java:
--------------------------------------------------------------------------------
1 | package com.iven.lfflfeedreader.domparser;
2 |
3 | import java.io.Serializable;
4 | import java.util.List;
5 | import java.util.Vector;
6 |
7 |
8 | //RSSFeed object which is written to by the DOMParser, containing
9 | //different RSSItem objects and the ability to add another item.
10 | //Also allows for finding the total number of items in the feed
11 | //if unknown already.
12 |
13 | //Original author Isaac Whitfield
14 |
15 | public class RSSFeed implements Serializable {
16 |
17 | //serializable ID
18 | private static final long serialVersionUID = 1L;
19 |
20 | //create a new item list
21 | private List _itemlist;
22 |
23 | //create a new item count
24 | private int _itemcount = 0;
25 |
26 | //initialize the item list
27 | RSSFeed() {
28 | _itemlist = new Vector<>(0);
29 | }
30 |
31 | void addItem(RSSItem item) {
32 |
33 | //add an item to the Vector
34 | _itemlist.add(item);
35 |
36 | //increment the item count
37 | _itemcount++;
38 | }
39 |
40 | public RSSItem getItem(int location) {
41 |
42 | //return the item at the chosen position
43 | return _itemlist.get(location);
44 | }
45 |
46 | public int getItemCount() {
47 |
48 | //return the number of items in the feed
49 | return _itemcount;
50 |
51 | }
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/project/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | #95000000
9 |
10 |
11 | @color/material_red_a400
12 | #ff898989
13 | #FF4081
14 |
15 |
16 | #FF1744
17 | #F50057
18 | #D500F9
19 | #651FFF
20 | #3D5AFE
21 | #2979FF
22 | #00B0FF
23 | #00E5FF
24 | #1DE9B6
25 | #00E676
26 | #76FF03
27 | #C6FF00
28 | #FFEA00
29 | #FFC400
30 | #FF9100
31 | #FF3D00
32 | #8D6E63
33 | #78909C
34 |
--------------------------------------------------------------------------------
/project/app/src/main/res/layout/action_buttons.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
12 |
13 |
14 |
22 |
23 |
24 |
32 |
33 |
34 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/project/app/src/main/java/com/iven/lfflfeedreader/utils/saveUtils.java:
--------------------------------------------------------------------------------
1 | package com.iven.lfflfeedreader.utils;
2 |
3 | import android.content.Context;
4 | import android.content.SharedPreferences;
5 |
6 | public class saveUtils {
7 |
8 | //save url
9 | static void saveFeedUrl(Context context, String feed) {
10 |
11 | SharedPreferences preferenceColor;
12 | preferenceColor = context.getSharedPreferences("feeds", Context.MODE_PRIVATE);
13 |
14 |
15 | preferenceColor.edit()
16 | .clear()
17 | .apply();
18 |
19 | preferenceColor.edit()
20 | .putString("selectedFeed", feed)
21 | .apply();
22 | }
23 |
24 | //retrieve url
25 | public static String getFeedUrl(final Context context) {
26 |
27 | SharedPreferences preferenceColor = context.getSharedPreferences("feeds", Context.MODE_PRIVATE);
28 |
29 | return preferenceColor.getString("selectedFeed", "http://feeds.feedburner.com/androidcentral");
30 | }
31 |
32 | //save last date
33 | public static void saveLastDate(Context context, String listCount) {
34 |
35 | SharedPreferences preferenceColor;
36 | preferenceColor = context.getSharedPreferences("date", Context.MODE_PRIVATE);
37 |
38 |
39 | preferenceColor.edit()
40 | .clear()
41 | .apply();
42 |
43 | preferenceColor.edit()
44 | .putString("lastDate", listCount)
45 | .apply();
46 | }
47 |
48 | //retrieve last date
49 | static String getLastDate(final Context context) {
50 |
51 | SharedPreferences preferenceColor = context.getSharedPreferences("date", Context.MODE_PRIVATE);
52 |
53 | return preferenceColor.getString("lastDate", "0");
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/project/app/src/main/java/com/iven/lfflfeedreader/domparser/RSSItem.java:
--------------------------------------------------------------------------------
1 | package com.iven.lfflfeedreader.domparser;
2 |
3 | import java.io.Serializable;
4 |
5 | public class RSSItem implements Serializable {
6 |
7 | //Simple struct class to hold the data for rss item
8 | //title, link, description, date, images.
9 |
10 | //Original author Isaac Whitfield
11 | //Extended by EnricoD
12 |
13 | //create the strings we need to store
14 | private static final long serialVersionUID = 1L;
15 |
16 | //note: do not set null values to avoid exceptions when 'if (item_x.isEmpty())' is used
17 | private String item_title = "no title";
18 | private String complete_desc = "no desc";
19 | private String item_desc = "no desc";
20 | private String item_date = "no date";
21 | private String item_image = "no image";
22 | private String rss_link = "no link";
23 | private String item_image2 = "no image";
24 |
25 | public String getTitle() {
26 | return item_title;
27 | }
28 |
29 | //set 'em all
30 | void setTitle(String title) {
31 | item_title = title;
32 | }
33 |
34 | public String getDescription() {
35 | return item_desc;
36 | }
37 |
38 | void setDescription(String description) {
39 | item_desc = description;
40 | }
41 |
42 | public String getCompleteDescription() {
43 | return complete_desc;
44 | }
45 |
46 | void setCompleteDescription(String complete_description) {
47 | complete_desc = complete_description;
48 | }
49 |
50 | public String getDate() {
51 | return item_date;
52 | }
53 |
54 | void setDate(String pubdate) {
55 | item_date = pubdate;
56 | }
57 |
58 | public String getLink() {
59 | return rss_link;
60 | }
61 |
62 | void setLink(String link) {
63 | rss_link = link;
64 | }
65 |
66 | public String getImage() {
67 | return item_image;
68 | }
69 |
70 | void setImage(String image) {
71 |
72 | item_image = image;
73 | }
74 |
75 | public String getImage2() {
76 | return item_image2;
77 | }
78 |
79 | void setImage2(String image2) {
80 |
81 | item_image2 = image2;
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/project/app/src/main/res/layout/add_feed_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
15 |
16 |
17 |
30 |
31 |
32 |
45 |
46 |
47 |
60 |
61 |
--------------------------------------------------------------------------------
/project/app/src/main/java/com/iven/lfflfeedreader/utils/ArticleUtils.java:
--------------------------------------------------------------------------------
1 | package com.iven.lfflfeedreader.utils;
2 |
3 | import android.app.Activity;
4 | import android.content.Intent;
5 | import android.net.Uri;
6 | import android.support.v7.app.AppCompatActivity;
7 |
8 | import com.iven.lfflfeedreader.R;
9 | import com.iven.lfflfeedreader.mainact.ArticlePage;
10 |
11 | public class ArticleUtils {
12 |
13 | //share method
14 | public static void share(Activity activity, String feedLink, String feedTitle) {
15 | Intent shareIntent = new Intent(Intent.ACTION_SEND);
16 | shareIntent.setType("text/plain");
17 | shareIntent.putExtra(Intent.EXTRA_TEXT, feedLink);
18 | activity.startActivity(Intent.createChooser(shareIntent, activity.getString(R.string.share) + " '" + feedTitle + "'"));
19 | }
20 |
21 | //read more method
22 | public static void continueReading(Activity activity, String feedLink) {
23 | Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(feedLink));
24 | CharSequence title2 = activity.getResources().getText(R.string.chooser_title);
25 | Intent chooser = Intent.createChooser(intent, title2);
26 | activity.startActivity(chooser);
27 | }
28 |
29 | //back navigation method
30 | public static void goBack(AppCompatActivity appCompatActivity) {
31 |
32 | //Cast getActivity() to AppCompatActivity to have access to support appcompat methods (onBackPressed();)
33 | appCompatActivity.onBackPressed();
34 | }
35 |
36 | //method to open the feed link using a webview
37 | public static void openFeedPage(Activity activity, String datfeed) {
38 | //we send the url and the title using intents to ArticlePage activity
39 | final Intent intent = new Intent(activity, ArticlePage.class);
40 |
41 | intent.putExtra("feedselected", datfeed);
42 |
43 | //and start a new ArticlePage activity with the selected feed
44 | activity.startActivity(intent);
45 | activity.overridePendingTransition(0, 0);
46 | }
47 |
48 | //method to open the image link
49 | public static void openImageLink(Activity activity, Intent intent) {
50 | CharSequence title2 = activity.getResources().getText(R.string.chooser_title);
51 | Intent chooser = Intent.createChooser(intent, title2);
52 | activity.startActivity(chooser);
53 | }
54 | }
--------------------------------------------------------------------------------
/project/app/src/main/res/layout/items.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
11 |
12 |
16 |
17 |
24 |
25 |
26 |
32 |
33 |
34 |
35 |
41 |
42 |
43 |
54 |
55 |
56 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/project/app/src/main/res/layout/article_fragment.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
10 |
11 |
19 |
20 |
21 |
28 |
29 |
30 |
35 |
36 |
37 |
42 |
43 |
44 |
50 |
51 |
52 |
59 |
60 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/project/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | -# Iven News Reader
2 | -Simple Android news reader
3 |
4 | **NOTE: The App is now DEPRECATED due to the lack of time (in everyday life I'm a Chemist)**
5 |
6 | 
7 |
8 |
9 | Iven news Reader is a light and modern Android News Reader that will allow You to read RSS feeds (the default blog is Android Central).
10 |
11 | The app supports 5.0+ devices
12 |
13 |
14 |
15 | Features:
16 |
17 | - Notifications;
18 | - Custom feeds;
19 | - Simple but modern UI;
20 | - Themes;
21 | - Immersive mode;
22 | - In-app webview;
23 | - Various customizations;
24 |
25 | 
26 |
27 |
28 |
29 | You can download the latest (3.2) signed APK from this repo here: https://github.com/enricocid/iven-feed-reader/raw/master-as/project/app/app-release.apk
30 |
31 |
32 |
33 |
34 | --------------------
35 | NOTES (Please Read):
36 |
37 | 1. NOTE: It is highly recommended to use the feedburner service to burn feeds, and enable "Convert format burner" service inside Optimize tab and select "Convert feed format to: RSS 2.0" to ensure the best compatibility.
38 |
39 | 2. We are not pro developers, but we hope You'll appreciate our work!
40 |
41 |
42 | This work is 100% Free and is released under gpl license.
43 |
44 |
45 |
46 | -------------
47 | **THANKS TO**
48 |
49 | **- Ivan D'Ortenzio**
50 | @ivn888
51 |
52 | Git page:
53 | https://github.com/ivn888
54 |
55 | **- Isaac Whitfield**
56 | @zackehh
57 |
58 | RSSfeed sample:
59 | https://github.com/zackehh/RSSDemo
60 |
61 | **- Lucas Urbas**
62 | @lurbas
63 |
64 | Making android toolbar responsive:
65 | https://medium.com/@lucasurbas/making-android-toolbar-responsive-2627d4e07129
66 |
67 | **- Chris Stewart**
68 | @cstew
69 |
70 | An example of a splash screen done the right way:
71 | https://github.com/cstew/Splash
72 |
73 | **- Ha Duy Trung**
74 | @hidroh
75 |
76 | Support multiple themes in your Android app:
77 | http://www.hidroh.com/2015/02/16/support-multiple-themes-android-app/
78 |
79 | **- Stack Overflow**
80 | http://stackoverflow.com/
81 |
82 | -------------------
83 | **USED LIBRARIES**
84 |
85 | **- Android Support Libraries**
86 | - Android Support v4;
87 | - Android Support Appcompatv7;
88 |
89 | **- Jsoup by Jonathan Hedley**
90 | @jhy
91 |
92 | Homepage:
93 | http://jsoup.org/
94 |
95 | **- Glide by Bump Technologies**
96 | @bumptech
97 |
98 | Git page:
99 | https://github.com/bumptech/glide
100 |
101 |
102 | -------------------
103 | This app follows the **KISS phylosophy** (https://en.wikipedia.org/wiki/KISS_principle), it means that the code/design will be kept simple & fast with no useless implementations/features.
104 | Anyway, if You have a feature request please send us an email with the following informations (use Issues for bug reports only please):
105 |
106 | - Description of the feature;
107 | - Why You think it would be useful;
108 |
--------------------------------------------------------------------------------
/project/app/src/main/java/com/iven/lfflfeedreader/mainact/SplashActivity.java:
--------------------------------------------------------------------------------
1 | package com.iven.lfflfeedreader.mainact;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.net.ConnectivityManager;
6 | import android.os.AsyncTask;
7 | import android.os.Bundle;
8 | import android.os.Handler;
9 | import android.support.v7.app.AppCompatActivity;
10 |
11 | import com.iven.lfflfeedreader.R;
12 | import com.iven.lfflfeedreader.domparser.DOMParser;
13 | import com.iven.lfflfeedreader.domparser.RSSFeed;
14 | import com.iven.lfflfeedreader.utils.Preferences;
15 | import com.iven.lfflfeedreader.utils.saveUtils;
16 |
17 | public class SplashActivity extends AppCompatActivity {
18 |
19 | //the default feed
20 | public static String default_feed_value;
21 |
22 | //the items
23 | RSSFeed lfflfeed;
24 |
25 | //Connectivity manager
26 | ConnectivityManager connectivityManager;
27 |
28 | @Override
29 | protected void onCreate(Bundle savedInstanceState) {
30 | super.onCreate(savedInstanceState);
31 |
32 | default_feed_value = saveUtils.getFeedUrl(SplashActivity.this);
33 |
34 | //set the navbar tint if the preference is enabled
35 | Preferences.applyNavTint(this);
36 |
37 | //set LightStatusBar
38 | Preferences.applyLightIcons(this);
39 |
40 | // Detect if there's a connection issue or not
41 | connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
42 |
43 | // If there's a connection problem
44 | if (connectivityManager.getActiveNetworkInfo() == null) {
45 |
46 | // Show alert splash
47 | setContentView(R.layout.splash_no_internet);
48 | new Handler().postDelayed(new Runnable() {
49 | public void run() {
50 |
51 | // and finish the splash activity
52 | SplashActivity.this.finish();
53 |
54 | }
55 | }, 2000);
56 |
57 | } else {
58 |
59 | //else :P, start the default splash screen and parse the RSSFeed and save the object
60 | setContentView(R.layout.splash);
61 | new AsyncLoadXMLFeed().execute();
62 |
63 | }
64 | }
65 |
66 | //using intents we send the lfflfeed (the parsed xml to populate the listview)
67 | // from the async task to listactivity
68 | private void startListActivity(RSSFeed lfflfeed) {
69 |
70 | Bundle bundle = new Bundle();
71 | bundle.putSerializable("feed", lfflfeed);
72 | Intent i = new Intent(SplashActivity.this, ListActivity.class);
73 | i.putExtras(bundle);
74 | startActivity(i);
75 | finish();
76 | }
77 |
78 | //parse the xml in an async task (background thread)
79 | private class AsyncLoadXMLFeed extends AsyncTask {
80 |
81 | @Override
82 | protected Void doInBackground(Void... params) {
83 |
84 | DOMParser Do = new DOMParser();
85 | lfflfeed = Do.parseXml(default_feed_value);
86 |
87 | return null;
88 |
89 | }
90 |
91 | @Override
92 | protected void onPostExecute(Void result) {
93 | super.onPostExecute(result);
94 | startListActivity(lfflfeed);
95 | }
96 |
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/project/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
17 |
18 |
21 |
22 |
25 |
28 |
31 |
34 |
37 |
38 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
53 |
54 |
58 |
59 |
63 |
64 |
69 |
70 |
74 |
75 |
78 |
79 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
--------------------------------------------------------------------------------
/project/app/src/main/java/com/iven/lfflfeedreader/mainact/ArticleActivity.java:
--------------------------------------------------------------------------------
1 | package com.iven.lfflfeedreader.mainact;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.content.Context;
5 | import android.os.Bundle;
6 | import android.support.v4.app.Fragment;
7 | import android.support.v4.app.FragmentManager;
8 | import android.support.v4.app.FragmentStatePagerAdapter;
9 | import android.support.v4.view.PagerAdapter;
10 | import android.support.v4.view.ViewPager;
11 | import android.support.v7.app.AppCompatActivity;
12 | import android.support.v7.view.ContextThemeWrapper;
13 |
14 | import com.iven.lfflfeedreader.R;
15 | import com.iven.lfflfeedreader.domparser.RSSFeed;
16 | import com.iven.lfflfeedreader.utils.Preferences;
17 |
18 | @SuppressLint("InlinedApi")
19 | public class ArticleActivity extends AppCompatActivity {
20 |
21 | //feed
22 | RSSFeed feed;
23 |
24 | //position
25 | int pos;
26 |
27 | //ContextThemeWrapper
28 | ContextThemeWrapper themewrapper;
29 |
30 | //context
31 | Context context;
32 |
33 | @Override
34 | protected void onCreate(Bundle savedInstanceState) {
35 |
36 | super.onCreate(savedInstanceState);
37 |
38 | //apply preferences
39 |
40 | //apply activity's theme if dark theme is enabled
41 | themewrapper = new ContextThemeWrapper(getBaseContext(), this.getTheme());
42 | Preferences.applyTheme(themewrapper, getBaseContext());
43 |
44 |
45 | //set the navbar tint if the preference is enabled
46 | Preferences.applyNavTint(this);
47 |
48 | //set LightStatusBar
49 | Preferences.applyLightIcons(this);
50 |
51 | //set the immersive mode (only for >= KitKat) if the preference is enabled
52 | Preferences.applyImmersiveMode(this);
53 |
54 | //set the view
55 | setContentView(R.layout.article_activity);
56 |
57 | //get the feed using intents
58 | feed = (RSSFeed) getIntent().getExtras().get("feed");
59 | pos = getIntent().getExtras().getInt("pos");
60 |
61 | //get the context
62 | context = getBaseContext();
63 |
64 | //initialize ViewPager and the adapter
65 | ViewPager pager;
66 | PagerAdapter mPagerAdapter;
67 |
68 | //set the viewpager that allows to swipe through articles
69 | mPagerAdapter = new MyPagerAdapter(getSupportFragmentManager());
70 | pager = (ViewPager) findViewById(R.id.pager);
71 | pager.setAdapter(mPagerAdapter);
72 | pager.setCurrentItem(pos);
73 | pager.setClipToPadding(false);
74 |
75 | }
76 |
77 | //(only for >= KitKat)
78 | //fix Immersive mode navigation becomes sticky after minimise-restore
79 | @Override
80 | public void onWindowFocusChanged(boolean hasFocus) {
81 | super.onWindowFocusChanged(hasFocus);
82 | if (hasFocus) {
83 | Preferences.applyImmersiveMode(this);
84 | }
85 | }
86 |
87 | //viewpager custom adapter, use FragmentStatePagerAdapter to handle a large number of items
88 | private class MyPagerAdapter extends FragmentStatePagerAdapter {
89 |
90 | MyPagerAdapter(FragmentManager fm) {
91 |
92 | super(fm);
93 | }
94 |
95 | @Override
96 | public Fragment getItem(int position) {
97 |
98 | ArticleFragment frag = new ArticleFragment();
99 | Bundle bundle = new Bundle();
100 | bundle.putSerializable("feed", feed);
101 | bundle.putInt("pos", position);
102 | frag.setArguments(bundle);
103 |
104 | return frag;
105 |
106 | }
107 |
108 | @Override
109 | public int getCount() {
110 | return feed.getItemCount();
111 | }
112 | }
113 | }
114 |
115 |
116 |
--------------------------------------------------------------------------------
/project/app/src/main/res/xml/info_pref.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
10 |
11 |
12 |
13 |
18 |
19 |
20 |
27 |
28 |
29 |
35 |
36 |
37 |
38 |
39 |
46 |
47 |
48 |
53 |
54 |
55 |
60 |
61 |
62 |
67 |
68 |
69 |
70 |
71 |
76 |
77 |
78 |
83 |
84 |
85 |
92 |
93 |
100 |
101 |
102 |
106 |
107 |
--------------------------------------------------------------------------------
/project/app/src/main/res/values/arrays.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | - @string/pref_text_verysmall
7 | - @string/pref_text_small
8 | - @string/pref_text_medium
9 | - @string/pref_text_large
10 | - @string/pref_text_verylarge
11 |
12 |
13 | - 0
14 | - 1
15 | - 2
16 | - 3
17 | - 4
18 |
19 |
20 |
21 | - @string/pref_text_small
22 | - @string/pref_text_medium
23 | - @string/pref_text_large
24 |
25 |
26 | - 5
27 | - 6
28 | - 7
29 |
30 |
31 |
32 |
33 | - @string/light_theme
34 | - @string/dark_theme
35 | - @string/red
36 | - @string/red_dark
37 | - @string/pink
38 | - @string/pink_dark
39 | - @string/purple
40 | - @string/purple_dark
41 | - @string/deepPurple
42 | - @string/deepPurple_dark
43 | - @string/indigo
44 | - @string/indigo_dark
45 | - @string/blue
46 | - @string/blue_dark
47 | - @string/lightBlue
48 | - @string/lightBlue_dark
49 | - @string/cyan
50 | - @string/cyan_dark
51 | - @string/teal
52 | - @string/teal_dark
53 | - @string/green
54 | - @string/green_dark
55 | - @string/lightGreen
56 | - @string/lightGreen_dark
57 | - @string/lime
58 | - @string/lime_dark
59 | - @string/yellow
60 | - @string/yellow_dark
61 | - @string/amber
62 | - @string/amber_dark
63 | - @string/orange
64 | - @string/orange_dark
65 | - @string/deepOrange
66 | - @string/deepOrange_dark
67 | - @string/brown
68 | - @string/brown_dark
69 | - @string/blueGrey
70 | - @string/blueGrey_dark
71 |
72 |
73 | - 8
74 | - 9
75 | - 10
76 |
77 | - 11
78 | - 12
79 | - 13
80 | - 14
81 | - 15
82 | - 16
83 | - 17
84 | - 18
85 | - 19
86 | - 20
87 | - 21
88 | - 22
89 | - 23
90 | - 24
91 | - 25
92 | - 26
93 | - 27
94 | - 28
95 | - 29
96 | - 30
97 | - 31
98 | - 32
99 | - 33
100 | - 34
101 | - 35
102 | - 36
103 | - 37
104 | - 38
105 | - 39
106 | - 40
107 | - 41
108 | - 42
109 | - 43
110 | - 44
111 | - 45
112 |
113 |
114 |
115 |
116 | - @string/pref_time_0
117 | - @string/pref_time_default
118 | - @string/pref_time_1
119 | - @string/pref_time_2
120 | - @string/pref_time_3
121 | - @string/pref_time_4
122 | - @string/pref_time_5
123 | - @string/pref_time_6
124 |
125 |
126 |
127 | - 47
128 | - 48
129 | - 49
130 | - 50
131 | - 51
132 | - 52
133 | - 53
134 | - 54
135 |
136 |
--------------------------------------------------------------------------------
/project/app/src/main/java/com/iven/lfflfeedreader/mainact/FeedsAdapter.java:
--------------------------------------------------------------------------------
1 | package com.iven.lfflfeedreader.mainact;
2 |
3 | import android.app.Activity;
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 | import android.support.v7.widget.RecyclerView;
7 | import android.util.TypedValue;
8 | import android.view.LayoutInflater;
9 | import android.view.View;
10 | import android.view.ViewGroup;
11 | import android.widget.ImageView;
12 | import android.widget.LinearLayout;
13 | import android.widget.TextView;
14 |
15 | import com.iven.lfflfeedreader.R;
16 | import com.iven.lfflfeedreader.domparser.RSSFeed;
17 | import com.iven.lfflfeedreader.domparser.RSSItem;
18 | import com.iven.lfflfeedreader.utils.GlideUtils;
19 | import com.iven.lfflfeedreader.utils.Preferences;
20 |
21 | class FeedsAdapter extends RecyclerView.Adapter {
22 |
23 | private Activity activity;
24 |
25 | private RSSFeed fFeed;
26 |
27 | FeedsAdapter(Activity activity, RSSFeed fFeed) {
28 |
29 | this.activity = activity;
30 |
31 | this.fFeed = fFeed;
32 |
33 | }
34 |
35 | @Override
36 | public SimpleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
37 |
38 | View itemView = LayoutInflater.from(parent.getContext())
39 | .inflate(R.layout.items, parent, false);
40 | return new SimpleViewHolder(activity, itemView, fFeed);
41 | }
42 |
43 | @Override
44 | public void onBindViewHolder(SimpleViewHolder holder, int position) {
45 |
46 | //get the chosen items text size from preferences
47 |
48 | RSSItem feedItem = fFeed.getItem(position);
49 |
50 | String imageLink = feedItem.getImage();
51 | String imageLink2 = feedItem.getImage2();
52 | String feedTitle = feedItem.getTitle();
53 | String feedDate = feedItem.getDate();
54 | int size = Preferences.resolveTextSizeListResId(activity);
55 |
56 | //dynamically set title and subtitle according to the feed data
57 |
58 | //title
59 | holder.itemTitle.setText(feedTitle);
60 |
61 | //subtitle = publication date
62 | holder.pubDate.setText(feedDate);
63 | holder.pubDate.setTextSize(TypedValue.COMPLEX_UNIT_SP, size - 2);
64 |
65 | //set the list items text size from preferences in SP unit
66 | holder.itemTitle.setTextSize(TypedValue.COMPLEX_UNIT_SP, size);
67 |
68 |
69 | //if the preference is enabled remove the linear layout containing the ImageView
70 | if (Preferences.imagesRemoved(activity)) {
71 |
72 | holder.linearLayout.removeAllViewsInLayout();
73 |
74 | }
75 |
76 | //else, load the image
77 | //if getImage() method fails (i.e when img is in content:encoded) load image2
78 | else if (imageLink.isEmpty()) {
79 |
80 | GlideUtils.loadImage(activity, imageLink2, holder.lfflImage);
81 |
82 | //else use image
83 | } else {
84 |
85 | GlideUtils.loadImage(activity, imageLink, holder.lfflImage);
86 | }
87 |
88 | }
89 |
90 | @Override
91 | public int getItemCount() {
92 |
93 | return fFeed.getItemCount();
94 | }
95 |
96 | //simple view holder implementing on click method to open feed page
97 | static class SimpleViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
98 |
99 |
100 | TextView itemTitle;
101 | TextView pubDate;
102 | ImageView lfflImage;
103 | LinearLayout linearLayout;
104 | private Activity activity;
105 | private RSSFeed fFeed;
106 |
107 |
108 | SimpleViewHolder(Activity activity, View itemView, RSSFeed fFeed) {
109 | super(itemView);
110 |
111 | itemView.setOnClickListener(this);
112 |
113 | this.fFeed = fFeed;
114 |
115 | this.activity = activity;
116 |
117 | itemTitle = (TextView) itemView.findViewById(R.id.title);
118 | pubDate = (TextView) itemView.findViewById(R.id.date);
119 | lfflImage = (ImageView) itemView.findViewById(R.id.thumb);
120 | linearLayout = (LinearLayout) itemView.findViewById(R.id.layout);
121 |
122 | }
123 |
124 | @Override
125 | public void onClick(View v) {
126 |
127 | //open feed page
128 | Bundle bundle = new Bundle();
129 |
130 | //set feed info to article activity
131 | bundle.putSerializable("feed", fFeed);
132 | Intent intent = new Intent(activity,
133 | ArticleActivity.class);
134 | intent.putExtras(bundle);
135 | intent.putExtra("pos", getAdapterPosition());
136 |
137 | //start the article activity to read the story
138 | activity.startActivity(intent);
139 |
140 | }
141 | }
142 | }
--------------------------------------------------------------------------------
/project/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/project/app/src/main/res/values-v23/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
16 |
17 |
23 |
24 |
30 |
31 |
37 |
38 |
44 |
45 |
51 |
52 |
58 |
59 |
65 |
66 |
72 |
73 |
79 |
80 |
86 |
87 |
93 |
94 |
100 |
101 |
107 |
108 |
114 |
115 |
121 |
--------------------------------------------------------------------------------
/project/app/src/main/res/values-it/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Installa un browser
7 | Condividi
8 | Scegli il browser …
9 | Opzioni tema
10 | Altre opzioni
11 | Tema app
12 | Necessita riavvio della app
13 | Opzioni
14 | Usa webview
15 | Leggi di più usando la in-app webview
16 | Abilita javascript
17 | Abilita tinta navbar
18 | Verrà abilitata la tinta della barra di navigazione
19 | Pulisci cache app
20 | Questa opzione pulirà la cache dell\'app e resetterà le opzioni
21 | Aggiusta font articoli
22 | Aggiusta font lista
23 | Scegli la dimensione di default del testo degli articoli
24 | Scegli la dimensione di default del testo degli oggetti della home
25 | Più piccolo
26 | Piccolo
27 | Intermedio
28 | Grande
29 | Molto grande
30 | Modalità immersive
31 | Abilita la modalità immersive negli articoli
32 | Disabilita immagini
33 | Disabilita la visualizzazione delle immagini degli articoli
34 | Icone status bar dark
35 | Abilita le icone dark nella status bar
36 | Eliminazione feed
37 | Vuoi eliminare
38 | Aggiunta feed
39 | Url qui
40 | Nome qui
41 | Aggiungi feed
42 | Inserisci il tuo feed nel formato RSS
43 | Opzione non disponibile su smartphone pre-Marshmallow
44 | Connettiti ad internet per favore
45 | Per favore attendi …
46 | Chiaro
47 | Scuro
48 | Più scuro
49 | Info developer
50 | Crediti
51 | Librerie
52 | Info applicazione
53 | Versione
54 |
55 | Notifiche
56 | Scegli intervallo controllo
57 | Scegli l\'intervallo di tempo che intercorre tra un controllo e il successivo
58 | 15 secondi
59 | 30 secondi
60 | 1 minuto
61 | 5 minuti
62 | 10 minuti
63 | 20 minuti
64 | 30 minuti
65 | 1 ora
66 | Abilita notifiche
67 | Nuovi articoli postati :D
68 | Ricevi una notifica quando vengono postati nuovi articoli
69 | Suono di notifica
70 | Cambia il suono della notifica
71 |
72 | Rosso
73 | Rosa
74 | Viola
75 | Viola scuro
76 | Indaco
77 | Blu
78 | Blu chiaro
79 | Ciano
80 | Alzavola
81 | Verde
82 | Verde chiaro
83 | Lime
84 | Giallo
85 | Ambra
86 | Arancio
87 | Arancio scuro
88 | Marrone
89 | Grigio blu
90 |
91 | Rosso notte
92 | Rosa notte
93 | Viola notte
94 | Viola scuro notte
95 | Indaco notte
96 | Blu notte
97 | Blu chiaro notte
98 | Ciano notte
99 | Alzavola notte
100 | Verde notte
101 | Verde chiaro notte
102 | Lime notte
103 | Giallo notte
104 | Ambra notte
105 | Arancio notte
106 | Arancio scuro notte
107 | Marrone notte
108 | Grigio blu notte
109 |
110 |
--------------------------------------------------------------------------------
/project/app/src/main/java/com/iven/lfflfeedreader/utils/notifyService.java:
--------------------------------------------------------------------------------
1 | package com.iven.lfflfeedreader.utils;
2 |
3 |
4 | import android.app.Notification;
5 | import android.app.NotificationManager;
6 | import android.app.PendingIntent;
7 | import android.app.Service;
8 | import android.content.Intent;
9 | import android.content.SharedPreferences;
10 | import android.media.RingtoneManager;
11 | import android.net.Uri;
12 | import android.os.Handler;
13 | import android.os.IBinder;
14 | import android.os.Looper;
15 | import android.preference.PreferenceManager;
16 | import android.support.v4.app.NotificationCompat;
17 | import android.support.v4.content.ContextCompat;
18 |
19 | import com.iven.lfflfeedreader.R;
20 | import com.iven.lfflfeedreader.domparser.DOMParser;
21 | import com.iven.lfflfeedreader.domparser.RSSFeed;
22 | import com.iven.lfflfeedreader.domparser.RSSItem;
23 | import com.iven.lfflfeedreader.mainact.SplashActivity;
24 |
25 |
26 | public class notifyService extends Service {
27 |
28 | public static final String PARAM_IN_MSG = "imsg";
29 |
30 | //all items
31 | int lastDate;
32 | String firstItemDate;
33 | Handler handler;
34 | Runnable runnableCode;
35 | DOMParser tmpDOMParser;
36 | RSSFeed fFeed;
37 | RSSItem updatedFeedItem;
38 | String updatedDate;
39 | String updatedDateFormat;
40 | int updatedLastDate;
41 | Intent broadcastIntent;
42 | PendingIntent pi;
43 | Uri notificationSound;
44 | Notification serviceNotification;
45 | Notification notification;
46 | NotificationManager notificationManager;
47 | SharedPreferences getAlarms;
48 | String alarm;
49 | Uri defaultRingtoneUri;
50 |
51 | @Override
52 | public IBinder onBind(Intent arg0) {
53 |
54 | return null;
55 | }
56 |
57 | @Override
58 | public int onStartCommand(Intent intent, int flags, int startId) {
59 |
60 |
61 | //make a foreground notification to avoid android kills the service
62 | serviceNotification = new NotificationCompat.Builder(this)
63 | .setOngoing(false)
64 |
65 | .build();
66 | startForeground(101, serviceNotification);
67 |
68 | //get selected notification sound
69 | getAlarms = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
70 |
71 | defaultRingtoneUri = RingtoneManager.getActualDefaultRingtoneUri(getBaseContext(), RingtoneManager.TYPE_NOTIFICATION);
72 |
73 | alarm = getAlarms.getString("audio", String.valueOf(defaultRingtoneUri));
74 |
75 | //get last item date from ListActivity
76 | firstItemDate = intent.getStringExtra(PARAM_IN_MSG);
77 | saveUtils.saveLastDate(getBaseContext(), firstItemDate);
78 |
79 | lastDate = Integer.valueOf(firstItemDate);
80 |
81 | //get selected notification
82 | notificationSound = Uri.parse(alarm);
83 |
84 | return START_STICKY;
85 | }
86 |
87 | @Override
88 | public void onTaskRemoved(Intent rootIntent) {
89 |
90 | if (Preferences.notificationsEnabled(getBaseContext())) {
91 |
92 | //the service will be restarted if killed
93 | broadcastIntent = new Intent("dontKillMe");
94 | sendBroadcast(broadcastIntent);
95 | }
96 | }
97 |
98 | @Override
99 | public void onCreate() {
100 |
101 | super.onCreate();
102 |
103 | Thread thread = new Thread(new Runnable() {
104 |
105 | public void run() {
106 |
107 | Looper.prepare();
108 |
109 | handler = new Handler();
110 |
111 | // Define the code block to be executed
112 | runnableCode = new Runnable() {
113 | @Override
114 | public void run() {
115 |
116 | //parse xml to check if there are new articles
117 | tmpDOMParser = new DOMParser();
118 | fFeed = tmpDOMParser.parseXml(saveUtils.getFeedUrl(getBaseContext()));
119 |
120 | //get the date of the last article posted
121 | updatedFeedItem = fFeed.getItem(0);
122 | updatedDate = updatedFeedItem.getDate();
123 |
124 | updatedDateFormat = updatedDate.substring(updatedDate.length() - 5).replace(":", "");
125 | updatedLastDate = Integer.valueOf(updatedDateFormat);
126 |
127 | if (updatedLastDate != lastDate) {
128 |
129 | pi = PendingIntent.getActivity(getBaseContext(), 0, new Intent(getBaseContext(), SplashActivity.class), 0);
130 |
131 | //build notification
132 | notification = new NotificationCompat.Builder(getBaseContext())
133 | .setSmallIcon(android.R.drawable.stat_notify_more)
134 | .setContentText(getString(R.string.news))
135 | .setContentIntent(pi)
136 | .setAutoCancel(true)
137 | .setColor(ContextCompat.getColor(getBaseContext(), R.color.notification_color))
138 | .setSound(notificationSound)
139 | .build();
140 |
141 | notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
142 | notificationManager.notify(0, notification);
143 |
144 | saveUtils.saveLastDate(getBaseContext(), updatedDate);
145 | }
146 |
147 | // Repeat this the same runnable code block again another tot seconds (defined by the user)
148 | handler.postDelayed(runnableCode, Preferences.resolveTime(getBaseContext()) * 1000);
149 | }
150 | };
151 |
152 | // Start the initial runnable task by posting through the handler
153 | handler.post(runnableCode);
154 |
155 | Looper.loop();
156 | }
157 | });
158 |
159 | thread.start();
160 | }
161 |
162 | @Override
163 | public void onDestroy() {
164 | handler.removeCallbacksAndMessages(null);
165 |
166 | }
167 | }
168 |
--------------------------------------------------------------------------------
/project/app/src/main/java/com/iven/lfflfeedreader/infoact/InfoActivity.java:
--------------------------------------------------------------------------------
1 | package com.iven.lfflfeedreader.infoact;
2 |
3 | import android.content.Intent;
4 | import android.content.SharedPreferences;
5 | import android.os.Build;
6 | import android.os.Bundle;
7 | import android.preference.ListPreference;
8 | import android.preference.Preference;
9 | import android.preference.PreferenceFragment;
10 | import android.preference.PreferenceScreen;
11 | import android.preference.RingtonePreference;
12 | import android.preference.SwitchPreference;
13 | import android.support.v4.content.IntentCompat;
14 | import android.support.v7.app.AppCompatActivity;
15 | import android.support.v7.view.ContextThemeWrapper;
16 | import android.support.v7.widget.Toolbar;
17 | import android.view.View;
18 |
19 | import com.iven.lfflfeedreader.R;
20 | import com.iven.lfflfeedreader.mainact.SplashActivity;
21 | import com.iven.lfflfeedreader.utils.Preferences;
22 |
23 | import java.io.File;
24 |
25 | public class InfoActivity extends AppCompatActivity {
26 |
27 | //ContextThemeWrapper
28 | ContextThemeWrapper themewrapper;
29 |
30 | @Override
31 | public void onCreate(Bundle savedInstanceState) {
32 |
33 | super.onCreate(savedInstanceState);
34 |
35 | //apply preferences
36 |
37 | //apply activity's theme if dark theme is enabled
38 | themewrapper = new ContextThemeWrapper(getBaseContext(), this.getTheme());
39 | Preferences.applyTheme(themewrapper, getBaseContext());
40 |
41 | //set the navbar tint if the preference is enabled
42 | Preferences.applyNavTint(this);
43 |
44 | //set LightStatusBar
45 | Preferences.applyLightIcons(this);
46 |
47 | //set the view
48 | setContentView(R.layout.preference_activity);
49 |
50 | //set the toolbar
51 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
52 | setSupportActionBar(toolbar);
53 |
54 | //provide back navigation
55 | if (getSupportActionBar() != null) {
56 | getSupportActionBar().setDisplayHomeAsUpEnabled(true);
57 | }
58 |
59 | toolbar.setNavigationOnClickListener(new View.OnClickListener() {
60 | @Override
61 | public void onClick(View v) {
62 | onBackPressed();
63 | overridePendingTransition(0, 0);
64 | }
65 | });
66 |
67 |
68 | if (getFragmentManager().findFragmentById(R.id.content_frame) == null) {
69 | getFragmentManager().beginTransaction().replace(R.id.content_frame, new SettingsFragment()).commit();
70 | }
71 | }
72 |
73 | public static class SettingsFragment extends PreferenceFragment {
74 |
75 | SwitchPreference LightStatusBar;
76 | Preference preferenceCache;
77 | ListPreference timePreference;
78 | RingtonePreference soundPreference;
79 |
80 | private SharedPreferences.OnSharedPreferenceChangeListener mListenerOptions;
81 |
82 | public static boolean deleteDir(File dir) {
83 |
84 | final String[] children = dir.list();
85 | boolean success;
86 |
87 | if (dir.isDirectory()) {
88 |
89 | for (String s : children) {
90 | success = deleteDir(new File(dir, s));
91 |
92 | if (!success) {
93 | return false;
94 | }
95 | }
96 | }
97 |
98 | return dir.delete();
99 | }
100 |
101 | @Override
102 | public void onCreate(Bundle savedInstanceState) {
103 | super.onCreate(savedInstanceState);
104 |
105 | addPreferencesFromResource(R.xml.info_pref);
106 |
107 | //get preference screen
108 | final PreferenceScreen screen = getPreferenceScreen();
109 |
110 | //get LightStatusBar preference
111 | LightStatusBar = (SwitchPreference) findPreference("lightcolored");
112 |
113 | //hide this option on pre-marshmallow devices
114 | if (Build.VERSION.SDK_INT < 23) {
115 | LightStatusBar.setEnabled(false);
116 | LightStatusBar.setSummary(getString(R.string.premarshmallow));
117 |
118 | //show this option on >= 23 devices
119 | } else {
120 | LightStatusBar.setEnabled(true);
121 | }
122 |
123 | //get the clear cache preference
124 | preferenceCache = findPreference("clearcache");
125 |
126 | preferenceCache.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
127 | public boolean onPreferenceClick(Preference preference) {
128 |
129 | clearApplicationData();
130 | return false;
131 | }
132 | });
133 |
134 | //get sound and time preference
135 | timePreference = (ListPreference) findPreference("pref_time");
136 | soundPreference = (RingtonePreference) findPreference("audio");
137 |
138 | if (Preferences.notificationsEnabled(getActivity())) {
139 |
140 | screen.addPreference(timePreference);
141 | screen.addPreference(soundPreference);
142 |
143 | } else {
144 | screen.removePreference(timePreference);
145 | screen.removePreference(soundPreference);
146 |
147 | }
148 |
149 | //initialize shared preference change listener
150 | //some preferences when enabled requires an app reboot
151 | mListenerOptions = new SharedPreferences.OnSharedPreferenceChangeListener() {
152 | @Override
153 | public void onSharedPreferenceChanged(SharedPreferences preftheme, String key) {
154 |
155 | //on theme selection restart the app
156 | if (key.equals(getResources().getString(R.string.pref_theme)) | key.equals("lightcolored") | key.equals("images") | key.equals("Navibar") | (key.equals("notifications"))) {
157 | restartApp();
158 | }
159 | }
160 | };
161 | }
162 |
163 | //register preferences changes
164 | @Override
165 | public void onResume() {
166 | super.onResume();
167 |
168 | getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(mListenerOptions);
169 | }
170 |
171 | //unregister preferences changes
172 | @Override
173 | public void onPause() {
174 | getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(mListenerOptions);
175 | super.onPause();
176 | }
177 |
178 | //this is the method to delete the app's cache
179 | public void clearApplicationData() {
180 | File cache = getActivity().getCacheDir();
181 | File appDir = new File(cache.getParent());
182 | if (appDir.exists()) {
183 | String[] children = appDir.list();
184 | for (String s : children) {
185 | if (!s.equals("lib")) {
186 | deleteDir(new File(appDir, s));
187 | }
188 | }
189 | }
190 | }
191 |
192 | //method to restart the app and apply the changes
193 | private void restartApp() {
194 | Intent newIntent = new Intent(getActivity(), SplashActivity.class);
195 | newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
196 | startActivity(newIntent);
197 | getActivity().overridePendingTransition(0, 0);
198 | getActivity().finish();
199 | }
200 | }
201 | }
--------------------------------------------------------------------------------
/project/app/src/main/java/com/iven/lfflfeedreader/domparser/DOMParser.java:
--------------------------------------------------------------------------------
1 | package com.iven.lfflfeedreader.domparser;
2 |
3 | import android.content.res.Resources;
4 | import android.os.Build;
5 | import android.webkit.MimeTypeMap;
6 |
7 | import org.jsoup.Jsoup;
8 | import org.jsoup.select.Elements;
9 | import org.w3c.dom.Document;
10 | import org.w3c.dom.Node;
11 | import org.w3c.dom.NodeList;
12 | import org.xml.sax.InputSource;
13 |
14 | import java.net.MalformedURLException;
15 | import java.net.URL;
16 | import java.text.SimpleDateFormat;
17 | import java.util.Date;
18 | import java.util.Locale;
19 | import java.util.TimeZone;
20 |
21 | import javax.xml.parsers.DocumentBuilder;
22 | import javax.xml.parsers.DocumentBuilderFactory;
23 |
24 | //Parses an RSS feed and adds the information to a new RSSFeed object.
25 |
26 | //Original author Isaac Whitfield
27 | //Extended by EnricoD
28 |
29 | public class DOMParser {
30 |
31 | //create a new RSS feed
32 |
33 | private RSSFeed _feed = new RSSFeed();
34 |
35 | @SuppressWarnings("deprecation")
36 | public RSSFeed parseXml(String xml) {
37 |
38 | //getting XML content
39 | URL url = null;
40 | try {
41 |
42 | //find the new URL from the given URL
43 | url = new URL(xml);
44 | } catch (MalformedURLException e1) {
45 |
46 | //throw an exception
47 | e1.printStackTrace();
48 | }
49 |
50 | //get the DOM element of the XML file. Below function will parse the XML content and will give you DOM element.
51 | try {
52 |
53 | //create a new DocumentBuilder
54 | DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
55 | DocumentBuilder db = dbf.newDocumentBuilder();
56 |
57 | //parse the XML
58 | Document doc = db.parse(new InputSource(url.openStream()));
59 |
60 | //normalize the data
61 | doc.getDocumentElement().normalize();
62 |
63 | //get each xml child element value by passing element node name
64 |
65 | //get all - tags.
66 | NodeList nl = doc.getElementsByTagName("item");
67 |
68 | //get size of the list
69 | int length = nl.getLength();
70 |
71 | //looping through all item nodes
72 | for (int i = 0; i < length; i++) {
73 |
74 | Node currentNode = nl.item(i);
75 | RSSItem _item = new RSSItem();
76 |
77 | //create a new node of the first item
78 | NodeList nchild = currentNode.getChildNodes();
79 |
80 | //get size of the child list
81 | int clength = nchild.getLength();
82 |
83 | //for all the children of a node
84 | for (int j = 0; j < clength; j++) {
85 |
86 | //get the name of the child
87 | Node thisNode = nchild.item(j);
88 | String theString = null;
89 |
90 | //if there is at least one child element
91 | if (thisNode != null && thisNode.getFirstChild() != null) {
92 |
93 | //set the string to be the value of the node
94 | theString = nchild.item(j).getFirstChild().getNodeValue();
95 | }
96 |
97 | //if the string isn't null
98 | if (theString != null) {
99 |
100 | //set the appropriate value
101 | String nodeName = thisNode.getNodeName();
102 | if ("title".equals(nodeName)) {
103 | _item.setTitle(theString);
104 |
105 | }
106 |
107 | //feed link
108 | else if ("link".equals(nodeName)) {
109 | _item.setLink(theString);
110 | }
111 |
112 | //complete description from content:encoded
113 | else if ("content:encoded".equals(nodeName)) {
114 |
115 | org.jsoup.nodes.Document docHtml = Jsoup
116 | .parse(theString);
117 |
118 | //select images by tag
119 | Elements imgEle = docHtml.select("img");
120 |
121 | //extract the images src from content:encoded
122 | String src = imgEle.attr("src");
123 |
124 | //setImage2() src
125 | _item.setImage2(processImageUrl(src));
126 |
127 | //set complete description
128 | _item.setCompleteDescription(theString);
129 |
130 | //description method is used when complete description returns 'no desc'
131 | } else if ("description".equals(nodeName)) {
132 | _item.setDescription(theString);
133 |
134 | org.jsoup.nodes.Document docHtml = Jsoup
135 | .parse(theString);
136 |
137 | //select images by tag
138 | Elements imgEle = docHtml.select("img");
139 |
140 | //get src attribute
141 | String src = imgEle.attr("src");
142 |
143 | //setImage() src
144 | _item.setImage(processImageUrl(src));
145 |
146 | }
147 |
148 | //publication date
149 | else if ("pubDate".equals(nodeName)) {
150 |
151 | //replace some text inside date
152 | String formatedDate = theString.replace(" +0000", "");
153 |
154 | Locale loc;
155 |
156 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
157 | loc = Resources.getSystem().getConfiguration().getLocales().get(0);
158 | } else {
159 | loc = Resources.getSystem().getConfiguration().locale;
160 | }
161 |
162 | //change date format
163 | SimpleDateFormat curFormater = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss", java.util.Locale.US);
164 | Date dateObj = curFormater.parse(formatedDate);
165 | SimpleDateFormat postFormater = new SimpleDateFormat("EEE, dd.MM.yyyy - HH:mm", loc);
166 |
167 | //get the timezone settings from the phone
168 | String timezoneID = TimeZone.getDefault().getID();
169 |
170 | //set it dynamically
171 | postFormater.setTimeZone(TimeZone.getTimeZone(timezoneID));
172 | String newDateStr = postFormater.format(dateObj);
173 |
174 | _item.setDate(newDateStr);
175 | }
176 | }
177 | }
178 |
179 | //add the new item to the RSS feed
180 | _feed.addItem(_item);
181 | }
182 |
183 | } catch (Exception e) {
184 | e.printStackTrace();
185 | }
186 |
187 | //return the feed
188 | return _feed;
189 | }
190 |
191 | //process images urls to get a "pure" image link, i.e something.extension (extension= .jpg, .png, .gif etc)
192 | private String processImageUrl(String imagesUrl) {
193 |
194 | //get image extension
195 | String extension = MimeTypeMap.getFileExtensionFromUrl(imagesUrl);
196 |
197 | //return pure url
198 | return imagesUrl.substring(0, imagesUrl.indexOf(extension)) + extension;
199 | }
200 | }
201 |
--------------------------------------------------------------------------------
/project/app/src/main/res/layout/activity_about.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 |
19 |
20 |
29 |
30 |
34 |
35 |
39 |
40 |
45 |
46 |
51 |
52 |
57 |
58 |
63 |
64 |
69 |
70 |
75 |
76 |
80 |
81 |
86 |
87 |
92 |
93 |
98 |
99 |
104 |
105 |
109 |
110 |
115 |
116 |
121 |
122 |
127 |
128 |
133 |
134 |
139 |
140 |
145 |
146 |
151 |
152 |
157 |
158 |
163 |
164 |
169 |
170 |
175 |
176 |
181 |
182 |
186 |
187 |
192 |
193 |
198 |
199 |
200 |
201 |
202 |
203 |
--------------------------------------------------------------------------------
/project/app/src/main/java/com/iven/lfflfeedreader/infoact/AboutActivity.java:
--------------------------------------------------------------------------------
1 | package com.iven.lfflfeedreader.infoact;
2 |
3 | import android.graphics.Paint;
4 | import android.os.Build;
5 | import android.os.Bundle;
6 | import android.support.v7.app.AppCompatActivity;
7 | import android.support.v7.view.ContextThemeWrapper;
8 | import android.support.v7.widget.Toolbar;
9 | import android.text.Html;
10 | import android.text.Spanned;
11 | import android.text.method.LinkMovementMethod;
12 | import android.view.MenuItem;
13 | import android.widget.TextView;
14 |
15 | import com.iven.lfflfeedreader.BuildConfig;
16 | import com.iven.lfflfeedreader.R;
17 | import com.iven.lfflfeedreader.utils.Preferences;
18 |
19 | public class AboutActivity extends AppCompatActivity {
20 |
21 | //ContextThemeWrapper
22 | ContextThemeWrapper themeWrapper;
23 |
24 | //get all the TextViews
25 | TextView dev, enricoGit, enricoGplus, credits, ivanGit, ivanGplus, stack, lucas, support4, appCompat, recyclerView, cardView, jsoup, glide, libraries, appInfo, build, sources;
26 |
27 | //Get all the Strings
28 | String enricoGitPage, enricoGplusPage, ivanGitPage, ivanGplusPage, stackPage, lucasPage, support4page, appCompatPage, recyclerViewPage, cardViewPage, jsoupPage, glidePage, version, appGit;
29 |
30 | //method to set clickable links
31 | @SuppressWarnings("deprecation")
32 | static Spanned setTextLinks(String htmlText, TextView... textViews) {
33 |
34 | for (TextView links : textViews) {
35 | links.setMovementMethod(LinkMovementMethod.getInstance());
36 | }
37 | if (Build.VERSION.SDK_INT >= 24) {
38 | return Html.fromHtml(htmlText, Html.FROM_HTML_MODE_LEGACY);
39 |
40 | } else {
41 | return Html.fromHtml(htmlText);
42 |
43 | }
44 | }
45 |
46 | @Override
47 | protected void onCreate(Bundle savedInstanceState) {
48 | super.onCreate(savedInstanceState);
49 |
50 | //apply activity's theme if dark theme is enabled
51 | themeWrapper = new ContextThemeWrapper(getBaseContext(), this.getTheme());
52 |
53 | Preferences.applyTheme(themeWrapper, getBaseContext());
54 |
55 | //apply light status bar icons if enabled
56 | Preferences.applyLightIcons(this);
57 |
58 | Preferences.applyNavTint(this);
59 |
60 | setContentView(R.layout.activity_about);
61 |
62 | //set the toolbar
63 | final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar2);
64 | setSupportActionBar(toolbar);
65 |
66 | //provide back navigation
67 | if (getSupportActionBar() != null) {
68 | getSupportActionBar().setDisplayHomeAsUpEnabled(true);
69 | }
70 |
71 | String colon = ": ";
72 |
73 | //get Titles
74 | dev = (TextView) findViewById(R.id.dev);
75 |
76 | credits = (TextView) findViewById(R.id.credits);
77 |
78 | libraries = (TextView) findViewById(R.id.libs);
79 |
80 | appInfo = (TextView) findViewById(R.id.app_info);
81 |
82 | //set text options to titles
83 | setTextUnderline(dev, credits, libraries, appInfo);
84 |
85 | //Developer info
86 | //git page
87 | enricoGit = (TextView) findViewById(R.id.enrico_git);
88 |
89 | enricoGitPage = "github";
90 |
91 | enricoGit.setText(setTextLinks(enricoGitPage, enricoGit));
92 |
93 | //gplus page
94 | enricoGplus = (TextView) findViewById(R.id.enrico_gplus);
95 |
96 | enricoGplusPage = "google+";
97 |
98 | enricoGplus.setText(setTextLinks(enricoGplusPage, enricoGplus));
99 |
100 | //Credits
101 | //Ivan
102 |
103 | //git page
104 | ivanGit = (TextView) findViewById(R.id.ivan_git);
105 |
106 | ivanGitPage = "github";
107 |
108 | ivanGit.setText(setTextLinks(ivanGitPage, ivanGit));
109 |
110 | //gplus page
111 | ivanGplus = (TextView) findViewById(R.id.ivan_gplus);
112 |
113 | ivanGplusPage = "google+";
114 |
115 | ivanGplus.setText(setTextLinks(ivanGplusPage, ivanGplus));
116 |
117 | //stackoverflow
118 | stack = (TextView) findViewById(R.id.stack_page);
119 |
120 | stackPage = "home";
121 |
122 | stack.setText(setTextLinks(stackPage, stack));
123 |
124 | //Lucas Urbas
125 | lucas = (TextView) findViewById(R.id.lucas_page);
126 |
127 | lucasPage = "responsive toolbar";
128 |
129 | lucas.setText(setTextLinks(lucasPage, lucas));
130 |
131 | //Libraries used
132 |
133 | //v4 support
134 | support4 = (TextView) findViewById(R.id.v4_page);
135 |
136 | support4page = "page";
137 |
138 | support4.setText(setTextLinks(support4page, support4));
139 |
140 | //appcompat
141 | appCompat = (TextView) findViewById(R.id.appcompat_page);
142 |
143 | appCompatPage = "page";
144 |
145 | appCompat.setText(setTextLinks(appCompatPage, appCompat));
146 |
147 | //recyclerView
148 | recyclerView = (TextView) findViewById(R.id.recyclerView_page);
149 |
150 | recyclerViewPage = "page";
151 |
152 | recyclerView.setText(setTextLinks(recyclerViewPage, recyclerView));
153 |
154 | //cardView
155 | cardView = (TextView) findViewById(R.id.card_page);
156 |
157 | cardViewPage = "page";
158 |
159 | cardView.setText(setTextLinks(cardViewPage, cardView));
160 |
161 | //jsoup
162 | jsoup = (TextView) findViewById(R.id.soup_page);
163 |
164 | jsoupPage = "github";
165 |
166 | jsoup.setText(setTextLinks(jsoupPage, jsoup));
167 |
168 | //glide
169 | glide = (TextView) findViewById(R.id.glide_page);
170 |
171 | glidePage = "github";
172 |
173 | glide.setText(setTextLinks(glidePage, glide));
174 |
175 | //Application info
176 | //set build version
177 | version = BuildConfig.VERSION_NAME;
178 |
179 | build = (TextView) findViewById(R.id.version);
180 |
181 | build.setText(getString(R.string.version) + colon + version);
182 |
183 | //set application git page
184 | sources = (TextView) findViewById(R.id.sources);
185 |
186 | appGit = "github";
187 |
188 | sources.setText(setTextLinks(appGit, sources));
189 |
190 | //set text options
191 | setTextOptions(enricoGit, enricoGplus, ivanGit, build, sources);
192 | }
193 |
194 | //set text options
195 | public void setTextOptions(TextView... textView) {
196 |
197 | for (TextView body : textView) {
198 | body.setElegantTextHeight(true);
199 | }
200 | }
201 |
202 | //method to style headlines
203 | public void setTextUnderline(TextView... textView) {
204 |
205 | for (TextView title : textView) {
206 | title.setElegantTextHeight(true);
207 | title.setElevation(6);
208 | title.setFontFeatureSettings("smcp"); //small caps
209 | title.setPaintFlags(title.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
210 | }
211 | }
212 |
213 | //close app
214 | @Override
215 | public boolean onOptionsItemSelected(MenuItem item) {
216 | if (item.getItemId() == android.R.id.home) {
217 |
218 | onBackPressed();
219 | return true;
220 | }
221 | return super.onOptionsItemSelected(item);
222 | }
223 | }
224 |
--------------------------------------------------------------------------------
/project/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | About
9 | Developer info
10 | \u2022 Enrico D\'Ortenzio
11 | Credits
12 | \u2022 Ivan D\'Ortenzio
13 | \u2022 stackoverflow
14 | \u2022 Lucas Urbas
15 | Libraries
16 | \u2022 v4 support library
17 | \u2022 v7 appcompat library
18 | \u2022 v7 recyclerView library
19 | \u2022 v7 cardView library
20 | \u2022 glide
21 | \u2022 jsoup
22 | Application info
23 | Version
24 |
25 | Iven News Reader
26 | placeholder
27 | Info
28 | Install a browser
29 | Share
30 | Choose your browser …
31 | Connect to the internet please
32 | Please wait …
33 |
34 |
35 |
36 |
37 | Theme options
38 | About
39 | Other options
40 | Options
41 | Changelog
42 | Option not available on pre-Marshmallow devices
43 | Notifications
44 |
45 |
46 | App theme
47 | The app needs to be restarted
48 | pref_theme
49 | pref_theme_list
50 | Light
51 | Dark
52 | Darker
53 |
54 | Red
55 | Pink
56 | Purple
57 | Deep purple
58 | Indigo
59 | Blue
60 | Light blue
61 | Cyan
62 | Teal
63 | Green
64 | Light green
65 | Lime
66 | Yellow
67 | Amber
68 | Orange
69 | Deep orange
70 | Brown
71 | Blue grey
72 | Red night
73 | Pink night
74 | Purple night
75 | Deep purple night
76 | Indigo night
77 | Blue night
78 | Light blue night
79 | Cyan night
80 | Teal night
81 | Green night
82 | Light green night
83 | Lime night
84 | Yellow night
85 | Amber night
86 | Orange night
87 | Deep orange night
88 | Brown night
89 | Blue grey night
90 |
91 |
92 | Dark status icons
93 | Enable dark colored status bar icons
94 |
95 |
96 | Enable navbar tint
97 | This will enable navigation bar tinting
98 |
99 |
100 | Immersive mode
101 | Enable immersive mode on article\'s activity
102 |
103 |
104 | Disable images
105 | Disable article\'s images visualisation
106 |
107 |
108 | Use webview
109 | Read more using in-app webview
110 | Enable JavaScript
111 |
112 |
113 | pref_text_size
114 | pref_text_size_list
115 | Adjust articles font
116 | Adjust items font
117 | Choose default text size on articles
118 | Choose default text size of the home items
119 | Very small
120 | Small
121 | Medium
122 | Large
123 | Very large
124 |
125 |
126 | Clear app cache
127 | This option will clean the app cache and reset the options
128 |
129 |
130 | Discard feed
131 | Do you want to discard
132 | Feed addition
133 | Add a feed
134 | Url here
135 | Name here
136 | Insert your custom feed in RSS format
137 |
138 |
139 | pref_time
140 | Choose check interval
141 | Choose the time between every check
142 | Notification sound
143 | Change notification sound
144 |
145 | New articles posted :D
146 | Enable notifications
147 | Get a notification when new articles are posted
148 |
149 | 15 seconds
150 | 30 seconds
151 | 1 minute
152 | 5 minutes
153 | 10 minutes
154 | 20 minutes
155 | 30 minutes
156 | 1 hour
157 |
158 |
--------------------------------------------------------------------------------
/project/app/src/main/java/com/iven/lfflfeedreader/mainact/ArticlePage.java:
--------------------------------------------------------------------------------
1 | package com.iven.lfflfeedreader.mainact;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.graphics.Bitmap;
5 | import android.os.Bundle;
6 | import android.support.v4.view.MenuItemCompat;
7 | import android.support.v7.app.AppCompatActivity;
8 | import android.support.v7.view.ContextThemeWrapper;
9 | import android.support.v7.widget.AppCompatCheckBox;
10 | import android.support.v7.widget.Toolbar;
11 | import android.view.Menu;
12 | import android.view.MenuItem;
13 | import android.view.View;
14 | import android.view.ViewGroup;
15 | import android.webkit.WebSettings;
16 | import android.webkit.WebSettings.LayoutAlgorithm;
17 | import android.webkit.WebView;
18 | import android.webkit.WebViewClient;
19 | import android.widget.CompoundButton;
20 | import android.widget.LinearLayout;
21 | import android.widget.ProgressBar;
22 | import android.widget.Toast;
23 |
24 | import com.iven.lfflfeedreader.R;
25 | import com.iven.lfflfeedreader.utils.Preferences;
26 |
27 | public class ArticlePage extends AppCompatActivity {
28 |
29 | //initialize feed infos
30 | String feedurl;
31 |
32 | //webview
33 | WebView wv;
34 | WebSettings ws;
35 |
36 | //ContextThemeWrapper
37 | ContextThemeWrapper themewrapper;
38 |
39 | //view
40 | AppCompatCheckBox js_button;
41 | Toolbar toolbar;
42 | Toast toast;
43 | ProgressBar progressBar;
44 | View v;
45 |
46 | //create the toolbar's menu
47 | @Override
48 | public boolean onCreateOptionsMenu(Menu menu) {
49 |
50 | getMenuInflater().inflate(R.menu.wb_menu, menu);
51 |
52 | return super.onCreateOptionsMenu(menu);
53 |
54 | }
55 |
56 | @SuppressLint("SetJavaScriptEnabled")
57 | @Override
58 | public boolean onPrepareOptionsMenu(Menu menu) {
59 |
60 | MenuItem actionViewItem = menu.findItem(R.id.checkbox);
61 |
62 | //retrieve the ActionView from menu
63 | v = MenuItemCompat.getActionView(actionViewItem);
64 |
65 | //find the button within actionview
66 | js_button = (AppCompatCheckBox) v.findViewById(R.id.js);
67 |
68 | js_button.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
69 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
70 | if (isChecked) {
71 |
72 | //enable JavaScript
73 | ws.setJavaScriptEnabled(true);
74 |
75 | //set Toolbar title to 'JavaScript On'
76 | toolbar.setTitle("JavaScript On");
77 | wv.reload();
78 | } else {
79 |
80 | //disable JavaScript
81 | ws.setJavaScriptEnabled(false);
82 |
83 | //set Toolbar title to 'JavaScript Off'
84 | toolbar.setTitle("JavaScript Off");
85 | wv.reload();
86 | }
87 | }
88 | });
89 |
90 | // Handle button click here
91 | return super.onPrepareOptionsMenu(menu);
92 | }
93 |
94 | @Override
95 | public void onCreate(Bundle savedInstanceState) {
96 | super.onCreate(savedInstanceState);
97 |
98 | //get the feed's link from the intent
99 | if (savedInstanceState == null) {
100 | Bundle extras = getIntent().getExtras();
101 | if (extras != null) {
102 | feedurl = extras.getString("feedselected");
103 | }
104 | }
105 |
106 | //apply preferences
107 |
108 | //apply activity's theme if dark theme is enabled
109 | themewrapper = new ContextThemeWrapper(getBaseContext(), this.getTheme());
110 | Preferences.applyTheme(themewrapper, getBaseContext());
111 |
112 | //set the navbar tint if the preference is enabled
113 | Preferences.applyNavTint(this);
114 |
115 | //set LightStatusBar
116 | Preferences.applyLightIcons(this);
117 |
118 | //set the immersive mode (only for >= KitKat) if the preference is enabled
119 | Preferences.applyImmersiveMode(this);
120 |
121 | //set the view
122 | setContentView(R.layout.article_page_layout);
123 |
124 | //set the toolbar
125 | toolbar = (Toolbar) findViewById(R.id.toolbar);
126 | setSupportActionBar(toolbar);
127 |
128 | //provide back navigation
129 | if (getSupportActionBar() != null) {
130 | getSupportActionBar().setDisplayHomeAsUpEnabled(true);
131 | }
132 |
133 | toolbar.setNavigationOnClickListener(new View.OnClickListener() {
134 | @Override
135 | public void onClick(View v) {
136 | onBackPressed();
137 | overridePendingTransition(0, 0);
138 | }
139 | });
140 |
141 | //set toolbar title
142 | getSupportActionBar().setTitle("JavaScript Off");
143 |
144 | //initialize the webview & its settings
145 | wv = (WebView) findViewById(R.id.web_view);
146 |
147 | ws = wv.getSettings();
148 |
149 | //initialize the progress bar
150 | progressBar = (ProgressBar) findViewById(R.id.progress);
151 |
152 | //set default encoding
153 | ws.setDefaultTextEncodingName("utf-8");
154 |
155 | //enum for controlling the layout of html. NORMAL means no rendering changes.
156 | //for more info http://developer.android.com/reference/android/webkit/WebSettings.LayoutAlgorithm.html
157 | ws.setLayoutAlgorithm(LayoutAlgorithm.NORMAL);
158 |
159 | //other WebView Settings
160 |
161 | //fit screen size
162 | ws.setLoadWithOverviewMode(true);
163 | ws.setUseWideViewPort(true);
164 |
165 | //enable pinch to zoom
166 | ws.setBuiltInZoomControls(true);
167 | ws.setDisplayZoomControls(false);
168 |
169 | //for more info about the next method:
170 | //http://stackoverflow.com/questions/3149216/how-to-listen-for-a-webview-finishing-loading-a-url-in-android
171 | wv.setWebViewClient(new WebViewClient() {
172 |
173 | private int running = 0; // Could be public if you want a timer to check.
174 |
175 | //on page started loading show circle progress
176 | @Override
177 | public void onPageStarted(WebView view, String url, Bitmap favicon) {
178 |
179 | running = Math.max(running, 1); // First request move it to 1.
180 |
181 | //hide WebView
182 | wv.setVisibility(View.INVISIBLE);
183 |
184 | //show loading toast
185 | toast = Toast.makeText(getBaseContext(), getResources().getString(R.string.loading), Toast.LENGTH_LONG);
186 |
187 | toast.show();
188 |
189 | //show progress bar
190 | progressBar.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 6));
191 | progressBar.setVisibility(View.VISIBLE);
192 |
193 | }
194 |
195 | //stop progress bar when the page is finished loading
196 | //and show the webview
197 | @Override
198 | public void onPageFinished(WebView view, String url) {
199 | if (--running == 0) { // just "running--;" if you add a timer.
200 |
201 | //show WebView
202 | wv.setVisibility(View.VISIBLE);
203 |
204 | //cancel the toast if WebView has finished loading
205 | toast.cancel();
206 |
207 | //hide progress bar
208 | progressBar.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0));
209 | progressBar.setVisibility(View.INVISIBLE);
210 |
211 | }
212 | }
213 | });
214 |
215 | this.runOnUiThread(new Runnable() {
216 | @Override
217 | public void run() {
218 | wv.loadUrl(feedurl);
219 |
220 | }
221 | });
222 | }
223 |
224 |
225 | //(only for >= KitKat)
226 | //fix Immersive mode navigation becomes sticky after minimise-restore
227 | @Override
228 | public void onWindowFocusChanged(boolean hasFocus) {
229 | super.onWindowFocusChanged(hasFocus);
230 | if (hasFocus) {
231 | Preferences.applyImmersiveMode(this);
232 | }
233 | }
234 | }
235 |
236 |
--------------------------------------------------------------------------------
/project/app/src/main/java/com/iven/lfflfeedreader/mainact/ArticleFragment.java:
--------------------------------------------------------------------------------
1 | package com.iven.lfflfeedreader.mainact;
2 |
3 | import android.content.Intent;
4 | import android.graphics.Typeface;
5 | import android.net.Uri;
6 | import android.os.Bundle;
7 | import android.support.v4.app.Fragment;
8 | import android.support.v7.app.AppCompatActivity;
9 | import android.text.Spannable;
10 | import android.text.SpannableString;
11 | import android.text.style.LeadingMarginSpan;
12 | import android.text.style.StyleSpan;
13 | import android.util.TypedValue;
14 | import android.view.LayoutInflater;
15 | import android.view.View;
16 | import android.view.ViewGroup;
17 | import android.widget.ImageButton;
18 | import android.widget.ImageView;
19 | import android.widget.LinearLayout;
20 | import android.widget.TextView;
21 |
22 | import com.iven.lfflfeedreader.R;
23 | import com.iven.lfflfeedreader.domparser.RSSFeed;
24 | import com.iven.lfflfeedreader.domparser.RSSItem;
25 | import com.iven.lfflfeedreader.utils.ArticleUtils;
26 | import com.iven.lfflfeedreader.utils.GlideUtils;
27 | import com.iven.lfflfeedreader.utils.Preferences;
28 |
29 | import org.jsoup.Jsoup;
30 |
31 | public class ArticleFragment extends Fragment {
32 |
33 | //feed
34 | RSSFeed fFeed;
35 | RSSItem feedItem;
36 | String feedDescription;
37 | String feedCompleteDescription;
38 | String datDescription;
39 | String imageLink;
40 | String imageLink2;
41 | String feedLink;
42 | String feedTitle;
43 | String feedDate;
44 | String datDescriptionFirstformat;
45 | String datDescriptionSecondformat;
46 | String datDescriptionThirdformat;
47 |
48 | //views
49 | ViewGroup rootView;
50 | TextView title;
51 | TextView subtitle;
52 | ImageButton button_continue_reading;
53 | ImageButton button_share;
54 | ImageButton button_back;
55 | ImageView imageView;
56 | LinearLayout article_default_linearLayout;
57 | TextView articletext;
58 |
59 | //Spannable
60 | Spannable titleSpan;
61 | Spannable subtitleSpan;
62 | Spannable storySpan;
63 | LeadingMarginSpan leadingMarginSpan;
64 |
65 | float size;
66 |
67 | @Override
68 | public void onCreate(Bundle savedInstanceState) {
69 |
70 | super.onCreate(savedInstanceState);
71 |
72 | //position
73 | int fPos;
74 |
75 | //initialize the feed (i.e. get all the data)
76 | fFeed = (RSSFeed) getArguments().getSerializable("feed");
77 | fPos = getArguments().getInt("pos");
78 | feedItem = fFeed.getItem(fPos);
79 |
80 | //get the content
81 | feedCompleteDescription = feedItem.getCompleteDescription();
82 | feedDescription = feedItem.getDescription();
83 | imageLink = feedItem.getImage();
84 | imageLink2 = feedItem.getImage2();
85 | feedLink = feedItem.getLink();
86 | feedTitle = feedItem.getTitle();
87 | feedDate = feedItem.getDate();
88 | datDescription = feedItem.getDescription();
89 |
90 | }
91 |
92 | @Override
93 | public View onCreateView(LayoutInflater inflater, ViewGroup container,
94 | Bundle savedInstanceState) {
95 |
96 | //set the view
97 | rootView = (ViewGroup) inflater
98 | .inflate(R.layout.article_fragment, container, false);
99 |
100 | //article title and subtitle
101 | //title
102 | title = (TextView) rootView.findViewById(R.id.title);
103 |
104 | //subtitle
105 | subtitle = (TextView) rootView.findViewById(R.id.subtitle);
106 |
107 | //action Buttons
108 |
109 | //read more button
110 | button_continue_reading = (ImageButton) rootView.findViewById(R.id.button_continue);
111 |
112 | //this is the method to handle the continue reading button click
113 | View.OnClickListener listener_forward = new View.OnClickListener() {
114 | @Override
115 | public void onClick(View v) {
116 | if (Preferences.WebViewEnabled(getContext())) {
117 | ArticleUtils.openFeedPage(getActivity(), feedLink);
118 | } else {
119 | ArticleUtils.continueReading(getActivity(), feedLink);
120 | }
121 | }
122 | };
123 |
124 | //set Read more listener
125 | button_continue_reading.setOnClickListener(listener_forward);
126 |
127 | if (Preferences.WebViewEnabled(getContext())) {
128 |
129 | //this is the method to handle the continue reading long button click
130 | View.OnLongClickListener listener_external = new View.OnLongClickListener() {
131 | @Override
132 | public boolean onLongClick(View v) {
133 |
134 | //open the url using external browser if webview is enabled
135 | ArticleUtils.continueReading(getActivity(), feedLink);
136 |
137 | return true;
138 | }
139 | };
140 |
141 | //set the long click listener
142 | button_continue_reading.setOnLongClickListener(listener_external);
143 | }
144 |
145 | //share button
146 | button_share = (ImageButton) rootView.findViewById(R.id.button_share);
147 |
148 | //this is the method to handle the share button click
149 | View.OnClickListener listener_share = new View.OnClickListener() {
150 | @Override
151 | public void onClick(View v) {
152 | ArticleUtils.share(getActivity(), feedLink, feedTitle);
153 |
154 | }
155 | };
156 |
157 | //set Share listener
158 | button_share.setOnClickListener(listener_share);
159 |
160 | //back button
161 | button_back = (ImageButton) rootView.findViewById(R.id.button_back);
162 |
163 | //this is the click listener to provide back navigation
164 | View.OnClickListener listener_back = new View.OnClickListener() {
165 | @Override
166 | public void onClick(View v) {
167 | AppCompatActivity appCompatActivity = (AppCompatActivity) getActivity();
168 | ArticleUtils.goBack(appCompatActivity);
169 |
170 | }
171 | };
172 |
173 | //set back button on click listener
174 | button_back.setOnClickListener(listener_back);
175 |
176 | titleSpan = new SpannableString(feedTitle.toUpperCase());
177 |
178 | titleSpan.setSpan(new StyleSpan(Typeface.BOLD), 0, titleSpan.length(), 0);
179 |
180 | //dynamically set title and subtitle according to the feed data
181 | //set title of the article
182 | title.setText(titleSpan);
183 |
184 | subtitleSpan = new SpannableString(feedDate);
185 |
186 | subtitleSpan.setSpan(new StyleSpan(Typeface.BOLD), 0, subtitleSpan.length(), 0);
187 |
188 | //set the date of the article to subtitle
189 | subtitle.setText(subtitleSpan);
190 |
191 | //set the articles text size from preferences
192 |
193 | //get the chosen article's text size from preferences
194 | size = Preferences.resolveTextSizeResId(getContext());
195 |
196 | //set it in SP unit
197 | title.setTextSize(TypedValue.COMPLEX_UNIT_SP, size + 4);
198 | subtitle.setTextSize(TypedValue.COMPLEX_UNIT_SP, size - 5);
199 |
200 | //if the preference is enabled remove the imageview from the linear layout
201 |
202 | //ImageView
203 | imageView = (ImageView) rootView.findViewById(R.id.img);
204 |
205 | //initialize the article view linear layout
206 | article_default_linearLayout = (LinearLayout) rootView.findViewById(R.id.article_linearlayout);
207 |
208 | if (Preferences.imagesRemoved(getContext())) {
209 |
210 | article_default_linearLayout.removeView(imageView);
211 |
212 | }
213 |
214 | //else, load the image
215 | //if getImage() method fails (i.e when img is in content:encoded) load image2
216 | else if (imageLink.isEmpty()) {
217 |
218 | GlideUtils.loadImage(getActivity(), imageLink2, imageView);
219 |
220 | //else use image
221 | } else {
222 |
223 | GlideUtils.loadImage(getActivity(), imageLink, imageView);
224 |
225 | }
226 |
227 | //we can open the image on web browser on long click on the image
228 | imageView.setOnLongClickListener(new View.OnLongClickListener() {
229 | public boolean onLongClick(View v) {
230 |
231 | final Intent intent;
232 |
233 | //open imageview links
234 | if (imageLink.isEmpty()) {
235 |
236 | intent = new Intent(Intent.ACTION_VIEW, Uri.parse(imageLink2));
237 |
238 | }
239 |
240 | //else use image
241 | else {
242 | intent = new Intent(Intent.ACTION_VIEW, Uri.parse(imageLink));
243 |
244 | }
245 |
246 | //open the image
247 | ArticleUtils.openImageLink(getActivity(), intent);
248 |
249 |
250 | return true;
251 | }
252 | }
253 | );
254 |
255 | //set the article's content
256 |
257 | //use complete description by default, but sometimes the method returns null
258 | if (feedCompleteDescription.contains("no desc")) {
259 | datDescription = Jsoup.parse(feedDescription).text().replace("Continua a leggere...", "");
260 |
261 | // else, use complete description
262 | } else {
263 | datDescription = Jsoup.parse(feedCompleteDescription).text().replace("Continua a leggere...", "");
264 |
265 | }
266 |
267 | //replace some items since this is a simple TextView
268 | datDescriptionFirstformat = datDescription.replace("Continue reading...", "");
269 |
270 | datDescriptionSecondformat = datDescriptionFirstformat.replace("Read More", "");
271 |
272 | datDescriptionThirdformat = datDescriptionSecondformat.replace("(read more)", "");
273 |
274 | //load the article inside a TextView
275 | articletext = (TextView) rootView.findViewById(R.id.webv);
276 |
277 | storySpan = new SpannableString(datDescriptionThirdformat);
278 |
279 | storySpan.setSpan(new StyleSpan(Typeface.ITALIC), 0, storySpan.length(), 0);
280 |
281 | leadingMarginSpan = new android.text.style.LeadingMarginSpan.Standard(10);
282 |
283 | storySpan.setSpan(leadingMarginSpan, 0, storySpan.length(), 0);
284 |
285 | //set the articles text
286 | articletext.setText(storySpan);
287 |
288 | //set the article text size according to preferences
289 | articletext.setTextSize(TypedValue.COMPLEX_UNIT_SP, size);
290 |
291 | return rootView;
292 |
293 | }
294 | }
--------------------------------------------------------------------------------
/project/app/src/main/java/com/iven/lfflfeedreader/utils/Preferences.java:
--------------------------------------------------------------------------------
1 | package com.iven.lfflfeedreader.utils;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.os.Build;
6 | import android.preference.PreferenceManager;
7 | import android.support.v7.view.ContextThemeWrapper;
8 | import android.util.TypedValue;
9 | import android.view.View;
10 |
11 | import com.iven.lfflfeedreader.R;
12 |
13 | public class Preferences {
14 |
15 | //This is where preferences are stored.
16 |
17 | public static int getThemeAccentColor(final Context context) {
18 | final TypedValue value = new TypedValue();
19 | context.getTheme().resolveAttribute(android.R.attr.colorAccent, value, true);
20 | return value.data;
21 | }
22 |
23 | //multi-preference dialog for articles text size
24 | public static float resolveTextSizeResId(Context context) {
25 |
26 | //Text size options
27 | float verysmall = 12;
28 | float small = 18;
29 | float medium = 24;
30 | float large = 30;
31 | float verylarge = 36;
32 |
33 | String choice = PreferenceManager.getDefaultSharedPreferences(context)
34 | .getString(context.getString(R.string.pref_text_size), String.valueOf(1));
35 | switch (Integer.parseInt(choice)) {
36 | case 0:
37 | return verysmall;
38 | case 1:
39 | default:
40 | return small;
41 | case 2:
42 | return medium;
43 | case 3:
44 | return large;
45 | case 4:
46 | return verylarge;
47 | }
48 | }
49 |
50 | //multi-preference dialog for notification options
51 | static int resolveTime(Context context) {
52 |
53 | //Text size options
54 | int minimum = 15;
55 | int normal = 30;
56 | int onemin = 60;
57 | int fivemin = 300;
58 | int tenmin = 600;
59 | int twentymin = 1200;
60 | int thirtymin = 1800;
61 | int onehour = 3600;
62 |
63 | String choice = PreferenceManager.getDefaultSharedPreferences(context)
64 | .getString(context.getString(R.string.pref_time), String.valueOf(47));
65 | switch (Integer.parseInt(choice)) {
66 | case 46:
67 | return minimum;
68 | default:
69 | case 47:
70 | return normal;
71 | case 48:
72 | return onemin;
73 | case 49:
74 | return fivemin;
75 | case 50:
76 | return tenmin;
77 | case 51:
78 | return twentymin;
79 | case 52:
80 | return thirtymin;
81 | case 53:
82 | return onehour;
83 | }
84 | }
85 |
86 | //multi-preference dialog for list items text size
87 | public static int resolveTextSizeListResId(Context context) {
88 |
89 | //Text size options
90 | int small_list = 10;
91 | int medium_list = 14;
92 | int large_list = 18;
93 |
94 | String choice = PreferenceManager.getDefaultSharedPreferences(context)
95 | .getString(context.getString(R.string.pref_text_size_list), String.valueOf(6));
96 | switch (Integer.parseInt(choice)) {
97 | case 5:
98 | return small_list;
99 | case 6:
100 | default:
101 | return medium_list;
102 | case 7:
103 | return large_list;
104 | }
105 | }
106 |
107 | //multi-preference dialog for theme options
108 | private static int resolveTheme(Context context) {
109 |
110 | //Themes options
111 |
112 | //light theme
113 | int light = R.style.Base_Theme;
114 |
115 | //dark theme
116 | int dark = R.style.Base_Theme_Dark;
117 |
118 | //other themes
119 | int red = R.style.Base_Theme_Red;
120 | int nightRed = R.style.Base_Theme_Dark_Red;
121 | int pink = R.style.Base_Theme_Pink;
122 | int nightPink = R.style.Base_Theme_Dark_Pink;
123 | int purple = R.style.Base_Theme_Purple;
124 | int nightPurple = R.style.Base_Theme_Dark_Purple;
125 | int deepPurple = R.style.Base_Theme_DeepPurple;
126 | int nightDeepPurple = R.style.Base_Theme_Dark_DeepPurple;
127 | int indigo = R.style.Base_Theme_Indigo;
128 | int nightIndigo = R.style.Base_Theme_Dark_Indigo;
129 | int blue = R.style.Base_Theme_Blue;
130 | int nightBlue = R.style.Base_Theme_Dark_Blue;
131 | int lightBlue = R.style.Base_Theme_LightBlue;
132 | int nightLightBlue = R.style.Base_Theme_Dark_LightBlue;
133 | int cyan = R.style.Base_Theme_Cyan;
134 | int nightCyan = R.style.Base_Theme_Dark_Cyan;
135 | int teal = R.style.Base_Theme_Teal;
136 | int nightTeal = R.style.Base_Theme_Dark_Teal;
137 | int green = R.style.Base_Theme_Green;
138 | int nightGreen = R.style.Base_Theme_Dark_Green;
139 | int lightGreen = R.style.Base_Theme_LightGreen;
140 | int nightLightGreen = R.style.Base_Theme_Dark_LightGreen;
141 | int lime = R.style.Base_Theme_Lime;
142 | int nightLime = R.style.Base_Theme_Dark_Lime;
143 | int yellow = R.style.Base_Theme_Yellow;
144 | int nightYellow = R.style.Base_Theme_Dark_Yellow;
145 | int amber = R.style.Base_Theme_Amber;
146 | int nightAmber = R.style.Base_Theme_Dark_Amber;
147 | int orange = R.style.Base_Theme_Orange;
148 | int nightOrange = R.style.Base_Theme_Dark_Orange;
149 | int deepOrange = R.style.Base_Theme_DeepOrange;
150 | int nightDeepOrange = R.style.Base_Theme_Dark_DeepOrange;
151 | int brown = R.style.Base_Theme_Brown;
152 | int nightBrown = R.style.Base_Theme_Dark_Brown;
153 | int blueGrey = R.style.Base_Theme_BlueGrey;
154 | int nightBlueGrey = R.style.Base_Theme_Dark_BlueGrey;
155 |
156 |
157 | String choice = PreferenceManager.getDefaultSharedPreferences(context)
158 | .getString(context.getString(R.string.pref_theme), String.valueOf(8));
159 | switch (Integer.parseInt(choice)) {
160 | default:
161 | case 8:
162 | return light;
163 | case 9:
164 | return dark;
165 |
166 | case 10:
167 | return red;
168 |
169 | case 11:
170 | return nightRed;
171 | case 12:
172 | return pink;
173 | case 13:
174 | return nightPink;
175 | case 14:
176 | return purple;
177 | case 15:
178 | return nightPurple;
179 | case 16:
180 | return deepPurple;
181 | case 17:
182 | return nightDeepPurple;
183 | case 18:
184 | return indigo;
185 | case 19:
186 | return nightIndigo;
187 | case 20:
188 | return blue;
189 | case 21:
190 | return nightBlue;
191 | case 22:
192 | return lightBlue;
193 | case 23:
194 | return nightLightBlue;
195 | case 24:
196 | return cyan;
197 | case 25:
198 | return nightCyan;
199 | case 26:
200 | return teal;
201 | case 27:
202 | return nightTeal;
203 | case 28:
204 | return green;
205 | case 29:
206 | return nightGreen;
207 | case 30:
208 | return lightGreen;
209 | case 31:
210 | return nightLightGreen;
211 | case 32:
212 | return lime;
213 | case 33:
214 | return nightLime;
215 | case 34:
216 | return yellow;
217 | case 35:
218 | return nightYellow;
219 | case 36:
220 | return amber;
221 | case 37:
222 | return nightAmber;
223 | case 38:
224 | return orange;
225 | case 39:
226 | return nightOrange;
227 | case 40:
228 | return deepOrange;
229 | case 41:
230 | return nightDeepOrange;
231 | case 42:
232 | return brown;
233 | case 43:
234 | return nightBrown;
235 | case 44:
236 | return blueGrey;
237 | case 45:
238 | return nightBlueGrey;
239 |
240 | }
241 | }
242 |
243 | //method to apply selected theme
244 | public static void applyTheme(ContextThemeWrapper contextThemeWrapper, Context context) {
245 | int theme = Preferences.resolveTheme(context);
246 | contextThemeWrapper.setTheme(theme);
247 |
248 | }
249 |
250 | //preference for the webview
251 | public static boolean WebViewEnabled(Context context) {
252 | return PreferenceManager.getDefaultSharedPreferences(context)
253 | .getBoolean("WebViewLoad", false);
254 | }
255 |
256 | //are light icons enabled?
257 | private static boolean LightIconsEnabled(Context context) {
258 | return PreferenceManager.getDefaultSharedPreferences(context)
259 | .getBoolean("lightcolored", false);
260 | }
261 |
262 | //if yes apply LightStatusBar icons
263 | public static void applyLightIcons(Activity activity) {
264 | if (Build.VERSION.SDK_INT >= 23) {
265 | if (Preferences.LightIconsEnabled(activity)) {
266 | activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
267 | }
268 | }
269 | }
270 |
271 | //Is navigation bar tint enabled?
272 | private static boolean NavTintEnabled(Context context) {
273 | return PreferenceManager.getDefaultSharedPreferences(context)
274 | .getBoolean("Navibar", false);
275 | }
276 |
277 | //if yes apply Navigation tint
278 | public static void applyNavTint(Activity activity) {
279 | if (Build.VERSION.SDK_INT >= 21) {
280 | if (Preferences.NavTintEnabled(activity)) {
281 | activity.getWindow().setNavigationBarColor(getThemeAccentColor(activity));
282 | }
283 | }
284 | }
285 |
286 | //is immersive mode enabled?
287 | private static boolean immersiveEnabled(Context context) {
288 | return PreferenceManager.getDefaultSharedPreferences(context)
289 | .getBoolean("Immerseme", false);
290 |
291 | }
292 |
293 | //if yes apply immersive mode
294 | public static void applyImmersiveMode(Activity activity) {
295 |
296 | if (Preferences.immersiveEnabled(activity)) {
297 | //immersive mode
298 | activity.getWindow().getDecorView().setSystemUiVisibility(
299 | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
300 | | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
301 | | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
302 | | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
303 | | View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
304 | | View.SYSTEM_UI_FLAG_IMMERSIVE
305 |
306 | //Sticky flag - This is the UI you see if you use the IMMERSIVE_STICKY flag, and the user
307 | //swipes to display the system bars. Semi-transparent bars temporarily appear
308 | //and then hide again
309 | | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
310 | );
311 | }
312 | }
313 |
314 | //are images removed?
315 | public static boolean imagesRemoved(Context context) {
316 | return PreferenceManager.getDefaultSharedPreferences(context)
317 | .getBoolean("images", false);
318 | }
319 |
320 | //are notifications enabled?
321 | public static boolean notificationsEnabled(Context context) {
322 | return PreferenceManager.getDefaultSharedPreferences(context)
323 | .getBoolean("notifications", false);
324 | }
325 | }
326 |
--------------------------------------------------------------------------------
/project/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
17 |
18 |
31 |
32 |
36 |
37 |
50 |
51 |
55 |
56 |
57 |
62 |
63 |
68 |
69 |
74 |
75 |
80 |
81 |
86 |
87 |
92 |
93 |
98 |
99 |
104 |
105 |
110 |
111 |
116 |
117 |
122 |
123 |
128 |
129 |
134 |
135 |
140 |
141 |
146 |
147 |
152 |
153 |
158 |
159 |
164 |
165 |
170 |
171 |
176 |
177 |
182 |
183 |
188 |
189 |
194 |
195 |
200 |
201 |
206 |
207 |
212 |
213 |
218 |
219 |
224 |
225 |
230 |
231 |
236 |
237 |
242 |
243 |
248 |
249 |
254 |
255 |
260 |
261 |
266 |
267 |
272 |
273 |
274 |
281 |
282 |
285 |
286 |
290 |
291 |
292 |
299 |
300 |
301 |
308 |
309 |
310 |
318 |
319 |
321 |
322 |
323 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
343 |
344 |
345 |
352 |
353 |
354 |
361 |
--------------------------------------------------------------------------------