├── .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 | 7 | 8 | 9 | 14 | 15 | -------------------------------------------------------------------------------- /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 | 9 | 10 | 11 | 16 | 17 | 18 | 23 | 24 | 25 | 31 | 32 | -------------------------------------------------------------------------------- /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 | ![ScreenShot](https://raw.githubusercontent.com/enricocid/iven-feed-reader/master-as/art/solid.png)![ScreenShot](https://raw.githubusercontent.com/enricocid/iven-feed-reader/master-as/art/round.png) 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 | ![ScreenShot](https://raw.githubusercontent.com/enricocid/iven-feed-reader/master-as/art/screens4.png) 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 | 343 | 344 | 345 | 352 | 353 | 354 | 361 | --------------------------------------------------------------------------------