├── .gitignore ├── README.md ├── app ├── .gitignore ├── app-release-1.3.apk ├── app-release.apk ├── build.gradle ├── google-services.json ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── amrendra │ │ └── codefiesta │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── amrendra │ │ │ └── codefiesta │ │ │ ├── CodeFiestaApplication.java │ │ │ ├── adapter │ │ │ ├── ContestAdapter.java │ │ │ └── SelectionAdapter.java │ │ │ ├── alarms │ │ │ ├── BootReceiver.java │ │ │ └── NotificationAlarm.java │ │ │ ├── bus │ │ │ ├── BusProvider.java │ │ │ └── events │ │ │ │ ├── CalendarPermissionGrantedEvent.java │ │ │ │ ├── ContestClickEvent.java │ │ │ │ ├── SettingsSaveEvent.java │ │ │ │ └── SnackBarMessageDetailFragmentEvent.java │ │ │ ├── db │ │ │ ├── DBContract.java │ │ │ ├── DBHelper.java │ │ │ └── Provider.java │ │ │ ├── handler │ │ │ └── DBQueryHandler.java │ │ │ ├── loaders │ │ │ ├── BaseLoader.java │ │ │ └── ResourceSettingLoader.java │ │ │ ├── model │ │ │ ├── ApiResponse.java │ │ │ ├── Contest.java │ │ │ ├── Error.java │ │ │ ├── Meta.java │ │ │ └── Website.java │ │ │ ├── progressbar │ │ │ └── TimerProgressBar.java │ │ │ ├── rest │ │ │ ├── RestApiClient.java │ │ │ └── RestApiService.java │ │ │ ├── sync │ │ │ ├── CodeFiestaAuthenticator.java │ │ │ ├── CodeFiestaAuthenticatorService.java │ │ │ ├── CodeFiestaSyncAdapter.java │ │ │ └── CodeFiestaSyncService.java │ │ │ ├── ui │ │ │ ├── activities │ │ │ │ ├── BaseActivity.java │ │ │ │ ├── MainActivity.java │ │ │ │ └── SplashScreenActivity.java │ │ │ └── fragments │ │ │ │ ├── BaseFragment.java │ │ │ │ ├── CreditsFragment.java │ │ │ │ ├── CurrentFragment.java │ │ │ │ ├── DetailFragment.java │ │ │ │ ├── PastFragment.java │ │ │ │ ├── SelectionFragment.java │ │ │ │ └── UpcomingFragment.java │ │ │ ├── utils │ │ │ ├── AppUtils.java │ │ │ ├── CalendarUtils.java │ │ │ ├── CustomDate.java │ │ │ ├── DateUtils.java │ │ │ ├── Debug.java │ │ │ ├── HtmlUtils.java │ │ │ ├── TimerUtil.java │ │ │ ├── TrackingConstants.java │ │ │ └── UserPreferences.java │ │ │ └── widget │ │ │ ├── CodeFiestaWidget.java │ │ │ ├── WidgetDataProvider.java │ │ │ └── WidgetService.java │ └── res │ │ ├── drawable-hdpi │ │ ├── credits.png │ │ ├── feedback.png │ │ ├── future.png │ │ ├── icon_notification.png │ │ ├── live.png │ │ ├── open_source.png │ │ ├── past.png │ │ ├── rate.png │ │ ├── refresh.png │ │ ├── settings.png │ │ └── share_app.png │ │ ├── drawable-mdpi │ │ ├── credits.png │ │ ├── feedback.png │ │ ├── future.png │ │ ├── icon_notification.png │ │ ├── live.png │ │ ├── open_source.png │ │ ├── past.png │ │ ├── rate.png │ │ ├── refresh.png │ │ ├── save.png │ │ ├── settings.png │ │ └── share_app.png │ │ ├── drawable-nodpi │ │ └── logo128.png │ │ ├── drawable-v21 │ │ └── button_ripple.xml │ │ ├── drawable-xhdpi │ │ ├── calendar_add.png │ │ ├── calendar_added.png │ │ ├── calendar_permission.png │ │ ├── credits.png │ │ ├── egg_empty.png │ │ ├── egg_error.png │ │ ├── feedback.png │ │ ├── future.png │ │ ├── icon_notification.png │ │ ├── live.png │ │ ├── notification_off.png │ │ ├── notification_on.png │ │ ├── open_source.png │ │ ├── past.png │ │ ├── rate.png │ │ ├── refresh.png │ │ ├── save.png │ │ ├── settings.png │ │ ├── share.png │ │ ├── share_app.png │ │ └── weblink.png │ │ ├── drawable-xxhdpi │ │ ├── credits.png │ │ ├── feedback.png │ │ ├── future.png │ │ ├── icon_notification.png │ │ ├── live.png │ │ ├── open_source.png │ │ ├── past.png │ │ ├── rate.png │ │ ├── refresh.png │ │ ├── save.png │ │ ├── settings.png │ │ └── share_app.png │ │ ├── drawable-xxxhdpi │ │ ├── credits.png │ │ ├── feedback.png │ │ ├── future.png │ │ ├── icon_notification.png │ │ ├── open_source.png │ │ ├── past.png │ │ ├── rate.png │ │ ├── refresh.png │ │ ├── save.png │ │ ├── settings.png │ │ ├── share_app.png │ │ └── widget_preview.png │ │ ├── drawable │ │ ├── button_ripple.xml │ │ ├── codechef.png │ │ ├── codeforces.png │ │ ├── hackerearth.png │ │ ├── hackerrank.png │ │ ├── kaggle.png │ │ ├── nav_item_selector.xml │ │ ├── round_tv_top.xml │ │ ├── splash.xml │ │ ├── spoj.png │ │ └── topcoder.png │ │ ├── layout-sw600dp │ │ └── activity_main.xml │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── coloress_divider.xml │ │ ├── contest_list_item.xml │ │ ├── divider.xml │ │ ├── error_view.xml │ │ ├── fragment_credits.xml │ │ ├── fragment_detail.xml │ │ ├── fragment_list.xml │ │ ├── loading_view.xml │ │ ├── nav_header_row.xml │ │ ├── select_item_row.xml │ │ ├── selection_fragment.xml │ │ ├── splash_activity.xml │ │ ├── toolbar.xml │ │ ├── widget_layout.xml │ │ └── widget_list_item.xml │ │ ├── menu │ │ └── menu_nav.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-v14 │ │ └── dimens.xml │ │ ├── values-v19 │ │ └── styles.xml │ │ ├── values-w820dp │ │ └── dimens.xml │ │ ├── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ │ ├── xml-v17 │ │ └── widget_info.xml │ │ └── xml │ │ ├── app_tracker.xml │ │ ├── authenticator.xml │ │ ├── syncadapter.xml │ │ └── widget_info.xml │ └── test │ └── java │ └── com │ └── amrendra │ └── codefiesta │ ├── ExampleUnitTest.java │ └── utils │ └── DateUtilsTest.java ├── build.gradle ├── design.pdf ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle/ 3 | /local.properties 4 | /.idea/ 5 | .DS_Store 6 | /build 7 | /captures 8 | app/build/ 9 | app/fabric.properties 10 | app/config/*.jks 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CodeZera 2 | Capstone Project : part of Android Nanodegree program at Udacity 3 | 4 | This app is for everyone who has passion for competitive programming across the globe. App lets you keep track of all upcoming, live and past contests on various websites which includes platforms like CodeChef, HackerRank, HackerEarth, Codeforces, TopCoder and others. 5 | Users can choose to set up reminder for upcoming contests, and get notified before the contest starts. Contests can be added to their calendars directly from the app. 6 | 7 | ## Features 8 | ● App shows all live, upcoming and past contests 9 | 10 | ● Contests can be categorized past, live and upcoming contests. 11 | 12 | ● Users can select his preferred websites to see contests from those websites only. 13 | 14 | ● Feature to add reminder notification for a contest 15 | 16 | ● Contests can be added directly to the calendar 17 | 18 | ● Home Screen widget to track live contests 19 | 20 | ## Preview 21 | 22 | ![Snapshot1](https://lh3.googleusercontent.com/sr8RJ58EHfGfhtdiEeSNesG0zZXJFgpYrnaw3neUGpQCRStPKDkEUOnoe6qtSyFB2DIs=h300-rw) ![Snapshot2](https://lh3.googleusercontent.com/iYEZQVkcvVU1dxCi7SQbieK6E1m7lSk-TAhsga141LDvbszbJN8gg4UsnbRFGVzqNpI=h300-rw) ![Snapshot3](https://lh3.googleusercontent.com/6xx4MwYYCGzemKnOX7gBxCibV5FpzFon2EcTi7XDWqLd5LNmPkQ19dB_e_dQFoig5aA=h300-rw) 23 | 24 | ## Google PlayStore 25 | Download and try out the app from playstore [here](https://play.google.com/store/apps/details?id=com.amrendra.codefiesta&hl=en). Donot forget to rate the app, and leave your valuable reviews/suggestions. 26 | 27 | App demo [here](https://www.youtube.com/watch?v=f0j-of73IHo) 28 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/app-release-1.3.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/app-release-1.3.apk -------------------------------------------------------------------------------- /app/app-release.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/app-release.apk -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | maven { url 'https://maven.fabric.io/public' } 4 | } 5 | 6 | dependencies { 7 | classpath 'io.fabric.tools:gradle:1.+' 8 | } 9 | } 10 | apply plugin: 'com.android.application' 11 | apply plugin: 'io.fabric' 12 | 13 | repositories { 14 | maven { url 'https://maven.fabric.io/public' } 15 | } 16 | 17 | def isCiServer = (System.getenv().containsKey("TRAVIS")) 18 | def API_KEY; 19 | def API_USERNAME; 20 | def RELEASE_STORE_PASSWORD 21 | def RELEASE_KEY_ALIAS 22 | def RELEASE_KEY_PASSWORD 23 | 24 | 25 | if (isCiServer) { 26 | API_KEY = System.getenv("CLIST_API_KEY") as String; 27 | API_USERNAME = System.getenv("CLIST_API_USERNAME") as String; 28 | RELEASE_STORE_PASSWORD = System.getenv("RELEASE_STORE_PASSWORD") as String; 29 | RELEASE_KEY_ALIAS = System.getenv("RELEASE_KEY_ALIAS") as String; 30 | RELEASE_KEY_PASSWORD = System.getenv("RELEASE_KEY_PASSWORD") as String; 31 | } else { 32 | API_KEY = '"' + codefiesta_api_key + '"'; 33 | API_USERNAME = '"' + codefiesta_api_username + '"'; 34 | RELEASE_STORE_PASSWORD = codefiesta_store_password; 35 | RELEASE_KEY_ALIAS = codefiesta_key_alias; 36 | RELEASE_KEY_PASSWORD = codefiesta_key_password; 37 | } 38 | 39 | android { 40 | compileSdkVersion 23 41 | buildToolsVersion "23.0.2" 42 | 43 | defaultConfig { 44 | applicationId "com.amrendra.codefiesta" 45 | minSdkVersion 16 46 | targetSdkVersion 23 47 | versionCode 3 48 | versionName "1.3" 49 | } 50 | 51 | signingConfigs { 52 | release { 53 | storeFile file("config/codezera.jks") 54 | storePassword "$RELEASE_STORE_PASSWORD" 55 | keyAlias "$RELEASE_KEY_ALIAS" 56 | keyPassword "$RELEASE_KEY_PASSWORD" 57 | } 58 | } 59 | 60 | buildTypes { 61 | release { 62 | signingConfig signingConfigs.release 63 | minifyEnabled false 64 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 65 | } 66 | 67 | buildTypes.each { 68 | it.buildConfigField 'String', 'API_KEY', "$API_KEY" 69 | it.buildConfigField 'String', 'API_USERNAME', "$API_USERNAME" 70 | } 71 | } 72 | 73 | compileOptions { 74 | sourceCompatibility JavaVersion.VERSION_1_7 75 | targetCompatibility JavaVersion.VERSION_1_7 76 | } 77 | } 78 | 79 | // Debug tasks to test keys 80 | task testKeys(){ 81 | System.out.println("API_KEY="+API_KEY); 82 | System.out.println("API_USERNAME="+API_USERNAME); 83 | System.out.println("RELEASE_STORE_PASSWORD="+RELEASE_STORE_PASSWORD); 84 | System.out.println("RELEASE_KEY_ALIAS="+RELEASE_KEY_ALIAS); 85 | System.out.println("RELEASE_KEY_PASSWORD="+RELEASE_KEY_PASSWORD); 86 | } 87 | 88 | dependencies { 89 | compile fileTree(dir: 'libs', include: ['*.jar']) 90 | testCompile 'junit:junit:4.12' 91 | 92 | compile 'com.android.support:appcompat-v7:23.1.1' 93 | compile 'com.android.support:design:23.1.1' 94 | compile 'com.android.support:cardview-v7:23.1.1' 95 | compile 'com.android.support:support-v4:23.1.1' 96 | 97 | compile 'com.squareup:otto:1.3.8' 98 | compile 'com.jakewharton:butterknife:7.0.1' 99 | compile 'com.squareup.retrofit:retrofit:2.0.0-beta2' 100 | compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2' 101 | compile 'com.github.bumptech.glide:glide:3.6.1' 102 | 103 | compile 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta2' 104 | compile 'io.reactivex:rxjava:1.0.13' 105 | 106 | compile 'com.google.android.gms:play-services-analytics:8.3.0' 107 | compile('com.crashlytics.sdk.android:crashlytics:2.6.5@aar') { 108 | transitive = true; 109 | } 110 | } 111 | 112 | apply plugin: 'com.google.gms.google-services' 113 | -------------------------------------------------------------------------------- /app/google-services.json: -------------------------------------------------------------------------------- 1 | { 2 | "project_info": { 3 | "project_id": "codefiesta-22bb8", 4 | "project_number": "786951059530", 5 | "name": "CodeFiesta" 6 | }, 7 | "client": [ 8 | { 9 | "client_info": { 10 | "mobilesdk_app_id": "1:786951059530:android:a65a36d58d9f424e", 11 | "client_id": "android:com.amrendra.codefiesta", 12 | "client_type": 1, 13 | "android_client_info": { 14 | "package_name": "com.amrendra.codefiesta", 15 | "certificate_hash": [] 16 | } 17 | }, 18 | "oauth_client": [], 19 | "api_key": [], 20 | "services": { 21 | "analytics_service": { 22 | "status": 2, 23 | "analytics_property": { 24 | "tracking_id": "UA-76539821-1" 25 | } 26 | }, 27 | "cloud_messaging_service": { 28 | "status": 1, 29 | "apns_config": [] 30 | }, 31 | "appinvite_service": { 32 | "status": 1, 33 | "other_platform_oauth_client": [] 34 | }, 35 | "google_signin_service": { 36 | "status": 1 37 | }, 38 | "ads_service": { 39 | "status": 1 40 | } 41 | } 42 | } 43 | ], 44 | "client_info": [], 45 | "ARTIFACT_VERSION": "1" 46 | } -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/amrendrk/android-sdks/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/amrendra/codefiesta/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 25 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 38 | 39 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 53 | 54 | 55 | 56 | 59 | 60 | 61 | 62 | 63 | 66 | 67 | 68 | 69 | 70 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 87 | 88 | 89 | 90 | 91 | 94 | 95 | 96 | 100 | 101 | 104 | 105 | 106 | 107 | 108 | 109 | 113 | 117 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 130 | 133 | 134 | 135 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrendra/codefiesta/CodeFiestaApplication.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta; 2 | 3 | import android.app.Application; 4 | 5 | import com.amrendra.codefiesta.sync.CodeFiestaSyncAdapter; 6 | import com.amrendra.codefiesta.utils.AppUtils; 7 | import com.amrendra.codefiesta.utils.Debug; 8 | import com.amrendra.codefiesta.utils.UserPreferences; 9 | import com.crashlytics.android.Crashlytics; 10 | import com.google.android.gms.analytics.GoogleAnalytics; 11 | import com.google.android.gms.analytics.Tracker; 12 | import io.fabric.sdk.android.Fabric; 13 | 14 | /** 15 | * Created by Amrendra Kumar on 05/04/16. 16 | */ 17 | public class CodeFiestaApplication extends Application { 18 | 19 | private Tracker mTracker; 20 | 21 | @Override 22 | public void onCreate() { 23 | super.onCreate(); 24 | Fabric.with(this, new Crashlytics()); 25 | AppUtils.cacheResources(this); 26 | getDefaultTracker(); 27 | checkAndSync(); 28 | } 29 | 30 | public void checkAndSync() { 31 | long lastSyncTime = UserPreferences.getInstance(this) 32 | .readValue(AppUtils.LAST_SYNC_PERFORMED, AppUtils 33 | .LAST_SYNC_PERFORMED_DEFAULT_VALUE); 34 | 35 | long currTime = System.currentTimeMillis() / 1000; 36 | if (currTime - lastSyncTime > AppUtils.SIX_HOURS) { 37 | CodeFiestaSyncAdapter.syncImmediately(this); 38 | } 39 | } 40 | 41 | public static void shouldNotHappen(String msg) { 42 | Debug.e(msg, false); 43 | } 44 | 45 | synchronized public Tracker getDefaultTracker() { 46 | if (mTracker == null) { 47 | GoogleAnalytics analytics = GoogleAnalytics.getInstance(this); 48 | // To enable debug logging use: adb shell setprop log.tag.GAv4 DEBUG 49 | mTracker = analytics.newTracker(R.xml.global_tracker); 50 | } 51 | return mTracker; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrendra/codefiesta/adapter/ContestAdapter.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta.adapter; 2 | 3 | import android.content.Context; 4 | import android.database.Cursor; 5 | import android.support.v4.widget.CursorAdapter; 6 | import android.support.v7.widget.CardView; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.ImageView; 11 | import android.widget.TextView; 12 | 13 | import com.amrendra.codefiesta.R; 14 | import com.amrendra.codefiesta.bus.BusProvider; 15 | import com.amrendra.codefiesta.bus.events.ContestClickEvent; 16 | import com.amrendra.codefiesta.model.Contest; 17 | import com.amrendra.codefiesta.utils.AppUtils; 18 | import com.amrendra.codefiesta.utils.CustomDate; 19 | import com.amrendra.codefiesta.utils.DateUtils; 20 | import com.bumptech.glide.Glide; 21 | 22 | import butterknife.Bind; 23 | import butterknife.ButterKnife; 24 | 25 | /** 26 | * Created by Amrendra Kumar on 10/04/16. 27 | */ 28 | public class ContestAdapter extends CursorAdapter { 29 | 30 | final LayoutInflater mInflator; 31 | Context mContext; 32 | 33 | public ContestAdapter(Context context, Cursor c, int flags) { 34 | super(context, c, flags); 35 | mInflator = LayoutInflater.from(context); 36 | mContext = context; 37 | } 38 | 39 | @Override 40 | public View newView(Context context, Cursor cursor, ViewGroup parent) { 41 | View mItem = mInflator.inflate(R.layout.contest_list_item, parent, false); 42 | ViewHolder mHolder = new ViewHolder(mItem); 43 | mItem.setTag(mHolder); 44 | return mItem; 45 | } 46 | 47 | @Override 48 | public void bindView(View view, Context context, Cursor cursor) { 49 | final ViewHolder mHolder = (ViewHolder) view.getTag(); 50 | final Contest contest = Contest.cursorToContest(mContext, cursor); 51 | mHolder.contestTitleTv.setText(contest.getEvent()); 52 | final int resourceId = contest.getWebsite().getId(); 53 | String resourceName = AppUtils.getResourceName(context, resourceId); 54 | final String shortResourceName = AppUtils.getGoodResourceName(resourceName); 55 | mHolder.contestWebsiteTv.setText(shortResourceName); 56 | final long starTime = DateUtils.getEpochTime(contest.getStart()); 57 | final long endTime = DateUtils.getEpochTime(contest.getEnd()); 58 | final CustomDate startDate = new CustomDate(DateUtils.epochToDateTimeLocalShow(starTime)); 59 | final CustomDate endDate = new CustomDate(DateUtils.epochToDateTimeLocalShow(endTime)); 60 | 61 | mHolder.contestStartTime.setText(startDate.getTime()); 62 | mHolder.contestStartAmPm.setText(startDate.getAmPm()); 63 | mHolder.contestStartDate.setText(startDate.getDateMonthYear()); 64 | 65 | mHolder.contestEndTime.setText(endDate.getTime()); 66 | mHolder.contestEndAmPm.setText(endDate.getAmPm()); 67 | mHolder.contestEndDate.setText(endDate.getDateMonthYear()); 68 | 69 | mHolder.statusTv.setText(DateUtils.getTimeLeftForEnd(starTime, endTime)); 70 | 71 | Glide.with(mContext) 72 | .load(AppUtils.getImageForResource(resourceName)) 73 | .error(R.mipmap.ic_launcher) 74 | .placeholder(R.mipmap.ic_launcher) 75 | .crossFade() 76 | .into(mHolder.resourceImageView); 77 | 78 | mHolder.mCardView.setOnClickListener(new View.OnClickListener() { 79 | @Override 80 | public void onClick(View v) { 81 | BusProvider.getInstance().post(new ContestClickEvent(contest)); 82 | } 83 | }); 84 | } 85 | 86 | 87 | class ViewHolder { 88 | 89 | @Bind(R.id.card_view) 90 | CardView mCardView; 91 | @Bind(R.id.contest_title_tv) 92 | TextView contestTitleTv; 93 | @Bind(R.id.contest_website_tv) 94 | TextView contestWebsiteTv; 95 | @Bind(R.id.resource_logo) 96 | ImageView resourceImageView; 97 | @Bind(R.id.status_tv) 98 | TextView statusTv; 99 | 100 | @Bind(R.id.contest_start_time_tv) 101 | TextView contestStartTime; 102 | @Bind(R.id.contest_start_time_ampm) 103 | TextView contestStartAmPm; 104 | @Bind(R.id.contest_start_date_tv) 105 | TextView contestStartDate; 106 | 107 | @Bind(R.id.contest_end_time_tv) 108 | TextView contestEndTime; 109 | @Bind(R.id.contest_end_time_ampm) 110 | TextView contestEndAmPm; 111 | @Bind(R.id.contest_end_date_tv) 112 | TextView contestEndDate; 113 | 114 | public ViewHolder(View view) { 115 | ButterKnife.bind(this, view); 116 | } 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrendra/codefiesta/adapter/SelectionAdapter.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta.adapter; 2 | 3 | /** 4 | * Created by Amrendra Kumar on 11/04/16. 5 | */ 6 | 7 | import android.content.Context; 8 | import android.support.annotation.NonNull; 9 | import android.support.v4.content.ContextCompat; 10 | import android.support.v7.widget.RecyclerView; 11 | import android.view.LayoutInflater; 12 | import android.view.View; 13 | import android.view.ViewGroup; 14 | import android.widget.CheckBox; 15 | import android.widget.ImageView; 16 | import android.widget.LinearLayout; 17 | import android.widget.TextView; 18 | 19 | import com.amrendra.codefiesta.R; 20 | import com.amrendra.codefiesta.model.Website; 21 | import com.amrendra.codefiesta.utils.AppUtils; 22 | import com.amrendra.codefiesta.utils.Debug; 23 | import com.bumptech.glide.Glide; 24 | 25 | import java.util.ArrayList; 26 | import java.util.List; 27 | 28 | import butterknife.Bind; 29 | import butterknife.ButterKnife; 30 | 31 | 32 | /** 33 | * Created by Amrendra Kumar on 10/04/16. 34 | */ 35 | public class SelectionAdapter extends RecyclerView.Adapter { 36 | 37 | private List mWebsitesList = new ArrayList<>(); 38 | 39 | CompetitionSettingsChangedListener settingsChangedListener; 40 | 41 | Context mContext; 42 | 43 | public SelectionAdapter(Context context, List wlist, 44 | CompetitionSettingsChangedListener 45 | mListner) { 46 | mContext = context; 47 | this.mWebsitesList = wlist; 48 | settingsChangedListener = mListner; 49 | } 50 | 51 | @Override 52 | public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 53 | View v = LayoutInflater.from(parent.getContext()) 54 | .inflate(R.layout.select_item_row, parent, false); 55 | return new ViewHolder(v); 56 | } 57 | 58 | @Override 59 | public void onBindViewHolder(final ViewHolder holder, int position) { 60 | final Website website = mWebsitesList.get(position); 61 | final int show = website.getShow(); 62 | holder.checkBox.setChecked(show != 0); 63 | holder.resourceName.setText(AppUtils.getGoodResourceName(website.getName())); 64 | 65 | final int resourceId = website.getId(); 66 | 67 | Glide.with(mContext) 68 | .load(AppUtils.getImageForResource(website.getName())) 69 | .error(R.mipmap.ic_launcher) 70 | .placeholder(R.mipmap.ic_launcher) 71 | .crossFade() 72 | .into(holder.websiteLogo); 73 | 74 | if (position % 2 == 0) { 75 | holder.layout.setBackgroundColor(ContextCompat.getColor(mContext, R.color.colorPrimaryLight)); 76 | } else { 77 | holder.layout.setBackgroundColor(ContextCompat.getColor(mContext, R.color.green_50)); 78 | } 79 | holder.layout.setOnClickListener(new View.OnClickListener() { 80 | @Override 81 | public void onClick(View v) { 82 | updateCheckBox(holder.checkBox, resourceId, website); 83 | } 84 | }); 85 | } 86 | 87 | public void updateCheckBox(CheckBox cb, final int resourceId, final Website website) { 88 | int toShow; 89 | if (cb.isChecked()) { 90 | cb.setChecked(false); 91 | toShow = 0; 92 | } else { 93 | cb.setChecked(true); 94 | toShow = 1; 95 | } 96 | Debug.i("resource : " + resourceId + " change : " + toShow, false); 97 | settingsChangedListener.settingsChanged(resourceId, toShow); 98 | website.setShow(toShow); 99 | } 100 | 101 | @Override 102 | public int getItemCount() { 103 | return mWebsitesList.size(); 104 | } 105 | 106 | public void resetWebsiteList(@NonNull List data) { 107 | mWebsitesList = data; 108 | notifyDataSetChanged(); 109 | } 110 | 111 | @NonNull 112 | public List getWebsiteList() { 113 | return mWebsitesList; 114 | } 115 | 116 | public void clearWebsites() { 117 | if (!mWebsitesList.isEmpty()) { 118 | mWebsitesList.clear(); 119 | notifyDataSetChanged(); 120 | } 121 | } 122 | 123 | public interface CompetitionSettingsChangedListener { 124 | void settingsChanged(int competitionId, int want); 125 | } 126 | 127 | class ViewHolder extends RecyclerView.ViewHolder { 128 | @Bind(R.id.checkBox) 129 | CheckBox checkBox; 130 | @Bind(R.id.resource_name) 131 | TextView resourceName; 132 | 133 | @Bind(R.id.website_logo) 134 | ImageView websiteLogo; 135 | 136 | @Bind(R.id.linear_layout_settings) 137 | LinearLayout layout; 138 | 139 | public ViewHolder(View view) { 140 | super(view); 141 | ButterKnife.bind(this, view); 142 | } 143 | } 144 | } 145 | 146 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrendra/codefiesta/alarms/BootReceiver.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta.alarms; 2 | 3 | import android.app.AlarmManager; 4 | import android.app.PendingIntent; 5 | import android.content.BroadcastReceiver; 6 | import android.content.Context; 7 | import android.content.Intent; 8 | import android.database.Cursor; 9 | import android.net.Uri; 10 | 11 | import com.amrendra.codefiesta.db.DBContract; 12 | import com.amrendra.codefiesta.model.Contest; 13 | import com.amrendra.codefiesta.utils.AppUtils; 14 | import com.amrendra.codefiesta.utils.Debug; 15 | 16 | /** 17 | * Created by Amrendra Kumar on 09/05/16. 18 | */ 19 | public class BootReceiver extends BroadcastReceiver { 20 | @Override 21 | public void onReceive(Context context, Intent intent) { 22 | Debug.c(); 23 | // iterate over all notifications and set alarms 24 | Cursor cursor = context.getContentResolver().query( 25 | DBContract.NotificationEntry.CONTENT_URI_ALL_NOTIFICATIONS, 26 | DBContract.NotificationEntry.NOTIFICATION_PROJECTION, 27 | null, 28 | null, 29 | null 30 | ); 31 | if (cursor != null) { 32 | try { 33 | while (cursor.moveToNext()) { 34 | long notificationId = cursor.getLong(cursor.getColumnIndex(DBContract 35 | .NotificationEntry._ID)); 36 | long contestId = cursor.getLong(cursor.getColumnIndex(DBContract 37 | .NotificationEntry.NOTIFICATION_CONTEST_ID_COL)); 38 | long timeNotification = cursor.getLong(cursor.getColumnIndex(DBContract 39 | .NotificationEntry.NOTIFICATION_TIME_COL)); 40 | if (timeNotification > System.currentTimeMillis() / 1000) { 41 | Uri uri = DBContract.ContestEntry.buildContestUriWithId(contestId); 42 | Cursor contestCursor = context.getContentResolver().query( 43 | uri, 44 | null, 45 | null, 46 | null, 47 | null 48 | ); 49 | if (contestCursor != null) { 50 | try { 51 | if (contestCursor.moveToFirst()) { 52 | Contest contest = Contest.cursorToContest(context, contestCursor); 53 | addNotification(context, contest, timeNotification); 54 | } 55 | } finally { 56 | contestCursor.close(); 57 | } 58 | } 59 | } else { 60 | int deleted = context.getContentResolver().delete( 61 | DBContract.NotificationEntry.CONTENT_URI_ALL_NOTIFICATIONS, 62 | DBContract.NotificationEntry._ID + " = ?", 63 | new String[]{Long.toString(notificationId)} 64 | ); 65 | Debug.e("deleted : " + deleted, false); 66 | } 67 | } 68 | } finally { 69 | cursor.close(); 70 | } 71 | } 72 | } 73 | 74 | private void addNotification(Context context, Contest contest, long time) { 75 | Debug.e("time : " + time + " contest: " + contest.getEvent(), false); 76 | Intent alarmIntent = new Intent(context, NotificationAlarm.class); 77 | alarmIntent.putExtra(AppUtils.CONTEST_KEY, contest); 78 | PendingIntent pendingIntent = PendingIntent.getBroadcast(context, contest.getId(), 79 | alarmIntent, PendingIntent 80 | .FLAG_UPDATE_CURRENT); 81 | AlarmManager alarmManager = (AlarmManager) context.getSystemService 82 | (Context.ALARM_SERVICE); 83 | alarmManager.set(AlarmManager.RTC_WAKEUP, time * 1000, pendingIntent); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrendra/codefiesta/alarms/NotificationAlarm.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta.alarms; 2 | 3 | import android.app.Notification; 4 | import android.app.NotificationManager; 5 | import android.app.PendingIntent; 6 | import android.content.BroadcastReceiver; 7 | import android.content.Context; 8 | import android.content.Intent; 9 | import android.media.RingtoneManager; 10 | import android.os.Build; 11 | import android.support.v4.content.ContextCompat; 12 | import android.support.v7.app.NotificationCompat; 13 | import android.text.Html; 14 | import android.text.Spanned; 15 | 16 | import com.amrendra.codefiesta.R; 17 | import com.amrendra.codefiesta.db.DBContract; 18 | import com.amrendra.codefiesta.model.Contest; 19 | import com.amrendra.codefiesta.ui.activities.MainActivity; 20 | import com.amrendra.codefiesta.utils.AppUtils; 21 | import com.amrendra.codefiesta.utils.CustomDate; 22 | import com.amrendra.codefiesta.utils.DateUtils; 23 | import com.amrendra.codefiesta.utils.Debug; 24 | 25 | /** 26 | * Created by Amrendra Kumar on 08/05/16. 27 | */ 28 | public class NotificationAlarm extends BroadcastReceiver { 29 | 30 | @Override 31 | public void onReceive(Context context, Intent intent) { 32 | Contest contest = intent.getParcelableExtra(AppUtils.CONTEST_KEY); 33 | Debug.e(contest.getEvent(), false); 34 | Intent newIntent = new Intent(context, MainActivity.class); 35 | PendingIntent pIntent = PendingIntent.getActivity(context, 0, newIntent, 0); 36 | 37 | Notification n; 38 | 39 | final int resourceId = contest.getWebsite().getId(); 40 | String resourceName = AppUtils.getResourceName(context, resourceId); 41 | final String shortResourceName = AppUtils.getGoodResourceName(resourceName); 42 | 43 | final long starTime = DateUtils.getEpochTime(contest.getStart()); 44 | final CustomDate startDate = new CustomDate(DateUtils.epochToDateTimeLocalShow(starTime)); 45 | 46 | Spanned msg = Html.fromHtml(String.format(context.getString(R.string.notification_string), 47 | shortResourceName, startDate.getFullTime())); 48 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 49 | n = new NotificationCompat.Builder(context) 50 | .setTicker(context.getString(R.string.app_name)) 51 | .setContentTitle(contest.getEvent()) 52 | .setStyle(new NotificationCompat.BigTextStyle().bigText(msg)) 53 | .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)) 54 | .setContentText(msg) 55 | .setColor(ContextCompat.getColor(context, R.color.colorAccent)) 56 | .setSmallIcon(R.drawable.icon_notification) 57 | .setContentIntent(pIntent) 58 | .build(); 59 | } else { 60 | n = new NotificationCompat.Builder(context) 61 | .setTicker(context.getString(R.string.app_name)) 62 | .setContentTitle(contest.getEvent()) 63 | .setStyle(new NotificationCompat.BigTextStyle().bigText(msg)) 64 | .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)) 65 | .setContentText(msg) 66 | .setSmallIcon(R.mipmap.ic_launcher) 67 | .setContentIntent(pIntent) 68 | .build(); 69 | } 70 | 71 | NotificationManager notificationManager = 72 | (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); 73 | 74 | notificationManager.notify(contest.getId(), n); 75 | 76 | 77 | //delete the notification entry from db 78 | context.getContentResolver().delete( 79 | DBContract.NotificationEntry.CONTENT_URI_ALL_NOTIFICATIONS, 80 | DBContract.NotificationEntry.NOTIFICATION_CONTEST_ID_COL + " = ?", 81 | new String[]{Long.toString(contest.getId())} 82 | ); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrendra/codefiesta/bus/BusProvider.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta.bus; 2 | 3 | import com.squareup.otto.Bus; 4 | 5 | /** 6 | * Created by Amrendra Kumar on 07/05/16. 7 | */ 8 | public class BusProvider { 9 | 10 | private static final Bus BUS = new Bus(); 11 | 12 | public static Bus getInstance() { 13 | return BUS; 14 | } 15 | 16 | public BusProvider() { 17 | throw new IllegalStateException("BusProvider is singleton! Use static method getInstance instead"); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrendra/codefiesta/bus/events/CalendarPermissionGrantedEvent.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta.bus.events; 2 | 3 | /** 4 | * Created by Amrendra Kumar on 08/05/16. 5 | */ 6 | public final class CalendarPermissionGrantedEvent { 7 | public CalendarPermissionGrantedEvent() { 8 | 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrendra/codefiesta/bus/events/ContestClickEvent.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta.bus.events; 2 | 3 | import com.amrendra.codefiesta.model.Contest; 4 | 5 | /** 6 | * Created by Amrendra Kumar on 07/05/16. 7 | */ 8 | public final class ContestClickEvent { 9 | Contest contest; 10 | 11 | public ContestClickEvent(Contest contest) { 12 | this.contest = contest; 13 | } 14 | 15 | public Contest getContest() { 16 | return contest; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrendra/codefiesta/bus/events/SettingsSaveEvent.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta.bus.events; 2 | 3 | /** 4 | * Created by amrendrk on 5/15/16. 5 | */ 6 | public class SettingsSaveEvent { 7 | public SettingsSaveEvent() { 8 | 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrendra/codefiesta/bus/events/SnackBarMessageDetailFragmentEvent.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta.bus.events; 2 | 3 | /** 4 | * Created by Amrendra Kumar on 08/05/16. 5 | */ 6 | public class SnackBarMessageDetailFragmentEvent { 7 | String msg; 8 | 9 | public SnackBarMessageDetailFragmentEvent(String msg) { 10 | this.msg = msg; 11 | } 12 | 13 | public String getMsg() { 14 | return msg; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrendra/codefiesta/db/DBContract.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta.db; 2 | 3 | import android.content.ContentResolver; 4 | import android.content.ContentUris; 5 | import android.net.Uri; 6 | import android.provider.BaseColumns; 7 | 8 | /** 9 | * Created by Amrendra Kumar on 09/04/16. 10 | */ 11 | public class DBContract { 12 | 13 | public static final String CONTENT_AUTHORITY = "com.amrendra.codefiesta"; 14 | public static Uri BASE_CONTENT_URI = Uri.parse("content://" + CONTENT_AUTHORITY); 15 | 16 | public static final String PATH_RESOURCE = "resource"; 17 | public static final String PATH_CONTEST = "contests"; 18 | public static final String PATH_NOTIFICATION = "notifications"; 19 | public static final String PATH_CALENDAR = "calendar"; 20 | public static final String PATH_LIVE = "live"; 21 | public static final String PATH_FUTURE = "future"; 22 | public static final String PATH_PAST = "past"; 23 | 24 | 25 | public static final class ResourceEntry implements BaseColumns { 26 | public static final String TABLE_NAME = "resources_table"; 27 | 28 | public static final Uri CONTENT_URI_ALL = 29 | BASE_CONTENT_URI.buildUpon().appendPath(PATH_RESOURCE).build(); 30 | 31 | public static final String CONTENT_DIR_TYPE = 32 | ContentResolver.CURSOR_DIR_BASE_TYPE + "/" + CONTENT_AUTHORITY + "/" + PATH_RESOURCE; 33 | 34 | public static final String CONTENT_ITEM_TYPE = 35 | ContentResolver.CURSOR_ITEM_BASE_TYPE + "/" + CONTENT_AUTHORITY + "/" + PATH_RESOURCE; 36 | 37 | public static final String RESOURCE_ID_COL = "rid"; 38 | public static final String RESOURCE_NAME_COL = "rname"; 39 | public static final String RESOURCE_SHOW_COL = "show"; 40 | 41 | public static final String[] RESOURCE_PROJECTION = new String[]{ 42 | _ID, 43 | RESOURCE_ID_COL, 44 | RESOURCE_NAME_COL, 45 | RESOURCE_SHOW_COL 46 | }; 47 | } 48 | 49 | public static final class ContestEntry implements BaseColumns { 50 | public static final String TABLE_NAME = "contests_table"; 51 | 52 | public static final Uri CONTENT_URI_ALL = 53 | BASE_CONTENT_URI.buildUpon().appendPath(PATH_CONTEST).build(); 54 | 55 | public static Uri buildContestUriWithId(long id) { 56 | return ContentUris.withAppendedId(CONTENT_URI_ALL, id); 57 | } 58 | 59 | public static long getIdFromContestUri(Uri uri) { 60 | return ContentUris.parseId(uri); 61 | } 62 | 63 | public static final Uri CONTENT_URI_LIVE = 64 | CONTENT_URI_ALL.buildUpon().appendPath(PATH_LIVE).build(); 65 | 66 | public static Uri buildLiveContestUri(long id) { 67 | return ContentUris.withAppendedId(CONTENT_URI_LIVE, id); 68 | } 69 | 70 | public static final Uri CONTENT_URI_FUTURE = 71 | CONTENT_URI_ALL.buildUpon().appendPath(PATH_FUTURE).build(); 72 | 73 | public static Uri buildFutureContestUri(long id) { 74 | return ContentUris.withAppendedId(CONTENT_URI_FUTURE, id); 75 | } 76 | 77 | public static final Uri CONTENT_URI_PAST = 78 | CONTENT_URI_ALL.buildUpon().appendPath(PATH_PAST).build(); 79 | 80 | public static Uri buildPastContestUri(long id) { 81 | return ContentUris.withAppendedId(CONTENT_URI_PAST, id); 82 | } 83 | 84 | public static long getTimeFromContestUri(Uri uri) { 85 | return ContentUris.parseId(uri); 86 | } 87 | 88 | public static final String CONTENT_DIR_TYPE = 89 | ContentResolver.CURSOR_DIR_BASE_TYPE + "/" + CONTENT_AUTHORITY + "/" + PATH_CONTEST; 90 | 91 | public static final String CONTENT_ITEM_TYPE = 92 | ContentResolver.CURSOR_ITEM_BASE_TYPE + "/" + CONTENT_AUTHORITY + "/" + PATH_CONTEST; 93 | 94 | public static final String CONTEST_ID_COL = "cid"; 95 | public static final String CONTEST_NAME_COL = "name"; 96 | public static final String CONTEST_URL_COL = "url"; 97 | public static final String CONTEST_RESOURCE_ID_COL = "resource_id"; 98 | public static final String CONTEST_START_COL = "start"; 99 | public static final String CONTEST_END_COL = "end"; 100 | public static final String CONTEST_DURATION_COL = "duration"; 101 | 102 | 103 | public static final String[] CONTEST_PROJECTION = new String[]{ 104 | _ID, 105 | CONTEST_ID_COL, 106 | CONTEST_NAME_COL, 107 | CONTEST_URL_COL, 108 | CONTEST_RESOURCE_ID_COL, 109 | CONTEST_START_COL, 110 | CONTEST_END_COL, 111 | CONTEST_DURATION_COL 112 | }; 113 | 114 | } 115 | 116 | public static final class NotificationEntry implements BaseColumns { 117 | public static final String TABLE_NAME = "notifications_table"; 118 | 119 | public static final Uri CONTENT_URI_ALL_NOTIFICATIONS = 120 | BASE_CONTENT_URI.buildUpon().appendPath(PATH_NOTIFICATION).build(); 121 | 122 | public static Uri buildNotificationEventUriWithContestId(long id) { 123 | return ContentUris.withAppendedId(CONTENT_URI_ALL_NOTIFICATIONS, id); 124 | } 125 | 126 | public static long getContestIdFromNotificationEventUri(Uri uri) { 127 | return ContentUris.parseId(uri); 128 | } 129 | 130 | public static final String CONTENT_DIR_TYPE = 131 | ContentResolver.CURSOR_DIR_BASE_TYPE + "/" + CONTENT_AUTHORITY + "/" + PATH_NOTIFICATION; 132 | 133 | public static final String CONTENT_ITEM_TYPE = 134 | ContentResolver.CURSOR_ITEM_BASE_TYPE + "/" + CONTENT_AUTHORITY + "/" + PATH_NOTIFICATION; 135 | 136 | public static final String NOTIFICATION_CONTEST_ID_COL = "contest_id"; 137 | public static final String NOTIFICATION_TIME_COL = "notify_time"; 138 | public static final String NOTIFICATION_CONTEST_START_TIME_COL = "start_time"; 139 | 140 | public static final String[] NOTIFICATION_PROJECTION = new String[]{ 141 | _ID, 142 | NOTIFICATION_CONTEST_ID_COL, 143 | NOTIFICATION_TIME_COL, 144 | NOTIFICATION_CONTEST_START_TIME_COL 145 | }; 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrendra/codefiesta/db/DBHelper.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta.db; 2 | 3 | import android.content.Context; 4 | import android.database.DatabaseErrorHandler; 5 | import android.database.sqlite.SQLiteDatabase; 6 | import android.database.sqlite.SQLiteOpenHelper; 7 | 8 | import com.amrendra.codefiesta.utils.Debug; 9 | 10 | /** 11 | * Created by Amrendra Kumar on 09/04/16. 12 | */ 13 | public class DBHelper extends SQLiteOpenHelper { 14 | 15 | public static final int DB_VERSION = 1; 16 | public static final String DB_NAME = "codefiesta.db"; 17 | 18 | public static final String SQL_CREATE_TABLE_RESOURCE = 19 | "CREATE TABLE " + DBContract.ResourceEntry.TABLE_NAME + " (" 20 | + DBContract.ResourceEntry._ID + " INTEGER PRIMARY KEY," 21 | + DBContract.ResourceEntry.RESOURCE_ID_COL + " INTEGER NOT NULL," 22 | + DBContract.ResourceEntry.RESOURCE_NAME_COL + " TEXT NOT NULL," 23 | + DBContract.ResourceEntry.RESOURCE_SHOW_COL + " INTEGER NOT NULL," 24 | + " UNIQUE (" + DBContract.ResourceEntry.RESOURCE_ID_COL + ") ON CONFLICT IGNORE" 25 | + " );"; 26 | 27 | public static final String SQL_CREATE_TABLE_CONTESTS = 28 | "CREATE TABLE " + DBContract.ContestEntry.TABLE_NAME + " (" 29 | + DBContract.ContestEntry._ID + " INTEGER PRIMARY KEY," 30 | + DBContract.ContestEntry.CONTEST_ID_COL + " INTEGER NOT NULL," 31 | + DBContract.ContestEntry.CONTEST_NAME_COL + " TEXT NOT NULL," 32 | + DBContract.ContestEntry.CONTEST_URL_COL + " TEXT NOT NULL," 33 | + DBContract.ContestEntry.CONTEST_RESOURCE_ID_COL + " TEXT NOT NULL," 34 | + DBContract.ContestEntry.CONTEST_START_COL + " INTEGER NOT NULL," 35 | + DBContract.ContestEntry.CONTEST_END_COL + " INTEGER NOT NULL," 36 | + DBContract.ContestEntry.CONTEST_DURATION_COL + " INTEGER NOT NULL," 37 | + " UNIQUE (" + DBContract.ContestEntry.CONTEST_ID_COL + ") ON CONFLICT REPLACE" 38 | + " );"; 39 | 40 | public static final String SQL_CREATE_TABLE_NOTIFICATIONS = 41 | "CREATE TABLE " + DBContract.NotificationEntry.TABLE_NAME + " (" 42 | + DBContract.NotificationEntry._ID + " INTEGER PRIMARY KEY," 43 | + DBContract.NotificationEntry.NOTIFICATION_CONTEST_ID_COL + " INTEGER NOT NULL," 44 | + DBContract.NotificationEntry.NOTIFICATION_TIME_COL + " INTEGER NOT NULL," 45 | + DBContract.NotificationEntry.NOTIFICATION_CONTEST_START_TIME_COL + " INTEGER NOT NULL," 46 | + " UNIQUE (" + DBContract.NotificationEntry._ID + ") ON CONFLICT REPLACE" 47 | + " );"; 48 | 49 | 50 | public DBHelper(Context context) { 51 | super(context, DB_NAME, null, DB_VERSION); 52 | Debug.c(); 53 | } 54 | 55 | public DBHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) { 56 | super(context, name, factory, version); 57 | } 58 | 59 | public DBHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version, DatabaseErrorHandler errorHandler) { 60 | super(context, name, factory, version, errorHandler); 61 | } 62 | 63 | @Override 64 | public void onCreate(SQLiteDatabase db) { 65 | Debug.c(); 66 | db.execSQL(SQL_CREATE_TABLE_RESOURCE); 67 | db.execSQL(SQL_CREATE_TABLE_CONTESTS); 68 | db.execSQL(SQL_CREATE_TABLE_NOTIFICATIONS); 69 | 70 | } 71 | 72 | @Override 73 | public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 74 | Debug.c(); 75 | db.execSQL("DROP TABLE IF EXISTS " + DBContract.ResourceEntry.TABLE_NAME); 76 | db.execSQL("DROP TABLE IF EXISTS " + DBContract.ContestEntry.TABLE_NAME); 77 | db.execSQL("DROP TABLE IF EXISTS " + DBContract.NotificationEntry.TABLE_NAME); 78 | onCreate(db); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrendra/codefiesta/handler/DBQueryHandler.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta.handler; 2 | 3 | import android.content.AsyncQueryHandler; 4 | import android.content.ContentResolver; 5 | import android.database.Cursor; 6 | import android.net.Uri; 7 | 8 | import java.lang.ref.WeakReference; 9 | 10 | /** 11 | * Created by Amrendra Kumar on 25/04/16. 12 | */ 13 | public class DBQueryHandler extends AsyncQueryHandler { 14 | 15 | private WeakReference mListener; 16 | 17 | public DBQueryHandler(ContentResolver cr, OnQueryCompleteListener listener) { 18 | super(cr); 19 | this.mListener = new WeakReference<>(listener); 20 | } 21 | 22 | @Override 23 | protected void onQueryComplete(int token, Object cookie, Cursor cursor) { 24 | if (mListener != null && mListener.get() != null) { 25 | mListener.get().onQueryComplete(token, cursor); 26 | } else { 27 | if (cursor != null) { 28 | cursor.close(); 29 | } 30 | } 31 | } 32 | 33 | @Override 34 | protected void onInsertComplete(int token, Object cookie, Uri uri) { 35 | if (mListener != null && mListener.get() != null) { 36 | mListener.get().onInsertComplete(token, uri); 37 | } 38 | } 39 | 40 | @Override 41 | protected void onUpdateComplete(int token, Object cookie, int result) { 42 | if (mListener != null && mListener.get() != null) { 43 | mListener.get().onUpdateComplete(token, result); 44 | } 45 | } 46 | 47 | @Override 48 | protected void onDeleteComplete(int token, Object cookie, int result) { 49 | if (mListener != null && mListener.get() != null) { 50 | mListener.get().onDeleteComplete(token, result); 51 | } 52 | } 53 | 54 | public interface OnQueryCompleteListener { 55 | void onQueryComplete(int token, Cursor cursor); 56 | 57 | void onInsertComplete(int token, Uri uri); 58 | 59 | void onDeleteComplete(int token, int result); 60 | 61 | void onUpdateComplete(int token, int result); 62 | } 63 | } 64 | 65 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrendra/codefiesta/loaders/BaseLoader.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta.loaders; 2 | 3 | import android.content.Context; 4 | import android.support.v4.content.AsyncTaskLoader; 5 | 6 | /** 7 | * Created by Amrendra Kumar on 06/04/16. 8 | */ 9 | public abstract class BaseLoader extends AsyncTaskLoader { 10 | 11 | private T mData; 12 | 13 | public BaseLoader(Context context) { 14 | super(context); 15 | } 16 | 17 | @Override 18 | public void deliverResult(T data) { 19 | if (isReset()) { 20 | releaseResources(data); 21 | return; 22 | } 23 | 24 | T oldData = mData; 25 | mData = data; 26 | 27 | if (isStarted()) { 28 | super.deliverResult(data); 29 | } 30 | 31 | if (oldData != null && oldData != data) { 32 | releaseResources(oldData); 33 | } 34 | } 35 | 36 | private void releaseResources(T oldData) { 37 | } 38 | 39 | @Override 40 | protected void onStartLoading() { 41 | if (mData != null) { 42 | deliverResult(mData); 43 | } 44 | 45 | if (takeContentChanged() || mData == null) { 46 | forceLoad(); 47 | } 48 | } 49 | 50 | 51 | @Override 52 | protected void onStopLoading() { 53 | cancelLoad(); 54 | } 55 | 56 | @Override 57 | protected void onReset() { 58 | onStopLoading(); 59 | if (mData != null) { 60 | releaseResources(mData); 61 | mData = null; 62 | } 63 | } 64 | 65 | @Override 66 | public void onCanceled(T data) { 67 | super.onCanceled(data); 68 | releaseResources(data); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrendra/codefiesta/loaders/ResourceSettingLoader.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta.loaders; 2 | 3 | import android.content.Context; 4 | import android.database.Cursor; 5 | 6 | import com.amrendra.codefiesta.db.DBContract; 7 | import com.amrendra.codefiesta.model.Website; 8 | import com.amrendra.codefiesta.utils.Debug; 9 | 10 | import java.util.List; 11 | 12 | /** 13 | * Created by Amrendra Kumar on 17/04/16. 14 | */ 15 | public class ResourceSettingLoader extends BaseLoader> { 16 | 17 | public ResourceSettingLoader(Context context) { 18 | super(context); 19 | } 20 | 21 | @Override 22 | public List loadInBackground() { 23 | Debug.c(); 24 | Cursor cursor = getContext().getContentResolver().query( 25 | DBContract.ResourceEntry.CONTENT_URI_ALL, 26 | DBContract.ResourceEntry.RESOURCE_PROJECTION, 27 | null, 28 | null, 29 | null 30 | ); 31 | 32 | List list = Website.cursorToList(cursor); 33 | if (cursor != null && !cursor.isClosed()) { 34 | cursor.close(); 35 | } 36 | return list; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrendra/codefiesta/model/ApiResponse.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta.model; 2 | 3 | /** 4 | * Created by Amrendra Kumar on 07/04/16. 5 | */ 6 | public class ApiResponse { 7 | 8 | Error error; 9 | T content; 10 | 11 | public ApiResponse() { 12 | error = new Error(); 13 | } 14 | 15 | public Error getError() { 16 | return error; 17 | } 18 | 19 | public T getContent() { 20 | return content; 21 | } 22 | 23 | public void setContent(T content) { 24 | this.content = content; 25 | } 26 | 27 | public void setError(Error error) { 28 | this.error = error; 29 | } 30 | 31 | @Override 32 | public String toString() { 33 | return "ApiResponse:" + error.toString(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrendra/codefiesta/model/Error.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta.model; 2 | 3 | /** 4 | * Created by Amrendra Kumar on 07/12/15. 5 | */ 6 | public class Error { 7 | 8 | public static final int CONNECTION_ERROR = -100; 9 | public static final int UNKNOWN_ERROR = -200; 10 | public static final int SUCCESS = 200; 11 | 12 | private int code; 13 | private String description; 14 | 15 | public Error() { 16 | code = SUCCESS; 17 | description = "Success"; 18 | } 19 | 20 | public Error(int code, String description) { 21 | this.code = code; 22 | this.description = description; 23 | } 24 | 25 | public void setCode(int code) { 26 | this.code = code; 27 | } 28 | 29 | public void setDescription(String description) { 30 | this.description = description; 31 | } 32 | 33 | public String getDescription() { 34 | return description; 35 | } 36 | 37 | public int getCode() { 38 | return code; 39 | } 40 | 41 | @Override 42 | public String toString() { 43 | return "Error[" + code + ": " + description + "]"; 44 | } 45 | } -------------------------------------------------------------------------------- /app/src/main/java/com/amrendra/codefiesta/model/Meta.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta.model; 2 | 3 | import android.os.Parcel; 4 | import android.os.Parcelable; 5 | 6 | import com.google.gson.annotations.SerializedName; 7 | 8 | /** 9 | * Created by Amrendra Kumar on 06/04/16. 10 | */ 11 | public class Meta implements Parcelable { 12 | 13 | int limit; 14 | String next; 15 | int offset; 16 | String previous; 17 | 18 | @SerializedName("total_count") 19 | long totalCount; 20 | 21 | 22 | protected Meta(Parcel in) { 23 | limit = in.readInt(); 24 | next = in.readString(); 25 | offset = in.readInt(); 26 | previous = in.readString(); 27 | totalCount = in.readLong(); 28 | } 29 | 30 | public static final Creator CREATOR = new Creator() { 31 | @Override 32 | public Meta createFromParcel(Parcel in) { 33 | return new Meta(in); 34 | } 35 | 36 | @Override 37 | public Meta[] newArray(int size) { 38 | return new Meta[size]; 39 | } 40 | }; 41 | 42 | public int getLimit() { 43 | return limit; 44 | } 45 | 46 | public void setLimit(int limit) { 47 | this.limit = limit; 48 | } 49 | 50 | public String getNext() { 51 | return next; 52 | } 53 | 54 | public void setNext(String next) { 55 | this.next = next; 56 | } 57 | 58 | public int getOffset() { 59 | return offset; 60 | } 61 | 62 | public void setOffset(int offset) { 63 | this.offset = offset; 64 | } 65 | 66 | public String getPrevious() { 67 | return previous; 68 | } 69 | 70 | public void setPrevious(String previous) { 71 | this.previous = previous; 72 | } 73 | 74 | public long getTotalCount() { 75 | return totalCount; 76 | } 77 | 78 | public void setTotalCount(long totalCount) { 79 | this.totalCount = totalCount; 80 | } 81 | 82 | @Override 83 | public int describeContents() { 84 | return 0; 85 | } 86 | 87 | @Override 88 | public void writeToParcel(Parcel dest, int flags) { 89 | dest.writeInt(limit); 90 | dest.writeString(next); 91 | dest.writeInt(offset); 92 | dest.writeString(previous); 93 | dest.writeLong(totalCount); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrendra/codefiesta/model/Website.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta.model; 2 | 3 | import android.content.ContentValues; 4 | import android.database.Cursor; 5 | import android.os.Parcel; 6 | import android.os.Parcelable; 7 | 8 | import com.amrendra.codefiesta.db.DBContract; 9 | import com.google.gson.annotations.Expose; 10 | import com.google.gson.annotations.SerializedName; 11 | 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | 15 | /** 16 | * Created by Amrendra Kumar on 06/04/16. 17 | */ 18 | public class Website implements Parcelable { 19 | int id; 20 | String name; 21 | 22 | int show = 1; 23 | 24 | public Website() { 25 | 26 | } 27 | 28 | public static final Creator CREATOR = new Creator() { 29 | @Override 30 | public Website createFromParcel(Parcel in) { 31 | return new Website(in); 32 | } 33 | 34 | @Override 35 | public Website[] newArray(int size) { 36 | return new Website[size]; 37 | } 38 | }; 39 | 40 | @Override 41 | public int describeContents() { 42 | return 0; 43 | } 44 | 45 | @Override 46 | public void writeToParcel(Parcel dest, int flags) { 47 | dest.writeInt(id); 48 | dest.writeString(name); 49 | dest.writeInt(show); 50 | } 51 | 52 | protected Website(Parcel in) { 53 | id = in.readInt(); 54 | name = in.readString(); 55 | show = in.readInt(); 56 | } 57 | 58 | public int getId() { 59 | return id; 60 | } 61 | 62 | public void setId(int id) { 63 | this.id = id; 64 | } 65 | 66 | public String getName() { 67 | return name; 68 | } 69 | 70 | public void setName(String name) { 71 | this.name = name; 72 | } 73 | 74 | public int getShow() { 75 | return show; 76 | } 77 | 78 | public void setShow(int show) { 79 | this.show = show; 80 | } 81 | 82 | @Override 83 | public String toString() { 84 | return "Website[" + getName() + " id:" + getId() + " show:" + getShow() + "]\n"; 85 | } 86 | 87 | public ContentValues getContentValues() { 88 | ContentValues value = new ContentValues(); 89 | value.put(DBContract.ResourceEntry.RESOURCE_ID_COL, getId()); 90 | value.put(DBContract.ResourceEntry.RESOURCE_NAME_COL, getName()); 91 | value.put(DBContract.ResourceEntry.RESOURCE_SHOW_COL, getShow()); 92 | return value; 93 | } 94 | 95 | public static final class Response { 96 | 97 | @Expose 98 | @SerializedName("meta") 99 | public Meta meta; 100 | 101 | @Expose 102 | @SerializedName("objects") 103 | public List websites = new ArrayList<>(); 104 | } 105 | 106 | public static ArrayList cursorToList(Cursor cursor) { 107 | ArrayList list = new ArrayList<>(); 108 | if (cursor != null) { 109 | try { 110 | while (cursor.moveToNext()) { 111 | int id = cursor.getInt(cursor.getColumnIndex(DBContract.ResourceEntry 112 | .RESOURCE_ID_COL)); 113 | String name = cursor.getString(cursor.getColumnIndex(DBContract.ResourceEntry 114 | .RESOURCE_NAME_COL)); 115 | int show = cursor.getInt(cursor.getColumnIndex(DBContract.ResourceEntry 116 | .RESOURCE_SHOW_COL)); 117 | Website website = new Website(); 118 | website.setId(id); 119 | website.setName(name); 120 | website.setShow(show); 121 | list.add(website); 122 | } 123 | } finally { 124 | cursor.close(); 125 | } 126 | } 127 | return list; 128 | } 129 | 130 | ; 131 | } 132 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrendra/codefiesta/rest/RestApiClient.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta.rest; 2 | 3 | import retrofit.GsonConverterFactory; 4 | import retrofit.Retrofit; 5 | import retrofit.RxJavaCallAdapterFactory; 6 | 7 | /** 8 | * Created by Amrendra Kumar on 06/04/16. 9 | */ 10 | public class RestApiClient { 11 | public static final String API_BASE_URL = "http://clist.by:80/"; 12 | 13 | private static RestApiService restApiService = null; 14 | 15 | private RestApiClient() { 16 | } 17 | 18 | public static RestApiService getInstance() { 19 | if (restApiService == null) { 20 | Retrofit retrofit = new Retrofit.Builder() 21 | .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 22 | .baseUrl(API_BASE_URL) 23 | .addConverterFactory(GsonConverterFactory.create()) 24 | .build(); 25 | restApiService = retrofit.create(RestApiService.class); 26 | } 27 | return restApiService; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrendra/codefiesta/rest/RestApiService.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta.rest; 2 | 3 | import com.amrendra.codefiesta.model.Contest; 4 | import com.amrendra.codefiesta.model.Website; 5 | 6 | import retrofit.http.GET; 7 | import retrofit.http.Path; 8 | import retrofit.http.Query; 9 | import rx.Observable; 10 | 11 | /** 12 | * Created by Amrendra Kumar on 06/04/16. 13 | */ 14 | public interface RestApiService { 15 | 16 | @GET("/api/v1/contest/") 17 | Observable getContestsList( 18 | @Query("limit") int limit, 19 | @Query("end__gt") String date, 20 | @Query("order_by") String orderBy, 21 | @Query("username") String userName, 22 | @Query("api_key") String userKey 23 | ); 24 | 25 | @GET("/api/v1/contest/{id}/") 26 | Observable getContestsById( 27 | @Path("id") int id, 28 | @Query("username") String userName, 29 | @Query("api_key") String userKey 30 | ); 31 | 32 | @GET("/api/v1/resource/") 33 | Observable getResourceList( 34 | @Query("username") String userName, 35 | @Query("api_key") String userKey 36 | ); 37 | 38 | @GET("/api/v1/resource/{id}/") 39 | Observable getResourceById( 40 | @Path("id") int id, 41 | @Query("username") String userName, 42 | @Query("api_key") String userKey 43 | ); 44 | 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrendra/codefiesta/sync/CodeFiestaAuthenticatorService.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta.sync; 2 | 3 | import android.app.Service; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.os.IBinder; 7 | import android.support.annotation.Nullable; 8 | 9 | /** 10 | * Created by Amrendra Kumar on 09/04/16. 11 | */ 12 | public class CodeFiestaAuthenticatorService extends Service { 13 | 14 | private CodeFiestaAuthenticator mAuthenticator; 15 | 16 | @Override 17 | public void onCreate() { 18 | mAuthenticator = new CodeFiestaAuthenticator(this); 19 | } 20 | 21 | /** 22 | * Return the communication channel to the service. May return null if 23 | * clients can not bind to the service. The returned 24 | * {@link IBinder} is usually for a complex interface 25 | * that has been described using 26 | * aidl. 27 | *

28 | *

Note that unlike other application components, calls on to the 29 | * IBinder interface returned here may not happen on the main thread 30 | * of the process. More information about the main thread can be found in 31 | * Processes and 32 | * Threads.

33 | * 34 | * @param intent The Intent that was used to bind to this service, 35 | * as given to {@link Context#bindService 36 | * Context.bindService}. Note that any extras that were included with 37 | * the Intent at that point will not be seen here. 38 | * @return Return an IBinder through which clients can call on to the 39 | * service. 40 | */ 41 | @Nullable 42 | @Override 43 | public IBinder onBind(Intent intent) { 44 | return mAuthenticator.getIBinder(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrendra/codefiesta/sync/CodeFiestaSyncService.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta.sync; 2 | 3 | import android.app.Service; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.os.IBinder; 7 | import android.support.annotation.Nullable; 8 | 9 | /** 10 | * Created by Amrendra Kumar on 09/04/16. 11 | */ 12 | public class CodeFiestaSyncService extends Service { 13 | 14 | private static final Object mSyncAdapterLock = new Object(); 15 | private static CodeFiestaSyncAdapter mCodeFiestaSyncAdapter = null; 16 | 17 | @Override 18 | public void onCreate() { 19 | synchronized (mSyncAdapterLock) { 20 | if (mCodeFiestaSyncAdapter == null) { 21 | mCodeFiestaSyncAdapter = new CodeFiestaSyncAdapter(getApplicationContext(), true); 22 | } 23 | } 24 | } 25 | 26 | /** 27 | * Return the communication channel to the service. May return null if 28 | * clients can not bind to the service. The returned 29 | * {@link IBinder} is usually for a complex interface 30 | * that has been described using 31 | * aidl. 32 | *

33 | *

Note that unlike other application components, calls on to the 34 | * IBinder interface returned here may not happen on the main thread 35 | * of the process. More information about the main thread can be found in 36 | * Processes and 37 | * Threads.

38 | * 39 | * @param intent The Intent that was used to bind to this service, 40 | * as given to {@link Context#bindService 41 | * Context.bindService}. Note that any extras that were included with 42 | * the Intent at that point will not be seen here. 43 | * @return Return an IBinder through which clients can call on to the 44 | * service. 45 | */ 46 | @Nullable 47 | @Override 48 | public IBinder onBind(Intent intent) { 49 | return mCodeFiestaSyncAdapter.getSyncAdapterBinder(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrendra/codefiesta/ui/activities/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta.ui.activities; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.LayoutRes; 5 | import android.support.annotation.Nullable; 6 | import android.support.v7.app.AppCompatActivity; 7 | 8 | import com.amrendra.codefiesta.CodeFiestaApplication; 9 | import com.amrendra.codefiesta.bus.BusProvider; 10 | import com.google.android.gms.analytics.HitBuilders; 11 | import com.google.android.gms.analytics.Tracker; 12 | 13 | /** 14 | * Created by Amrendra Kumar on 05/04/16. 15 | */ 16 | public abstract class BaseActivity extends AppCompatActivity { 17 | 18 | Tracker mTracker; 19 | 20 | @Override 21 | protected void onCreate(@Nullable Bundle savedInstanceState) { 22 | super.onCreate(savedInstanceState); 23 | CodeFiestaApplication application = (CodeFiestaApplication) getApplication(); 24 | mTracker = application.getDefaultTracker(); 25 | application.checkAndSync(); 26 | BusProvider.getInstance().register(this); 27 | } 28 | 29 | @Override 30 | public void setContentView(@LayoutRes int layoutResID) { 31 | super.setContentView(layoutResID); 32 | } 33 | 34 | @Override 35 | protected void onDestroy() { 36 | super.onDestroy(); 37 | BusProvider.getInstance().unregister(this); 38 | } 39 | 40 | protected void trackActivity(String screenName) { 41 | mTracker.setScreenName(screenName); 42 | mTracker.send(new HitBuilders.ScreenViewBuilder().build()); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrendra/codefiesta/ui/activities/SplashScreenActivity.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta.ui.activities; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.support.v4.view.ViewCompat; 6 | import android.support.v4.view.ViewPropertyAnimatorCompat; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | import android.view.animation.DecelerateInterpolator; 10 | import android.widget.ImageView; 11 | import android.widget.LinearLayout; 12 | 13 | import com.amrendra.codefiesta.R; 14 | import com.amrendra.codefiesta.utils.Debug; 15 | import com.amrendra.codefiesta.utils.TrackingConstants; 16 | 17 | import butterknife.Bind; 18 | import butterknife.ButterKnife; 19 | 20 | /** 21 | * Created by Amrendra Kumar on 05/04/16. 22 | */ 23 | public class SplashScreenActivity extends BaseActivity { 24 | 25 | public static final int STARTUP_DELAY = 150; 26 | public static final int ANIM_ITEM_DURATION = 1000; 27 | public static final int ITEM_DELAY = 250; 28 | public static final int ITEM_DELAY_OFFSET = 400; 29 | public static final int ANIM_TEXT_DURATION = 1000; 30 | public static final int LOGO_Y_TRANSLATION = -150; 31 | public static final int TEXT_Y_TRANSLATION = 50; 32 | 33 | private boolean animationStarted = false; 34 | 35 | @Bind(R.id.img_logo) 36 | ImageView logoImageView; 37 | 38 | @Bind(R.id.container) 39 | LinearLayout linearLayoutContainer; 40 | 41 | @Override 42 | protected void onCreate(Bundle savedInstanceState) { 43 | super.onCreate(savedInstanceState); 44 | Debug.c(); 45 | getWindow().getDecorView().setSystemUiVisibility( 46 | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 47 | | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION); 48 | setContentView(R.layout.splash_activity); 49 | ButterKnife.bind(this); 50 | } 51 | 52 | private void startMainListActivity() { 53 | Intent intent = new Intent(this, MainActivity.class); 54 | startActivity(intent); 55 | finish(); 56 | } 57 | 58 | 59 | @Override 60 | public void onWindowFocusChanged(boolean hasFocus) { 61 | if (!hasFocus || animationStarted) { 62 | return; 63 | } 64 | animate(); 65 | super.onWindowFocusChanged(hasFocus); 66 | } 67 | 68 | private void animate() { 69 | animationStarted = true; 70 | ViewGroup container = linearLayoutContainer; 71 | ViewCompat.animate(logoImageView) 72 | .translationY(LOGO_Y_TRANSLATION) 73 | .setStartDelay(STARTUP_DELAY) 74 | .setDuration(ANIM_ITEM_DURATION).setInterpolator( 75 | new DecelerateInterpolator(1.2f)).start(); 76 | 77 | for (int i = 0; i < container.getChildCount(); i++) { 78 | View v = container.getChildAt(i); 79 | ViewPropertyAnimatorCompat viewAnimator = ViewCompat.animate(v) 80 | .translationY(TEXT_Y_TRANSLATION).alpha(1) 81 | .setStartDelay((ITEM_DELAY * i) + ITEM_DELAY_OFFSET) 82 | .setDuration(ANIM_TEXT_DURATION); 83 | 84 | if (v.getId() == R.id.hello_world_tv) { 85 | viewAnimator.withEndAction(runnable); 86 | } 87 | viewAnimator.setInterpolator(new DecelerateInterpolator()).start(); 88 | } 89 | } 90 | 91 | Runnable runnable = new Runnable() { 92 | @Override 93 | public void run() { 94 | startMainListActivity(); 95 | } 96 | }; 97 | 98 | @Override 99 | protected void onResume() { 100 | super.onResume(); 101 | trackActivity(TrackingConstants.SPLASH_ACTIVITY_SCREEN_NAME); 102 | } 103 | 104 | @Override 105 | protected void onDestroy() { 106 | super.onDestroy(); 107 | ButterKnife.unbind(this); 108 | } 109 | } -------------------------------------------------------------------------------- /app/src/main/java/com/amrendra/codefiesta/ui/fragments/BaseFragment.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta.ui.fragments; 2 | 3 | import android.database.Cursor; 4 | import android.os.Bundle; 5 | import android.os.Handler; 6 | import android.os.Looper; 7 | import android.support.annotation.Nullable; 8 | import android.support.v4.app.Fragment; 9 | import android.view.View; 10 | import android.widget.Toast; 11 | 12 | import com.amrendra.codefiesta.CodeFiestaApplication; 13 | import com.amrendra.codefiesta.bus.BusProvider; 14 | import com.amrendra.codefiesta.bus.events.ContestClickEvent; 15 | import com.amrendra.codefiesta.model.Contest; 16 | import com.amrendra.codefiesta.ui.activities.MainActivity; 17 | import com.amrendra.codefiesta.utils.Debug; 18 | import com.google.android.gms.analytics.HitBuilders; 19 | import com.google.android.gms.analytics.Tracker; 20 | 21 | /** 22 | * Created by Amrendra Kumar on 05/04/16. 23 | */ 24 | public abstract class BaseFragment extends Fragment { 25 | 26 | private Toast mToast; 27 | Tracker mTracker; 28 | 29 | @Override 30 | public void onCreate(@Nullable Bundle savedInstanceState) { 31 | super.onCreate(savedInstanceState); 32 | CodeFiestaApplication application = (CodeFiestaApplication) getActivity().getApplication(); 33 | mTracker = application.getDefaultTracker(); 34 | } 35 | 36 | @Override 37 | public void onViewCreated(View view, Bundle savedInstanceState) { 38 | super.onViewCreated(view, savedInstanceState); 39 | BusProvider.getInstance().register(this); 40 | } 41 | 42 | 43 | @Override 44 | public void onDestroyView() { 45 | super.onDestroyView(); 46 | BusProvider.getInstance().unregister(this); 47 | } 48 | 49 | protected void showToast(String message) { 50 | if (mToast != null) { 51 | mToast.cancel(); 52 | } 53 | mToast = Toast.makeText(getActivity(), message, Toast.LENGTH_SHORT); 54 | mToast.show(); 55 | } 56 | 57 | protected void trackFragment(String screenName) { 58 | mTracker.setScreenName(screenName); 59 | mTracker.send(new HitBuilders.ScreenViewBuilder().build()); 60 | } 61 | 62 | protected void showToast(int resId) { 63 | if (mToast != null) { 64 | mToast.cancel(); 65 | } 66 | mToast = Toast.makeText(getActivity(), resId, Toast.LENGTH_SHORT); 67 | mToast.show(); 68 | } 69 | 70 | protected void checkForNewLoad(Cursor cursor) { 71 | boolean twoPane = ((MainActivity) getActivity()).isTwoPane(); 72 | Debug.e(" twoPane: " + twoPane, false); 73 | if (twoPane && cursor != null && cursor.moveToFirst()) { 74 | final Contest contest = Contest.cursorToContest(getActivity(), cursor); 75 | if (contest != null) { 76 | Handler handler = new Handler(Looper.getMainLooper()); 77 | handler.post(new Runnable() { 78 | @Override 79 | public void run() { 80 | BusProvider.getInstance().post(new ContestClickEvent(contest)); 81 | } 82 | }); 83 | } 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrendra/codefiesta/ui/fragments/CurrentFragment.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta.ui.fragments; 2 | 3 | import android.database.Cursor; 4 | import android.net.Uri; 5 | import android.os.Bundle; 6 | import android.support.design.widget.CoordinatorLayout; 7 | import android.support.v4.app.LoaderManager; 8 | import android.support.v4.content.CursorLoader; 9 | import android.support.v4.content.Loader; 10 | import android.view.LayoutInflater; 11 | import android.view.View; 12 | import android.view.ViewGroup; 13 | import android.widget.ListView; 14 | import android.widget.ProgressBar; 15 | import android.widget.RelativeLayout; 16 | import android.widget.TextView; 17 | 18 | import com.amrendra.codefiesta.R; 19 | import com.amrendra.codefiesta.adapter.ContestAdapter; 20 | import com.amrendra.codefiesta.db.DBContract; 21 | import com.amrendra.codefiesta.sync.CodeFiestaSyncAdapter; 22 | import com.amrendra.codefiesta.utils.DateUtils; 23 | import com.amrendra.codefiesta.utils.Debug; 24 | import com.amrendra.codefiesta.utils.TrackingConstants; 25 | 26 | import butterknife.Bind; 27 | import butterknife.ButterKnife; 28 | import butterknife.OnClick; 29 | 30 | import static com.amrendra.codefiesta.utils.AppUtils.showSnackBarMessage; 31 | 32 | 33 | public class CurrentFragment extends BaseFragment { 34 | 35 | private static final int CURRENT_CONTESTS_LOADER = 0; 36 | 37 | @Bind(R.id.list_fragment_coordinator_layout) 38 | CoordinatorLayout mCoordinatorLayout; 39 | @Bind(R.id.contest_list) 40 | ListView mListView; 41 | @Bind(R.id.view_error) 42 | RelativeLayout errorLayout; 43 | @Bind(R.id.view_loading) 44 | RelativeLayout loadingLayout; 45 | @Bind(R.id.progress_bar) 46 | ProgressBar progressBar; 47 | @Bind(R.id.error_message) 48 | TextView errorTv; 49 | 50 | @OnClick(R.id.refresh) 51 | void onRefreshClick() { 52 | showSnackBarMessage(getActivity(), mCoordinatorLayout, getString(R.string.sync_data)); 53 | CodeFiestaSyncAdapter.syncImmediately(getActivity()); 54 | } 55 | 56 | ContestAdapter mAdapter; 57 | 58 | public CurrentFragment() { 59 | 60 | } 61 | 62 | @Override 63 | public void onResume() { 64 | super.onResume(); 65 | trackFragment(TrackingConstants.CURRENT_FRAGMENT_SCREEN_NAME); 66 | } 67 | 68 | @Override 69 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 70 | Bundle savedInstanceState) { 71 | View view = inflater.inflate(R.layout.fragment_list, container, false); 72 | ButterKnife.bind(this, view); 73 | return view; 74 | } 75 | 76 | @Override 77 | public void onDestroyView() { 78 | super.onDestroyView(); 79 | ButterKnife.unbind(this); 80 | } 81 | 82 | /* 83 | Lifecycle of a fragment 84 | 1. onInflate 85 | 2. onAttach() 86 | 3. onCreate() 87 | 4. onCreateView() 88 | 5. onViewCreated() 89 | Activity.onCreate() 90 | 6. onActivityCreated() 91 | 7. onStart() 92 | 8. onResume() Fragment is visible now 93 | 9. onPause() 94 | 10. onStop() 95 | 11. onDestroyView(); 96 | 12. onDestroy() 97 | 13. onDetach 98 | */ 99 | 100 | @Override 101 | public void onViewCreated(View view, Bundle savedInstanceState) { 102 | super.onViewCreated(view, savedInstanceState); 103 | mAdapter = new ContestAdapter(getActivity(), null, 0); 104 | mListView.setAdapter(mAdapter); 105 | restartLoader(null); 106 | } 107 | 108 | 109 | private void restartLoader(Bundle bundle) { 110 | progressBar.setVisibility(View.VISIBLE); 111 | loadingLayout.setVisibility(View.VISIBLE); 112 | errorTv.setVisibility(View.INVISIBLE); 113 | LoaderManager mLoaderManager = getActivity().getSupportLoaderManager(); 114 | if (mLoaderManager.getLoader(CURRENT_CONTESTS_LOADER) == null) { 115 | mLoaderManager.initLoader(CURRENT_CONTESTS_LOADER, bundle, currentContestLoaderCallbacks); 116 | } else { 117 | mLoaderManager.restartLoader(CURRENT_CONTESTS_LOADER, bundle, currentContestLoaderCallbacks); 118 | } 119 | } 120 | 121 | private LoaderManager.LoaderCallbacks currentContestLoaderCallbacks 122 | = new LoaderManager.LoaderCallbacks() { 123 | 124 | @Override 125 | public Loader onCreateLoader(int id, Bundle args) { 126 | Debug.c(); 127 | Uri uri = DBContract.ContestEntry.buildLiveContestUri(DateUtils.getCurrentEpochTime()); 128 | return new CursorLoader( 129 | getActivity(), 130 | uri, 131 | null, 132 | null, 133 | null, 134 | DBContract.ContestEntry.CONTEST_END_COL + " ASC" 135 | ); 136 | } 137 | 138 | @Override 139 | public void onLoadFinished(Loader loader, Cursor cursor) { 140 | Debug.c(); 141 | mAdapter.swapCursor(cursor); 142 | progressBar.setVisibility(View.INVISIBLE); 143 | if (cursor != null && cursor.getCount() > 0) { 144 | errorTv.setVisibility(View.INVISIBLE); 145 | errorLayout.setVisibility(View.INVISIBLE); 146 | checkForNewLoad(cursor); 147 | } else { 148 | errorTv.setText(getActivity().getString(R.string.nomatch)); 149 | errorTv.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.egg_empty, 0, 0); 150 | errorTv.setContentDescription(getActivity().getString(R.string.nomatch)); 151 | errorTv.setVisibility(View.VISIBLE); 152 | errorLayout.setVisibility(View.VISIBLE); 153 | } 154 | } 155 | 156 | @Override 157 | public void onLoaderReset(Loader loader) { 158 | Debug.c(); 159 | mAdapter.swapCursor(null); 160 | } 161 | }; 162 | 163 | } 164 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrendra/codefiesta/ui/fragments/PastFragment.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta.ui.fragments; 2 | 3 | import android.database.Cursor; 4 | import android.net.Uri; 5 | import android.os.Bundle; 6 | import android.support.design.widget.CoordinatorLayout; 7 | import android.support.v4.app.LoaderManager; 8 | import android.support.v4.content.CursorLoader; 9 | import android.support.v4.content.Loader; 10 | import android.view.LayoutInflater; 11 | import android.view.View; 12 | import android.view.ViewGroup; 13 | import android.widget.ListView; 14 | import android.widget.ProgressBar; 15 | import android.widget.RelativeLayout; 16 | import android.widget.TextView; 17 | 18 | import com.amrendra.codefiesta.R; 19 | import com.amrendra.codefiesta.adapter.ContestAdapter; 20 | import com.amrendra.codefiesta.db.DBContract; 21 | import com.amrendra.codefiesta.utils.DateUtils; 22 | import com.amrendra.codefiesta.utils.Debug; 23 | import com.amrendra.codefiesta.utils.TrackingConstants; 24 | 25 | import butterknife.Bind; 26 | import butterknife.ButterKnife; 27 | 28 | public class PastFragment extends BaseFragment { 29 | 30 | private static final int CURRENT_CONTESTS_LOADER = 0; 31 | @Bind(R.id.list_fragment_coordinator_layout) 32 | CoordinatorLayout mCoordinatorLayout; 33 | @Bind(R.id.contest_list) 34 | ListView mListView; 35 | @Bind(R.id.view_error) 36 | RelativeLayout errorLayout; 37 | @Bind(R.id.view_loading) 38 | RelativeLayout loadingLayout; 39 | @Bind(R.id.progress_bar) 40 | ProgressBar progressBar; 41 | @Bind(R.id.error_message) 42 | TextView errorTv; 43 | ContestAdapter mAdapter; 44 | 45 | public PastFragment() { 46 | 47 | } 48 | 49 | @Override 50 | public void onResume() { 51 | super.onResume(); 52 | trackFragment(TrackingConstants.PAST_FRAGMENT_SCREEN_NAME); 53 | } 54 | 55 | @Override 56 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 57 | Bundle savedInstanceState) { 58 | View view = inflater.inflate(R.layout.fragment_list, container, false); 59 | ButterKnife.bind(this,view); 60 | return view; 61 | } 62 | 63 | @Override 64 | public void onDestroyView() { 65 | super.onDestroyView(); 66 | ButterKnife.unbind(this); 67 | } 68 | 69 | /* 70 | Lifecycle of a fragment 71 | 1. onInflate 72 | 2. onAttach() 73 | 3. onCreate() 74 | 4. onCreateView() 75 | 5. onViewCreated() 76 | Activity.onCreate() 77 | 6. onActivityCreated() 78 | 7. onStart() 79 | 8. onResume() Fragment is visible now 80 | 9. onPause() 81 | 10. onStop() 82 | 11. onDestroyView(); 83 | 12. onDestroy() 84 | 13. onDetach 85 | */ 86 | 87 | @Override 88 | public void onViewCreated(View view, Bundle savedInstanceState) { 89 | super.onViewCreated(view, savedInstanceState); 90 | mAdapter = new ContestAdapter(getActivity(), null, 0); 91 | mListView.setAdapter(mAdapter); 92 | restartLoader(null); 93 | } 94 | 95 | private void restartLoader(Bundle bundle) { 96 | progressBar.setVisibility(View.VISIBLE); 97 | loadingLayout.setVisibility(View.VISIBLE); 98 | errorTv.setVisibility(View.INVISIBLE); 99 | LoaderManager mLoaderManager = getActivity().getSupportLoaderManager(); 100 | if (mLoaderManager.getLoader(CURRENT_CONTESTS_LOADER) == null) { 101 | mLoaderManager.initLoader(CURRENT_CONTESTS_LOADER, bundle, currentContestLoaderCallbacks); 102 | } else { 103 | mLoaderManager.restartLoader(CURRENT_CONTESTS_LOADER, bundle, currentContestLoaderCallbacks); 104 | } 105 | } 106 | 107 | private LoaderManager.LoaderCallbacks currentContestLoaderCallbacks 108 | = new LoaderManager.LoaderCallbacks() { 109 | 110 | @Override 111 | public Loader onCreateLoader(int id, Bundle args) { 112 | Debug.c(); 113 | Uri uri = DBContract.ContestEntry.buildPastContestUri(DateUtils.getCurrentEpochTime()); 114 | return new CursorLoader( 115 | getActivity(), 116 | uri, 117 | null, 118 | null, 119 | null, 120 | DBContract.ContestEntry.CONTEST_END_COL + " ASC" 121 | ); 122 | } 123 | 124 | @Override 125 | public void onLoadFinished(Loader loader, Cursor cursor) { 126 | Debug.c(); 127 | mAdapter.swapCursor(cursor); 128 | progressBar.setVisibility(View.INVISIBLE); 129 | if (cursor != null && cursor.getCount() > 0) { 130 | errorTv.setVisibility(View.INVISIBLE); 131 | errorLayout.setVisibility(View.INVISIBLE); 132 | checkForNewLoad(cursor); 133 | } else { 134 | errorTv.setText(getActivity().getString(R.string.nomatch)); 135 | errorTv.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.egg_empty, 0, 0); 136 | errorTv.setContentDescription(getActivity().getString(R.string.nomatch)); 137 | errorTv.setVisibility(View.VISIBLE); 138 | errorLayout.setVisibility(View.VISIBLE); 139 | } 140 | } 141 | 142 | @Override 143 | public void onLoaderReset(Loader loader) { 144 | Debug.c(); 145 | mAdapter.swapCursor(null); 146 | } 147 | }; 148 | } 149 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrendra/codefiesta/ui/fragments/SelectionFragment.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta.ui.fragments; 2 | 3 | import android.content.ContentProviderOperation; 4 | import android.content.ContentProviderResult; 5 | import android.content.ContentValues; 6 | import android.content.OperationApplicationException; 7 | import android.os.Bundle; 8 | import android.os.RemoteException; 9 | import android.support.v4.app.LoaderManager; 10 | import android.support.v4.content.Loader; 11 | import android.support.v7.widget.LinearLayoutManager; 12 | import android.support.v7.widget.RecyclerView; 13 | import android.view.LayoutInflater; 14 | import android.view.View; 15 | import android.view.ViewGroup; 16 | 17 | import com.amrendra.codefiesta.R; 18 | import com.amrendra.codefiesta.adapter.SelectionAdapter; 19 | import com.amrendra.codefiesta.bus.BusProvider; 20 | import com.amrendra.codefiesta.bus.events.SettingsSaveEvent; 21 | import com.amrendra.codefiesta.db.DBContract; 22 | import com.amrendra.codefiesta.loaders.ResourceSettingLoader; 23 | import com.amrendra.codefiesta.model.Website; 24 | import com.amrendra.codefiesta.utils.Debug; 25 | 26 | import java.util.ArrayList; 27 | import java.util.HashMap; 28 | import java.util.List; 29 | import java.util.Map; 30 | 31 | import butterknife.Bind; 32 | import butterknife.ButterKnife; 33 | import butterknife.OnClick; 34 | 35 | /** 36 | * Created by Amrendra Kumar on 11/04/16. 37 | */ 38 | public class SelectionFragment extends BaseFragment implements SelectionAdapter.CompetitionSettingsChangedListener { 39 | 40 | private static final int RESOURCE_SELECTION_LOADER = 1; 41 | 42 | @Bind(R.id.contest_list) 43 | RecyclerView mRecyclerView; 44 | 45 | @OnClick(R.id.save_button) 46 | void onSaveButtonClick() { 47 | saveSettingsList(); 48 | BusProvider.getInstance().post(new SettingsSaveEvent()); 49 | } 50 | 51 | SelectionAdapter mAdapter; 52 | 53 | HashMap settingsHashMap; 54 | 55 | public SelectionFragment() { 56 | 57 | } 58 | 59 | @Override 60 | public void onResume() { 61 | super.onResume(); 62 | refreshSettingsList(); 63 | } 64 | 65 | @Override 66 | public void onPause() { 67 | super.onPause(); 68 | saveSettingsList(); 69 | } 70 | 71 | @Override 72 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 73 | Bundle savedInstanceState) { 74 | View view = inflater.inflate(R.layout.selection_fragment, container, false); 75 | ButterKnife.bind(this,view); 76 | return view; 77 | } 78 | 79 | @Override 80 | public void onDestroyView() { 81 | super.onDestroyView(); 82 | ButterKnife.unbind(this); 83 | } 84 | 85 | /* 86 | Lifecycle of a fragment 87 | 1. onInflate 88 | 2. onAttach() 89 | 3. onCreate() 90 | 4. onCreateView() 91 | 5. onViewCreated() 92 | Activity.onCreate() 93 | 6. onActivityCreated() 94 | 7. onStart() 95 | 8. onResume() Fragment is visible now 96 | 9. onPause() 97 | 10. onStop() 98 | 11. onDestroyView(); 99 | 12. onDestroy() 100 | 13. onDetach 101 | */ 102 | 103 | @Override 104 | public void onViewCreated(View view, Bundle savedInstanceState) { 105 | super.onViewCreated(view, savedInstanceState); 106 | List list = new ArrayList<>(); 107 | mAdapter = new SelectionAdapter(getActivity(), list, this); 108 | LinearLayoutManager mLinearLayoutManager = new LinearLayoutManager(getActivity()); 109 | mRecyclerView.setLayoutManager(mLinearLayoutManager); 110 | mRecyclerView.setAdapter(mAdapter); 111 | restartLoader(null); 112 | } 113 | 114 | private void restartLoader(Bundle bundle) { 115 | LoaderManager mLoaderManager = getActivity().getSupportLoaderManager(); 116 | if (mLoaderManager.getLoader(RESOURCE_SELECTION_LOADER) == null) { 117 | mLoaderManager.initLoader(RESOURCE_SELECTION_LOADER, bundle, resourceSettingsLoader); 118 | } else { 119 | mLoaderManager.restartLoader(RESOURCE_SELECTION_LOADER, bundle, resourceSettingsLoader); 120 | } 121 | } 122 | 123 | private LoaderManager.LoaderCallbacks> resourceSettingsLoader 124 | = new LoaderManager.LoaderCallbacks>() { 125 | 126 | @Override 127 | public Loader> onCreateLoader(int id, Bundle args) { 128 | Debug.c(); 129 | return new ResourceSettingLoader(getActivity()); 130 | } 131 | 132 | @Override 133 | public void onLoadFinished(Loader> loader, List list) { 134 | Debug.c(); 135 | if (list != null) { 136 | Debug.e(" size : " + list.size(), false); 137 | mAdapter.resetWebsiteList(list); 138 | } 139 | 140 | } 141 | 142 | @Override 143 | public void onLoaderReset(Loader> loader) { 144 | Debug.c(); 145 | mAdapter.clearWebsites(); 146 | 147 | } 148 | }; 149 | 150 | @Override 151 | public void onSaveInstanceState(Bundle outState) { 152 | super.onSaveInstanceState(outState); 153 | } 154 | 155 | @Override 156 | public void settingsChanged(int competitionId, int want) { 157 | Debug.e("Change required : " + competitionId + " change : " + want, false); 158 | settingsHashMap.put(competitionId, want); 159 | } 160 | 161 | private void refreshSettingsList() { 162 | Debug.c(); 163 | if (settingsHashMap != null) { 164 | settingsHashMap.clear(); 165 | } else { 166 | settingsHashMap = new HashMap<>(); 167 | } 168 | } 169 | 170 | private void saveSettingsList() { 171 | Debug.c(); 172 | if (settingsHashMap != null && settingsHashMap.size() > 0) { 173 | ArrayList cpo = new ArrayList<>(); 174 | for (Map.Entry entry : settingsHashMap.entrySet()) { 175 | int resourceId = entry.getKey(); 176 | int show = entry.getValue(); 177 | Debug.e("changing operation for : " + resourceId + " change : " + show, false); 178 | ContentValues cv = new ContentValues(); 179 | cv.put(DBContract.ResourceEntry.RESOURCE_ID_COL, resourceId); 180 | cv.put(DBContract.ResourceEntry.RESOURCE_SHOW_COL, show); 181 | cpo.add( 182 | ContentProviderOperation.newUpdate(DBContract.ResourceEntry.CONTENT_URI_ALL) 183 | .withValues(cv).build() 184 | ); 185 | } 186 | try { 187 | ContentProviderResult[] cpr = getActivity().getContentResolver() 188 | .applyBatch(getString(R.string.contentauthority), cpo); 189 | Debug.showToastShort("Updated settings for " + cpr.length + " websites", getActivity(), true); 190 | } catch (RemoteException | OperationApplicationException e) { 191 | e.printStackTrace(); 192 | Debug.e(" error : " + e.getLocalizedMessage(), false); 193 | } 194 | Debug.c(); 195 | refreshSettingsList(); 196 | } 197 | } 198 | } 199 | 200 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrendra/codefiesta/ui/fragments/UpcomingFragment.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta.ui.fragments; 2 | 3 | import android.database.Cursor; 4 | import android.net.Uri; 5 | import android.os.Bundle; 6 | import android.support.design.widget.CoordinatorLayout; 7 | import android.support.v4.app.LoaderManager; 8 | import android.support.v4.content.CursorLoader; 9 | import android.support.v4.content.Loader; 10 | import android.view.LayoutInflater; 11 | import android.view.View; 12 | import android.view.ViewGroup; 13 | import android.widget.ListView; 14 | import android.widget.ProgressBar; 15 | import android.widget.RelativeLayout; 16 | import android.widget.TextView; 17 | 18 | import com.amrendra.codefiesta.R; 19 | import com.amrendra.codefiesta.adapter.ContestAdapter; 20 | import com.amrendra.codefiesta.db.DBContract; 21 | import com.amrendra.codefiesta.sync.CodeFiestaSyncAdapter; 22 | import com.amrendra.codefiesta.utils.DateUtils; 23 | import com.amrendra.codefiesta.utils.Debug; 24 | import com.amrendra.codefiesta.utils.TrackingConstants; 25 | 26 | import butterknife.Bind; 27 | import butterknife.ButterKnife; 28 | import butterknife.OnClick; 29 | 30 | import static com.amrendra.codefiesta.utils.AppUtils.showSnackBarMessage; 31 | 32 | public class UpcomingFragment extends BaseFragment { 33 | 34 | private static final int CURRENT_CONTESTS_LOADER = 0; 35 | @Bind(R.id.list_fragment_coordinator_layout) 36 | CoordinatorLayout mCoordinatorLayout; 37 | @Bind(R.id.contest_list) 38 | ListView mListView; 39 | @Bind(R.id.view_error) 40 | RelativeLayout errorLayout; 41 | @Bind(R.id.view_loading) 42 | RelativeLayout loadingLayout; 43 | @Bind(R.id.progress_bar) 44 | ProgressBar progressBar; 45 | @Bind(R.id.error_message) 46 | TextView errorTv; 47 | 48 | @OnClick(R.id.refresh) 49 | void onRefreshClick() { 50 | showSnackBarMessage(getActivity(), mCoordinatorLayout, getString(R.string.sync_data)); 51 | CodeFiestaSyncAdapter.syncImmediately(getActivity()); 52 | } 53 | 54 | ContestAdapter mAdapter; 55 | 56 | public UpcomingFragment() { 57 | 58 | } 59 | 60 | @Override 61 | public void onResume() { 62 | super.onResume(); 63 | trackFragment(TrackingConstants.FUTURE_FRAGMENT_SCREEN_NAME); 64 | } 65 | 66 | @Override 67 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 68 | Bundle savedInstanceState) { 69 | View view = inflater.inflate(R.layout.fragment_list, container, false); 70 | ButterKnife.bind(this, view); 71 | return view; 72 | } 73 | 74 | @Override 75 | public void onDestroyView() { 76 | super.onDestroyView(); 77 | ButterKnife.unbind(this); 78 | } 79 | 80 | /* 81 | Lifecycle of a fragment 82 | 1. onInflate 83 | 2. onAttach() 84 | 3. onCreate() 85 | 4. onCreateView() 86 | 5. onViewCreated() 87 | Activity.onCreate() 88 | 6. onActivityCreated() 89 | 7. onStart() 90 | 8. onResume() Fragment is visible now 91 | 9. onPause() 92 | 10. onStop() 93 | 11. onDestroyView(); 94 | 12. onDestroy() 95 | 13. onDetach 96 | */ 97 | 98 | @Override 99 | public void onViewCreated(View view, Bundle savedInstanceState) { 100 | super.onViewCreated(view, savedInstanceState); 101 | mAdapter = new ContestAdapter(getActivity(), null, 0); 102 | mListView.setAdapter(mAdapter); 103 | restartLoader(null); 104 | } 105 | 106 | private void restartLoader(Bundle bundle) { 107 | progressBar.setVisibility(View.VISIBLE); 108 | loadingLayout.setVisibility(View.VISIBLE); 109 | errorTv.setVisibility(View.INVISIBLE); 110 | LoaderManager mLoaderManager = getActivity().getSupportLoaderManager(); 111 | if (mLoaderManager.getLoader(CURRENT_CONTESTS_LOADER) == null) { 112 | mLoaderManager.initLoader(CURRENT_CONTESTS_LOADER, bundle, currentContestLoaderCallbacks); 113 | } else { 114 | mLoaderManager.restartLoader(CURRENT_CONTESTS_LOADER, bundle, currentContestLoaderCallbacks); 115 | } 116 | } 117 | 118 | private LoaderManager.LoaderCallbacks currentContestLoaderCallbacks 119 | = new LoaderManager.LoaderCallbacks() { 120 | 121 | @Override 122 | public Loader onCreateLoader(int id, Bundle args) { 123 | Debug.c(); 124 | Uri uri = DBContract.ContestEntry.buildFutureContestUri(DateUtils.getCurrentEpochTime()); 125 | return new CursorLoader( 126 | getActivity(), 127 | uri, 128 | null, 129 | null, 130 | null, 131 | DBContract.ContestEntry.CONTEST_START_COL + " ASC" 132 | ); 133 | } 134 | 135 | @Override 136 | public void onLoadFinished(Loader loader, Cursor cursor) { 137 | Debug.c(); 138 | mAdapter.swapCursor(cursor); 139 | progressBar.setVisibility(View.INVISIBLE); 140 | if (cursor != null && cursor.getCount() > 0) { 141 | errorTv.setVisibility(View.INVISIBLE); 142 | errorLayout.setVisibility(View.INVISIBLE); 143 | checkForNewLoad(cursor); 144 | } else { 145 | errorTv.setText(getActivity().getString(R.string.nomatch)); 146 | errorTv.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.egg_empty, 0, 0); 147 | errorTv.setContentDescription(getActivity().getString(R.string.nomatch)); 148 | errorTv.setVisibility(View.VISIBLE); 149 | errorLayout.setVisibility(View.VISIBLE); 150 | } 151 | } 152 | 153 | @Override 154 | public void onLoaderReset(Loader loader) { 155 | Debug.c(); 156 | mAdapter.swapCursor(null); 157 | } 158 | }; 159 | } 160 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrendra/codefiesta/utils/AppUtils.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta.utils; 2 | 3 | import android.content.ActivityNotFoundException; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.database.Cursor; 7 | import android.net.Uri; 8 | import android.support.design.widget.CoordinatorLayout; 9 | import android.support.design.widget.Snackbar; 10 | import android.support.v4.content.ContextCompat; 11 | import android.text.Html; 12 | 13 | import com.amrendra.codefiesta.R; 14 | import com.amrendra.codefiesta.db.DBContract; 15 | import com.crashlytics.android.Crashlytics; 16 | 17 | import java.util.HashMap; 18 | 19 | /** 20 | * Created by Amrendra Kumar on 11/04/16. 21 | */ 22 | public class AppUtils { 23 | public static final long SIX_HOURS = 6 * 60 * 60; 24 | public static final long ONE_DAY = SIX_HOURS * 4; 25 | public static final long ONE_WEEK = ONE_DAY * 7; 26 | public static final long ONE_MONTH = ONE_WEEK * 4; 27 | 28 | public static final String MAX_CONTEST_DURATION = "MAX_CONTEST_DURATION"; 29 | public static final long MAX_DEFAULT_CONTEST_DURATION = 3 * ONE_MONTH; 30 | public static final String LAST_SYNC_PERFORMED = "LAST_SYNC_PERFORMED"; 31 | public static final long LAST_SYNC_PERFORMED_DEFAULT_VALUE = -1; 32 | 33 | 34 | public static final int STATUS_CONTEST_ENDED = -1; 35 | public static final int STATUS_CONTEST_LIVE = 0; 36 | public static final int STATUS_CONTEST_FUTURE = 1; 37 | 38 | public static final int STATUS_CALENDAR_EVENT_SUCCESS = 0; 39 | public static final int STATUS_CALENDAR_PERMISSION_ERROR = -1; 40 | public static final int STATUS_CALENDAR_NO_ACCOUNT = -2; 41 | public static final int STATUS_CALENDAR_EVENT_ALREADY_ADDED = -3; 42 | public static final int STATUS_CALENDAR_EVENT_NOT_PRESENT = -4; 43 | 44 | public static final int STATUS_CALENDAR_EVENT_NOT_PRESENT_SO_ADDED = 101; 45 | public static final int STATUS_CALENDAR_EVENT_PRESENT_SO_REMOVED = 102; 46 | 47 | public static final String BROADCAST_DATA_UPDATED = "com.amrendra.codefiesta" + ".BROADCAST_SYNC_PERFORMED"; 48 | public static final String CONTEST_KEY = "CONTEST_KEY"; 49 | public static final String UNKNOWN_RESOURCE = "Unknown Website"; 50 | public static final String GIT_URL = "https://github.com/amrendra18/codezera"; 51 | public static final String EMAIL_ID = "amrendra.nitb+appfeedback@gmail.com"; 52 | 53 | static HashMap resourceHashMap; 54 | 55 | public static void cacheResources(Context context) { 56 | if (resourceHashMap == null) { 57 | resourceHashMap = new HashMap<>(); 58 | } 59 | Debug.c(); 60 | Cursor cursor = context.getContentResolver().query( 61 | DBContract.ResourceEntry.CONTENT_URI_ALL, 62 | DBContract.ResourceEntry.RESOURCE_PROJECTION, 63 | null, 64 | null, 65 | null 66 | ); 67 | if (cursor != null) { 68 | try { 69 | while (cursor.moveToNext()) { 70 | int id = cursor.getInt(cursor.getColumnIndex(DBContract.ResourceEntry 71 | .RESOURCE_ID_COL)); 72 | String name = cursor.getString(cursor.getColumnIndex(DBContract.ResourceEntry 73 | .RESOURCE_NAME_COL)); 74 | resourceHashMap.put(id, name); 75 | } 76 | } finally { 77 | cursor.close(); 78 | } 79 | } 80 | } 81 | 82 | public static String getResourceName(Context context, int key) { 83 | if (resourceHashMap == null 84 | || resourceHashMap.size() == 0 85 | || (!resourceHashMap.containsKey(key))) { 86 | cacheResources(context); 87 | } 88 | if (resourceHashMap.containsKey(key)) { 89 | return resourceHashMap.get(key); 90 | } 91 | return UNKNOWN_RESOURCE; 92 | } 93 | 94 | public static String getGoodResourceName(String resource) { 95 | String ret = resource; 96 | int slash = resource.indexOf("/"); 97 | if (slash != -1) { 98 | ret = resource.substring(slash + 1); 99 | } else { 100 | int lastDot = resource.lastIndexOf("."); 101 | if (lastDot != -1) { 102 | ret = resource.substring(0, lastDot); 103 | } 104 | } 105 | ret = ret.replaceAll("\\.", " ").toUpperCase(); 106 | return ret; 107 | } 108 | 109 | public static int getImageForResource(String resource) { 110 | if (resource != null) { 111 | String res = resource.toLowerCase(); 112 | if (res.contains("codechef")) { 113 | return R.drawable.codechef; 114 | } else if (res.contains("hackerrank")) { 115 | return R.drawable.hackerrank; 116 | } else if (res.contains("hackerearth")) { 117 | return R.drawable.hackerearth; 118 | } else if (res.contains("codeforces")) { 119 | return R.drawable.codeforces; 120 | } else if (res.contains("topcoder")) { 121 | return R.drawable.topcoder; 122 | } else if (res.contains("spoj")) { 123 | return R.drawable.spoj; 124 | } else if (res.contains("kaggle")) { 125 | return R.drawable.kaggle; 126 | } 127 | } 128 | return R.mipmap.ic_launcher; 129 | } 130 | 131 | public static void openWebsite(Context context, CoordinatorLayout mCoordinatorLayout, String url) { 132 | if (url != null && url.trim().length() > 0) { 133 | Intent i = new Intent(Intent.ACTION_VIEW); 134 | i.setData(Uri.parse(url)); 135 | try { 136 | context.startActivity(i); 137 | } catch (ActivityNotFoundException e) { 138 | Crashlytics.log("ANFE;url=" + url); 139 | Crashlytics.logException(e); 140 | showSnackBarMessage(context, mCoordinatorLayout, context.getString(R.string.website_open_error)); 141 | } 142 | } 143 | 144 | } 145 | 146 | public static void showSnackBarMessage(Context context, CoordinatorLayout mCoordinatorLayout, String msg) { 147 | if (context != null && mCoordinatorLayout != null) { 148 | Snackbar snackbar = Snackbar.make(mCoordinatorLayout, Html.fromHtml(msg), Snackbar.LENGTH_SHORT); 149 | snackbar.getView().setBackgroundColor(ContextCompat.getColor(context, R.color.colorPrimary)); 150 | snackbar.show(); 151 | } 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrendra/codefiesta/utils/CalendarUtils.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta.utils; 2 | 3 | import android.content.Context; 4 | import android.database.Cursor; 5 | import android.provider.CalendarContract; 6 | 7 | /** 8 | * Created by Amrendra Kumar on 24/04/16. 9 | */ 10 | public class CalendarUtils { 11 | public static long getCalendarId(Context mContext) { 12 | Debug.c(); 13 | String[] projection = new String[]{CalendarContract.Calendars._ID, CalendarContract 14 | .Calendars.NAME, CalendarContract.Calendars.ACCOUNT_NAME, CalendarContract 15 | .Calendars.CALENDAR_TIME_ZONE}; 16 | 17 | try { 18 | Cursor cursor = mContext.getContentResolver().query( 19 | CalendarContract.Calendars.CONTENT_URI, 20 | projection, 21 | null, 22 | null, 23 | null); 24 | if (cursor != null) { 25 | try { 26 | if (cursor.moveToFirst()) { 27 | int id = cursor.getInt(cursor.getColumnIndex(CalendarContract.Calendars 28 | ._ID)); 29 | String name = cursor.getString(cursor.getColumnIndex(CalendarContract 30 | .Calendars 31 | .NAME)); 32 | String accountName = cursor.getString(cursor.getColumnIndex(CalendarContract 33 | .Calendars 34 | .ACCOUNT_NAME)); 35 | String timezone = cursor.getString(cursor.getColumnIndex(CalendarContract 36 | .Calendars 37 | .CALENDAR_TIME_ZONE)); 38 | Debug.i("id: " + id + " name: " + name + " accName: " + accountName + " zone: " + 39 | "" + timezone, false); 40 | return id; 41 | } else { 42 | return AppUtils.STATUS_CALENDAR_NO_ACCOUNT; 43 | } 44 | } finally { 45 | cursor.close(); 46 | } 47 | } 48 | } catch (SecurityException ex) { 49 | ex.printStackTrace(); 50 | } 51 | return AppUtils.STATUS_CALENDAR_PERMISSION_ERROR; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrendra/codefiesta/utils/CustomDate.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta.utils; 2 | 3 | /** 4 | * Created by Amrendra Kumar on 17/04/16. 5 | */ 6 | public class CustomDate { 7 | 8 | String dayOfWeek; 9 | String dateOfMonth; 10 | String month; 11 | String year; 12 | String time; 13 | String ampm; 14 | 15 | public CustomDate(String date) { 16 | String splits[] = date.split(" "); 17 | dayOfWeek = splits[0]; 18 | dateOfMonth = splits[1]; 19 | month = splits[2]; 20 | year = splits[3]; 21 | time = splits[4]; 22 | ampm = splits[5]; 23 | } 24 | 25 | 26 | public String getDayOfWeek() { 27 | return dayOfWeek + ","; 28 | } 29 | 30 | public String getDateOfMonth() { 31 | return dateOfMonth; 32 | } 33 | 34 | public String getDateMonthYear() { 35 | return dayOfWeek.toUpperCase() + ", " + dateOfMonth + " " + month + " '" + year; 36 | } 37 | 38 | public String getFullTime(){ 39 | return getTimeAmPm()+" "+getDateMonthYear(); 40 | } 41 | 42 | public String getMonth() { 43 | return month; 44 | } 45 | 46 | public String getYear() { 47 | return year; 48 | } 49 | 50 | public String getTime() { 51 | return time; 52 | } 53 | 54 | public String getTimeAmPm() { 55 | return time + " " + ampm; 56 | } 57 | 58 | public String getAmPm() { 59 | return ampm; 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrendra/codefiesta/utils/DateUtils.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta.utils; 2 | 3 | import com.amrendra.codefiesta.CodeFiestaApplication; 4 | 5 | import java.text.ParseException; 6 | import java.text.SimpleDateFormat; 7 | import java.util.Date; 8 | import java.util.TimeZone; 9 | 10 | /** 11 | * Created by Amrendra Kumar on 09/04/16. 12 | */ 13 | public class DateUtils { 14 | 15 | public static long SEC_IN_ONE_MINUTE = 60; 16 | public static long SEC_IN_ONE_HOUR = SEC_IN_ONE_MINUTE * 60; 17 | public static long SEC_IN_ONE_DAY = SEC_IN_ONE_HOUR * 24; 18 | public static long SEC_IN_ONE_YEAR = SEC_IN_ONE_DAY * 365; 19 | 20 | public static long getEpochTime(String time) { 21 | long epochTime = -1; 22 | //"2013-12-08T09:00:00" 23 | if (null != time) { 24 | SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); 25 | df.setTimeZone(TimeZone.getTimeZone("GMT")); 26 | try { 27 | Date date = df.parse(time); 28 | epochTime = date.getTime() / 1000; 29 | } catch (ParseException e) { 30 | CodeFiestaApplication.shouldNotHappen( 31 | "Exception in converting time to epoch : " 32 | + "time=" + time + " exception=" + 33 | e.getLocalizedMessage()); 34 | } 35 | } else { 36 | CodeFiestaApplication.shouldNotHappen("Time to convert to epoch is null"); 37 | } 38 | return epochTime; 39 | } 40 | 41 | public static String epochToDateTimeGmt(long time) { 42 | long timems = time * 1000L; 43 | SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); 44 | formatter.setTimeZone(TimeZone.getTimeZone("GMT")); 45 | return formatter.format(new Date(timems)); 46 | } 47 | 48 | public static String epochToDateTimeLocal(long time) { 49 | long timems = time * 1000L; 50 | SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 51 | formatter.setTimeZone(TimeZone.getDefault()); 52 | return formatter.format(new Date(timems)); 53 | } 54 | 55 | public static String epochToDateTimeLocalShow(long time) { 56 | long timems = time * 1000L; 57 | SimpleDateFormat formatter = new SimpleDateFormat("EEE dd MMM yy hh:mm a"); 58 | formatter.setTimeZone(TimeZone.getDefault()); 59 | return formatter.format(new Date(timems)); 60 | } 61 | 62 | 63 | public static long getCurrentEpochTime() { 64 | return System.currentTimeMillis() / 1000; 65 | } 66 | 67 | public static String getTimeLeftForEnd(long startTime, long endTime) { 68 | long currTime = System.currentTimeMillis() / 1000; 69 | if (currTime < startTime) { 70 | return "Starts in " + getDurationString(startTime - currTime, false); 71 | } 72 | long left = endTime - currTime; 73 | if (left > 0) { 74 | return "Ends in " + getDurationString(left, true); 75 | } else { 76 | return "Ended"; 77 | } 78 | } 79 | 80 | public static int getContestStatus(long start, long end) { 81 | long currTime = System.currentTimeMillis() / 1000; 82 | if (currTime < start) { 83 | return AppUtils.STATUS_CONTEST_FUTURE; 84 | } 85 | long left = end - currTime; 86 | if (left > 0) { 87 | return AppUtils.STATUS_CONTEST_LIVE; 88 | } 89 | return AppUtils.STATUS_CONTEST_ENDED; 90 | } 91 | 92 | public static String getContestStatusString(long start, long end) { 93 | long currTime = System.currentTimeMillis() / 1000; 94 | if (currTime < start) { 95 | return "Starts in"; 96 | } 97 | long left = end - currTime; 98 | if (left > 0) { 99 | return "Ends in"; 100 | } 101 | return "Ended"; 102 | } 103 | 104 | public static String getDurationString(long time, boolean secRequired) { 105 | StringBuilder sb = new StringBuilder(); 106 | long years = time / SEC_IN_ONE_YEAR; 107 | time %= SEC_IN_ONE_YEAR; 108 | long days = time / SEC_IN_ONE_DAY; 109 | time %= SEC_IN_ONE_DAY; 110 | long hours = time / SEC_IN_ONE_HOUR; 111 | time %= SEC_IN_ONE_HOUR; 112 | long mins = time / SEC_IN_ONE_MINUTE; 113 | time %= SEC_IN_ONE_MINUTE; 114 | if (years > 0) { 115 | sb.append(Long.toString(years)).append("y "); 116 | } 117 | if (days > 0) { 118 | sb.append(Long.toString(days)).append("d "); 119 | } 120 | if (hours > 0) { 121 | sb.append(Long.toString(hours)).append("h "); 122 | } 123 | if (mins > 0) { 124 | sb.append(Long.toString(mins)).append("m "); 125 | } 126 | if (secRequired && time > 0) { 127 | sb.append(Long.toString(time)).append("s "); 128 | } 129 | return sb.toString().trim(); 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrendra/codefiesta/utils/Debug.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta.utils; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.content.SharedPreferences; 6 | import android.os.Bundle; 7 | import android.support.design.BuildConfig; 8 | import android.util.Log; 9 | import android.widget.Toast; 10 | 11 | import org.json.JSONException; 12 | import org.json.JSONObject; 13 | 14 | import java.util.Arrays; 15 | import java.util.Iterator; 16 | import java.util.Map; 17 | 18 | /** 19 | * Created by Amrendra Kumar on 05/04/16. 20 | */ 21 | public class Debug { 22 | private static final Boolean DEBUG = BuildConfig.DEBUG; 23 | private static final String TAG = "bdebug"; 24 | 25 | public static void forceCrash() { 26 | if (DEBUG) { 27 | throw new RuntimeException("Cheeky!! This is a simulated debug crash"); 28 | } 29 | } 30 | 31 | private static String getMsg(String msg) { 32 | if (DEBUG) { 33 | StackTraceElement strace = Thread.currentThread().getStackTrace()[4]; 34 | // String fileName = strace.getFileName(); 35 | String className = strace.getClassName(); 36 | //className = className.replace(packageName, ""); 37 | String methodName = strace.getMethodName(); 38 | int line = strace.getLineNumber(); 39 | msg = className + "::" + methodName + "()[" + line + "]" + " : " + msg; 40 | } 41 | return msg; 42 | } 43 | 44 | public static void c() { 45 | if (DEBUG) { 46 | Log.e(TAG, getMsg("CHECK")); 47 | } 48 | } 49 | 50 | public static void e(String msg, Boolean show) { 51 | if (DEBUG || show) { 52 | Log.e(TAG, getMsg(msg)); 53 | } 54 | } 55 | 56 | public static void d(String msg, Boolean show) { 57 | if (DEBUG || show) { 58 | Log.d(TAG, getMsg(msg)); 59 | } 60 | } 61 | 62 | public static void i(String msg, Boolean show) { 63 | if (DEBUG || show) { 64 | Log.i(TAG, getMsg(msg)); 65 | } 66 | } 67 | 68 | public static void w(String msg, Boolean show) { 69 | if (DEBUG || show) { 70 | Log.w(TAG, getMsg(msg)); 71 | } 72 | } 73 | 74 | public static void v(String msg, Boolean show) { 75 | if (DEBUG || show) { 76 | Log.v(TAG, getMsg(msg)); 77 | } 78 | } 79 | 80 | public static void showToastShort(String msg, Context context) { 81 | showToastShort(msg, context, false); 82 | } 83 | 84 | public static void showToastLong(String msg, Context context) { 85 | showToastLong(msg, context, false); 86 | } 87 | 88 | public static void showToastShort(String msg, Context context, Boolean show) { 89 | if (DEBUG || show) { 90 | if (context == null) { 91 | Log.e(TAG, getMsg("Context is null. Trying to show toast. Msg: " + msg)); 92 | } else { 93 | Toast.makeText(context, msg, Toast.LENGTH_SHORT).show(); 94 | } 95 | } 96 | } 97 | 98 | public static void showToastLong(String msg, Context context, Boolean show) { 99 | if (DEBUG || show) { 100 | if (context == null) { 101 | Log.e(TAG, getMsg("Context is null. Trying to show toast. Msg: " + msg)); 102 | } else { 103 | Toast.makeText(context, msg, Toast.LENGTH_LONG).show(); 104 | } 105 | } 106 | } 107 | 108 | public static void array(Object[] arr) { 109 | if (DEBUG) { 110 | Log.i(TAG, getMsg(Arrays.deepToString(arr))); 111 | } 112 | } 113 | 114 | public static void object(Object obj, String desc) { 115 | if (DEBUG) { 116 | if (obj == null) { 117 | Log.e(TAG, getMsg("Error : " + desc + " is NULL")); 118 | } else { 119 | Log.e(TAG, getMsg(obj.toString())); 120 | } 121 | } 122 | } 123 | 124 | private static String debugObject(String key, Object obj) { 125 | if (obj == null) { 126 | return String.format("%s = %n", key); 127 | } 128 | return String.format("%s = %s (%s)%n", key, String.valueOf(obj), obj.getClass() 129 | .getSimpleName()); 130 | } 131 | 132 | public static void bundle(Bundle bundle) { 133 | if (DEBUG) { 134 | if (bundle != null) { 135 | StringBuilder sb = new StringBuilder(); 136 | sb.append("Bundle{\n"); 137 | for (String key : bundle.keySet()) { 138 | sb.append(debugObject(key, bundle.get(key))); 139 | } 140 | sb.append("}"); 141 | Log.d(TAG, getMsg(sb.toString())); 142 | } else { 143 | Log.e(TAG, getMsg("Error : Expected Bundle is null")); 144 | } 145 | } 146 | } 147 | 148 | public static void intent(Intent intent) { 149 | if (DEBUG) { 150 | if (intent != null) { 151 | bundle(intent.getExtras()); 152 | } else { 153 | Log.d(TAG, getMsg("Error : Expected Intent is null")); 154 | } 155 | } 156 | } 157 | 158 | public static void preferences(SharedPreferences prefs) { 159 | if (DEBUG) { 160 | if (prefs != null) { 161 | StringBuilder sb = new StringBuilder(); 162 | sb.append("SharedPreferences{\n"); 163 | for (Map.Entry entry : prefs.getAll().entrySet()) { 164 | sb.append(debugObject(entry.getKey(), entry.getValue())); 165 | } 166 | sb.append("}"); 167 | Log.d(TAG, getMsg(sb.toString())); 168 | } else { 169 | Log.e(TAG, getMsg("Error : Expected SharedPreferences is null")); 170 | } 171 | } 172 | } 173 | 174 | public static void JSONObject(JSONObject jsonObject) { 175 | if (DEBUG) { 176 | if (jsonObject != null) { 177 | StringBuilder sb = new StringBuilder(); 178 | sb.append("JsonObject{\n"); 179 | Iterator s = jsonObject.keys(); 180 | while (s.hasNext()) { 181 | String key = s.next(); 182 | try { 183 | sb.append(debugObject(key, jsonObject.get(key))); 184 | } catch (JSONException e) { 185 | e.printStackTrace(); 186 | } 187 | } 188 | sb.append("}"); 189 | Log.i(TAG, getMsg(sb.toString())); 190 | } else { 191 | Log.e(TAG, getMsg("Error : Expected JSONObject is null")); 192 | } 193 | } 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrendra/codefiesta/utils/HtmlUtils.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta.utils; 2 | 3 | /** 4 | * Created by amrendrk on 5/15/16. 5 | */ 6 | public class HtmlUtils { 7 | 8 | public static String getLink(String text, String url) { 9 | StringBuilder sb = new StringBuilder(); 10 | sb.append("").append(text).append(""); 11 | return sb.toString(); 12 | } 13 | 14 | public static String getBold(String text) { 15 | StringBuilder sb = new StringBuilder(); 16 | sb.append("").append(text).append(""); 17 | return sb.toString(); 18 | } 19 | 20 | public static String getItalic(String text) { 21 | StringBuilder sb = new StringBuilder(); 22 | sb.append("").append(text).append(""); 23 | return sb.toString(); 24 | } 25 | 26 | public static String getUnderline(String text) { 27 | StringBuilder sb = new StringBuilder(); 28 | sb.append("").append(text).append(""); 29 | return sb.toString(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrendra/codefiesta/utils/TimerUtil.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta.utils; 2 | 3 | /** 4 | * Created by Amrendra Kumar on 08/05/16. 5 | */ 6 | public class TimerUtil { 7 | long days; 8 | long hours; 9 | long min; 10 | long sec; 11 | 12 | public long getDays() { 13 | return days; 14 | } 15 | 16 | public long getHours() { 17 | return hours; 18 | } 19 | 20 | public long getMin() { 21 | return min; 22 | } 23 | 24 | public long getSec() { 25 | return sec; 26 | } 27 | 28 | public TimerUtil(long diff) { 29 | days = diff / DateUtils.SEC_IN_ONE_DAY; 30 | diff %= DateUtils.SEC_IN_ONE_DAY; 31 | 32 | hours = diff / DateUtils.SEC_IN_ONE_HOUR; 33 | diff %= DateUtils.SEC_IN_ONE_HOUR; 34 | 35 | min = diff / DateUtils.SEC_IN_ONE_MINUTE; 36 | diff %= DateUtils.SEC_IN_ONE_MINUTE; 37 | 38 | sec = diff; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrendra/codefiesta/utils/TrackingConstants.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta.utils; 2 | 3 | /** 4 | * Created by Amrendra Kumar on 17/04/16. 5 | */ 6 | public class TrackingConstants { 7 | public static final String CURRENT_FRAGMENT_SCREEN_NAME = "curr_comp_frag"; 8 | public static final String PAST_FRAGMENT_SCREEN_NAME = "past_comp_frag"; 9 | public static final String FUTURE_FRAGMENT_SCREEN_NAME = "future_comp_frag"; 10 | public static final String SELECT_COMP_FRAGMENT_SCREEN_NAME = "select_com_setting_frag"; 11 | 12 | public static final String LIST_ACTIVITY_SCREEN_NAME = "list_act"; 13 | public static final String DETAIL_ACTIVITY_SCREEN_NAME = "detail_act"; 14 | public static final String SPLASH_ACTIVITY_SCREEN_NAME = "splash_act"; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrendra/codefiesta/utils/UserPreferences.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta.utils; 2 | 3 | import android.content.Context; 4 | import android.content.SharedPreferences; 5 | 6 | /** 7 | * Created by Amrendra Kumar on 24/04/16. 8 | */ 9 | public class UserPreferences { 10 | private static final String SHARED_PREF_FILE_NAME = "codefiesta.pref"; 11 | 12 | SharedPreferences mSharedPreference; 13 | SharedPreferences.Editor mEditor; 14 | 15 | static UserPreferences mSharedPreferenceMgr = null; 16 | 17 | private UserPreferences(Context context) { 18 | mSharedPreference = context.getSharedPreferences(SHARED_PREF_FILE_NAME, Context.MODE_PRIVATE); 19 | mEditor = mSharedPreference.edit(); 20 | } 21 | 22 | public static UserPreferences getInstance(Context context) { 23 | if (mSharedPreferenceMgr == null) { 24 | mSharedPreferenceMgr = new UserPreferences(context); 25 | } 26 | return mSharedPreferenceMgr; 27 | } 28 | 29 | public void removeKey(final String key) { 30 | mEditor.remove(key).commit(); 31 | } 32 | 33 | public int readValue(final String key, final int defaultValue) { 34 | return mSharedPreference.getInt(key, defaultValue); 35 | } 36 | 37 | public void writeValue(final String key, final int value) { 38 | mEditor.putInt(key, value).commit(); 39 | } 40 | 41 | public long readValue(final String key, final long defaultValue) { 42 | return mSharedPreference.getLong(key, defaultValue); 43 | } 44 | 45 | public void writeValue(final String key, final long value) { 46 | mEditor.putLong(key, value).commit(); 47 | } 48 | 49 | public double readValue(final String key, final double defaultValue) { 50 | return Double.longBitsToDouble(mSharedPreference.getLong(key, Double.doubleToLongBits(defaultValue))); 51 | } 52 | 53 | public void writeValue(final String key, final double value) { 54 | mEditor.putLong(key, Double.doubleToRawLongBits(value)).commit(); 55 | } 56 | 57 | public boolean readValue(String key, boolean defaultValue) { 58 | return mSharedPreference.getBoolean(key, defaultValue); 59 | } 60 | 61 | public void writeValue(final String key, final boolean value) { 62 | mEditor.putBoolean(key, value).commit(); 63 | } 64 | 65 | public String readValue(final String key, final String defaultValue) { 66 | return mSharedPreference.getString(key, defaultValue); 67 | } 68 | 69 | public void writeValue(final String key, final String value) { 70 | mEditor.putString(key, value).commit(); 71 | } 72 | 73 | public void clear() { 74 | mEditor.clear().commit(); 75 | } 76 | 77 | 78 | public void debug() { 79 | Debug.preferences(mSharedPreference); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrendra/codefiesta/widget/CodeFiestaWidget.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta.widget; 2 | 3 | import android.app.PendingIntent; 4 | import android.appwidget.AppWidgetManager; 5 | import android.appwidget.AppWidgetProvider; 6 | import android.content.ComponentName; 7 | import android.content.Context; 8 | import android.content.Intent; 9 | import android.widget.RemoteViews; 10 | 11 | import com.amrendra.codefiesta.R; 12 | import com.amrendra.codefiesta.ui.activities.MainActivity; 13 | import com.amrendra.codefiesta.utils.AppUtils; 14 | import com.amrendra.codefiesta.utils.Debug; 15 | 16 | /** 17 | * Created by amrendrk on 5/16/16. 18 | */ 19 | public class CodeFiestaWidget extends AppWidgetProvider { 20 | 21 | public CodeFiestaWidget() { 22 | 23 | } 24 | 25 | public static void onUpdate(Context context, AppWidgetManager appWidgetManager, int appWidgetId) { 26 | RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_layout); 27 | Intent intent = new Intent(context, MainActivity.class); 28 | PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0); 29 | views.setOnClickPendingIntent(R.id.widget_title_bar, pendingIntent); 30 | views.setRemoteAdapter(R.id.contest_list_widget, new Intent(context, WidgetService.class)); 31 | views.setEmptyView(R.id.contest_list_widget, R.id.contest_list_widget_empty); 32 | appWidgetManager.updateAppWidget(appWidgetId, views); 33 | } 34 | 35 | @Override 36 | public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { 37 | for (int appWidgetId : appWidgetIds) { 38 | onUpdate(context, appWidgetManager, appWidgetId); 39 | } 40 | } 41 | 42 | @Override 43 | public void onReceive(Context context, Intent intent) { 44 | super.onReceive(context, intent); 45 | if (intent != null) { 46 | Debug.e("intent : " + intent.getAction(), false); 47 | if (intent.getAction().equals(AppUtils.BROADCAST_DATA_UPDATED)) { 48 | Debug.e("Need to update widget", false); 49 | AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); 50 | int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, getClass())); 51 | appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.contest_list_widget); 52 | } 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrendra/codefiesta/widget/WidgetDataProvider.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta.widget; 2 | 3 | import android.content.ContentResolver; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.database.Cursor; 7 | import android.net.Uri; 8 | import android.widget.RemoteViews; 9 | import android.widget.RemoteViewsService; 10 | 11 | import com.amrendra.codefiesta.R; 12 | import com.amrendra.codefiesta.db.DBContract; 13 | import com.amrendra.codefiesta.model.Contest; 14 | import com.amrendra.codefiesta.utils.AppUtils; 15 | import com.amrendra.codefiesta.utils.CustomDate; 16 | import com.amrendra.codefiesta.utils.DateUtils; 17 | import com.amrendra.codefiesta.utils.Debug; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | 22 | /** 23 | * Created by amrendrk on 5/16/16. 24 | */ 25 | public class WidgetDataProvider implements RemoteViewsService.RemoteViewsFactory { 26 | 27 | List contests = null; 28 | Context mContext = null; 29 | ContentResolver mContentResolver = null; 30 | 31 | public WidgetDataProvider(Context context, Intent intent) { 32 | Debug.c(); 33 | mContext = context; 34 | mContentResolver = mContext.getContentResolver(); 35 | } 36 | 37 | @Override 38 | public RemoteViews getViewAt(int position) { 39 | RemoteViews view = new RemoteViews(mContext.getPackageName(), 40 | R.layout.widget_list_item); 41 | Contest c = contests.get(position); 42 | final int resourceId = c.getWebsite().getId(); 43 | String resourceName = AppUtils.getResourceName(mContext, resourceId); 44 | final String shortResourceName = AppUtils.getGoodResourceName(resourceName); 45 | view.setTextViewText(R.id.contest_title_tv, c.getEvent()); 46 | view.setTextViewText(R.id.contest_website_tv, shortResourceName); 47 | view.setImageViewResource(R.id.resource_logo, AppUtils.getImageForResource(resourceName)); 48 | final long starTime = DateUtils.getEpochTime(c.getStart()); 49 | final long endTime = DateUtils.getEpochTime(c.getEnd()); 50 | final CustomDate startDate = new CustomDate(DateUtils.epochToDateTimeLocalShow(starTime)); 51 | final CustomDate endDate = new CustomDate(DateUtils.epochToDateTimeLocalShow(endTime)); 52 | 53 | view.setTextViewText(R.id.start_time, startDate.getFullTime()); 54 | view.setTextViewText(R.id.end_time, endDate.getFullTime()); 55 | return view; 56 | } 57 | 58 | private void initData() { 59 | if (contests != null) { 60 | contests.clear(); 61 | } 62 | contests = new ArrayList<>(); 63 | Debug.c(); 64 | Uri uri = DBContract.ContestEntry.buildLiveContestUri(DateUtils.getCurrentEpochTime()); 65 | Cursor cursor = mContentResolver.query( 66 | uri, 67 | null, 68 | null, 69 | null, 70 | DBContract.ContestEntry.CONTEST_END_COL + " ASC" 71 | ); 72 | if (cursor != null && cursor.getCount() > 0) { 73 | Debug.e("Fetch for widget : " + cursor.getCount(), false); 74 | cursor.moveToFirst(); 75 | while (!cursor.isAfterLast()) { 76 | contests.add(Contest.cursorToContest(mContext, cursor)); 77 | cursor.moveToNext(); 78 | } 79 | } 80 | if (cursor != null) { 81 | cursor.close(); 82 | } 83 | } 84 | 85 | @Override 86 | public void onCreate() { 87 | Debug.c(); 88 | } 89 | 90 | @Override 91 | public void onDataSetChanged() { 92 | Debug.c(); 93 | initData(); 94 | } 95 | 96 | @Override 97 | public void onDestroy() { 98 | contests.clear(); 99 | } 100 | 101 | @Override 102 | public int getCount() { 103 | return contests.size(); 104 | } 105 | 106 | 107 | @Override 108 | public RemoteViews getLoadingView() { 109 | return null; 110 | } 111 | 112 | @Override 113 | public int getViewTypeCount() { 114 | return 1; 115 | } 116 | 117 | @Override 118 | public long getItemId(int position) { 119 | return position; 120 | } 121 | 122 | @Override 123 | public boolean hasStableIds() { 124 | return true; 125 | } 126 | 127 | } 128 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrendra/codefiesta/widget/WidgetService.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta.widget; 2 | 3 | import android.content.Intent; 4 | import android.widget.RemoteViewsService; 5 | 6 | /** 7 | * Created by amrendrk on 5/16/16. 8 | */ 9 | public class WidgetService extends RemoteViewsService { 10 | @Override 11 | public RemoteViewsFactory onGetViewFactory(Intent intent) { 12 | return new WidgetDataProvider(this, intent); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/credits.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-hdpi/credits.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/feedback.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-hdpi/feedback.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/future.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-hdpi/future.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/icon_notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-hdpi/icon_notification.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/live.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-hdpi/live.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/open_source.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-hdpi/open_source.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/past.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-hdpi/past.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/rate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-hdpi/rate.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-hdpi/refresh.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-hdpi/settings.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/share_app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-hdpi/share_app.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/credits.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-mdpi/credits.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/feedback.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-mdpi/feedback.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/future.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-mdpi/future.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/icon_notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-mdpi/icon_notification.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/live.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-mdpi/live.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/open_source.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-mdpi/open_source.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/past.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-mdpi/past.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/rate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-mdpi/rate.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-mdpi/refresh.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-mdpi/save.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-mdpi/settings.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/share_app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-mdpi/share_app.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/logo128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-nodpi/logo128.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/button_ripple.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/calendar_add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xhdpi/calendar_add.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/calendar_added.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xhdpi/calendar_added.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/calendar_permission.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xhdpi/calendar_permission.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/credits.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xhdpi/credits.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/egg_empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xhdpi/egg_empty.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/egg_error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xhdpi/egg_error.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/feedback.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xhdpi/feedback.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/future.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xhdpi/future.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/icon_notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xhdpi/icon_notification.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/live.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xhdpi/live.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/notification_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xhdpi/notification_off.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/notification_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xhdpi/notification_on.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/open_source.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xhdpi/open_source.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/past.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xhdpi/past.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/rate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xhdpi/rate.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xhdpi/refresh.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xhdpi/save.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xhdpi/settings.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/share.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xhdpi/share.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/share_app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xhdpi/share_app.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/weblink.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xhdpi/weblink.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/credits.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xxhdpi/credits.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/feedback.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xxhdpi/feedback.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/future.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xxhdpi/future.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/icon_notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xxhdpi/icon_notification.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/live.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xxhdpi/live.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/open_source.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xxhdpi/open_source.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/past.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xxhdpi/past.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/rate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xxhdpi/rate.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xxhdpi/refresh.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xxhdpi/save.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xxhdpi/settings.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/share_app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xxhdpi/share_app.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/credits.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xxxhdpi/credits.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/feedback.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xxxhdpi/feedback.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/future.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xxxhdpi/future.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/icon_notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xxxhdpi/icon_notification.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/open_source.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xxxhdpi/open_source.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/past.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xxxhdpi/past.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/rate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xxxhdpi/rate.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xxxhdpi/refresh.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xxxhdpi/save.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xxxhdpi/settings.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/share_app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xxxhdpi/share_app.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/widget_preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable-xxxhdpi/widget_preview.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/button_ripple.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/codechef.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable/codechef.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/codeforces.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable/codeforces.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/hackerearth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable/hackerearth.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/hackerrank.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable/hackerrank.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/kaggle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable/kaggle.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/nav_item_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/round_tv_top.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/splash.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/spoj.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable/spoj.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/topcoder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/drawable/topcoder.png -------------------------------------------------------------------------------- /app/src/main/res/layout-sw600dp/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 12 | 13 | 14 | 18 | 19 | 20 | 25 | 26 | 27 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 12 | 13 | 14 | 18 | 19 | 20 | 21 | 25 | 26 | 27 | 28 | 29 | 30 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /app/src/main/res/layout/coloress_divider.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/layout/divider.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/layout/error_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_credits.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 15 | 16 | 21 | 22 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_list.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 13 | 14 | 27 | 28 | 33 | 34 | 39 | 40 | 41 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /app/src/main/res/layout/loading_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/layout/nav_header_row.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 16 | 17 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/layout/select_item_row.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 23 | 24 | 25 | 39 | 40 | 52 | 53 | -------------------------------------------------------------------------------- /app/src/main/res/layout/selection_fragment.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 15 | 16 | 22 | 23 | 24 | 41 | 42 | -------------------------------------------------------------------------------- /app/src/main/res/layout/splash_activity.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 17 | 18 | 30 | 31 | 44 | 45 | 46 | 54 | -------------------------------------------------------------------------------- /app/src/main/res/layout/toolbar.xml: -------------------------------------------------------------------------------- 1 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/layout/widget_layout.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 13 | 14 | 24 | 25 | 30 | 31 | 39 | 40 | 47 | 48 | 49 | 50 | 51 | 52 | 57 | 58 | 65 | 66 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /app/src/main/res/layout/widget_list_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 17 | 18 | 24 | 25 | 35 | 36 | 46 | 47 | 48 | 60 | 61 | 62 | 63 | 68 | 69 | 76 | 77 | 88 | 89 | 90 | 95 | 96 | 103 | 104 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_nav.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 8 | 9 | 13 | 17 | 21 | 22 | 23 | 26 | 27 | 31 | 32 | 36 | 37 | 41 | 42 | 43 | 44 | 47 | 48 | 52 | 53 | 57 | 58 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/values-v14/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 0dp 4 | -------------------------------------------------------------------------------- /app/src/main/res/values-v19/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 8dp 5 | 6 | 7 | 150dp 8 | 8dp 9 | 36sp 10 | 18sp 11 | 40dp 12 | 13 | 2dp 14 | 2dp 15 | 1dp 16 | 17 | 18 | 8dp 19 | 10dp 20 | 10dp 21 | 16dp 22 | 18sp 23 | 4dp 24 | 16sp 25 | 8dp 26 | 32sp 27 | 16sp 28 | 18sp 29 | 16sp 30 | 4dp 31 | 16sp 32 | 2dp 33 | 4dp 34 | 40dp 35 | 32dp 36 | 10dp 37 | 38 | 24sp 39 | 18sp 40 | 2 41 | 16dp 42 | 12dp 43 | 4dp 44 | 4dp 45 | 46 | 4dp 47 | 1dp 48 | 4dp 49 | 70dp 50 | 16sp 51 | 52 | 53 | 144dp 54 | 16dp 55 | 40sp 56 | 8dp 57 | 20sp 58 | 59 | 16sp 60 | 61 | 62 | 63 | 24dp 64 | 16sp 65 | 16sp 66 | 12dp 67 | 14sp 68 | 4dp 69 | 2dp 70 | 4dp 71 | 1 72 | 80dp 73 | 180dp 74 | 75 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | CodeZera 3 | <CodeZera/> 4 | Hello World! 5 | Lets Get Started 6 | Splash Screen 7 | ListActivity 8 | Settings 9 | DetailActivity 10 | open drawer 11 | close drawer 12 | 13 | Live 14 | Upcoming 15 | Past 16 | Settings 17 | Rate App 18 | Share App 19 | Feedback 20 | Open Source 21 | Credits 22 | 23 | Live Events 24 | Upcoming Events 25 | Past Events 26 | Event Details 27 | Today\'s Events 28 | 29 | Navigation Menu 30 | 31 | Grant calendar permission 32 | Add to calendar 33 | Remove from calendar 34 | Add notification 35 | Remove notification 36 | Visit website 37 | Sharing is fun 38 | Refreshing contests data from web 39 | 40 | Share 41 | 42 | Status 43 | Start 44 | Started 45 | End 46 | Ended 47 | 48 | days 49 | hours 50 | min 51 | sec 52 | 53 | Save 54 | 55 | 56 | @string/nav_current 57 | @string/nav_upcoming 58 | @string/nav_past 59 | @string/nav_settings 60 | @string/nav_rate 61 | @string/nav_feedback 62 | 63 | 64 | com.amrendra.codefiesta 65 | com.amrendra.codefiesta 66 | 67 | 68 | No Contests found!! 69 | 70 | 71 | Contest <b>%1$s</b> @ <b>%2$s</b> already 72 | started. 73 | 74 | Contest <b>%1$s</b> @ <b>%2$s</b> already 75 | ended. 76 | 77 | 78 | Please wait while we 79 | fetch calendar event status for <b>%1$s</b>. 80 | 81 | Please wait while we 82 | fetch notification status for <b>%1$s</b>. 83 | 84 | Event <b>%1$s</b> added to your calendar. 85 | 86 | Calendar Read/Write permission denied. 87 | 88 | Calendar Read/Write permission granted. 89 | 90 | No calendar accounts found!! Please login to 91 | google calendar and try again 92 | 93 | 94 | <b>Error</b> occurred in adding 95 | <b>%1$s</b> to your 96 | calendar. 97 | 98 | Event <b>%1$s</b> removed from your calendar. 99 | <b>Error</b> occurred in removing event 100 | <b>%1$s</b> from your 101 | calendar. 102 | 103 | 104 | 105 | Reminder notification added 1 hour before start of <b>%1$s</b> 106 | <b>Error</b> occurred in setting 107 | reminder notification for <b>%1$s</b>. 108 | 109 | Reminder notification deleted for <b>%1$s</b> 110 | <b>Error</b> occurred in deleting 111 | reminder notification for <b>%1$s</b> 112 | 113 | %1$s <br> 114 | Starts at <b>%2$s</b> 115 | 116 | Credits Info 117 | Feedback on %1$s; version %2$s 118 | Send email using … 119 | Playstore app not found!! 120 | Unexpected error occurred in opening the website. 121 | 122 | 123 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | 15 | 16 | 20 | 21 | 28 | 29 | 34 | 35 | 43 | 44 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /app/src/main/res/xml-v17/widget_info.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/src/main/res/xml/app_tracker.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 300 5 | 6 | 7 | true 8 | 9 | 10 | UA-40448102-1 11 | 12 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/xml/authenticator.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/xml/syncadapter.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/xml/widget_info.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/src/test/java/com/amrendra/codefiesta/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * To work on unit tests, switch the Test Artifact in the Build Variants view. 9 | */ 10 | public class ExampleUnitTest { 11 | @Test 12 | public void addition_isCorrect() throws Exception { 13 | assertEquals(4, 2 + 2); 14 | } 15 | } -------------------------------------------------------------------------------- /app/src/test/java/com/amrendra/codefiesta/utils/DateUtilsTest.java: -------------------------------------------------------------------------------- 1 | package com.amrendra.codefiesta.utils; 2 | 3 | import junit.framework.Assert; 4 | 5 | import org.junit.After; 6 | import org.junit.Before; 7 | import org.junit.Test; 8 | 9 | import java.util.TimeZone; 10 | 11 | /** 12 | * Created by Amrendra Kumar on 09/04/16. 13 | */ 14 | public class DateUtilsTest { 15 | 16 | String timeStr[] = { 17 | "2016-04-08T18:30:00", 18 | "2016-04-08T08:30:00", 19 | "2016-04-11T09:30:00", 20 | "2016-04-01T09:32:00", 21 | }; 22 | 23 | String timeStrGMT[] = { 24 | "2016-04-08 18:30:00", 25 | "2016-04-08 08:30:00", 26 | "2016-04-11 09:30:00", 27 | "2016-04-01 09:32:00", 28 | }; 29 | 30 | String timeStrIST[] = { 31 | "2016-04-09 00:00:00", 32 | "2016-04-08 14:00:00", 33 | "2016-04-11 15:00:00", 34 | "2016-04-01 15:02:00", 35 | }; 36 | 37 | long epochTimes[] = { 38 | 1460140200, 39 | 1460104200, 40 | 1460367000, 41 | 1459503120, 42 | }; 43 | 44 | @Before 45 | public void setUp() throws Exception { 46 | } 47 | 48 | @After 49 | public void tearDown() throws Exception { 50 | 51 | } 52 | 53 | @Test 54 | public void testGetEpochTime() throws Exception { 55 | for (int i = 0; i < timeStr.length; i++) { 56 | long t = DateUtils.getEpochTime(timeStr[i]); 57 | Assert.assertEquals("Epoch time different", epochTimes[i], t); 58 | } 59 | } 60 | 61 | @Test 62 | public void testEpochToDateTimeGMT() throws Exception { 63 | for (int i = 0; i < epochTimes.length; i++) { 64 | String t = DateUtils.epochToDateTimeGmt(epochTimes[i]); 65 | Assert.assertEquals("Epoch time different", timeStrGMT[i], t); 66 | } 67 | } 68 | 69 | @Test 70 | public void testEpochToDateTimeLocal() throws Exception { 71 | TimeZone.setDefault(TimeZone.getTimeZone("IST")); 72 | for (int i = 0; i < epochTimes.length; i++) { 73 | String t = DateUtils.epochToDateTimeLocal(epochTimes[i]); 74 | Assert.assertEquals("Epoch time different", timeStrIST[i], t); 75 | } 76 | } 77 | 78 | } -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:2.2.3' 9 | classpath 'com.google.gms:google-services:2.0.0-alpha6' 10 | // NOTE: Do not place your application dependencies here; they belong 11 | // in the individual module build.gradle files 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | jcenter() 18 | } 19 | } 20 | 21 | task clean(type: Delete) { 22 | delete rootProject.buildDir 23 | } 24 | -------------------------------------------------------------------------------- /design.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/design.pdf -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 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 -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amrendra18/codezera/d2839acbfb79a6e342624c62401efd3e05b085dd/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Dec 21 20:36:52 CST 2016 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-2.14.1-all.zip 7 | -------------------------------------------------------------------------------- /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 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | --------------------------------------------------------------------------------