├── .gitignore ├── .gitmodules ├── .travis.yml ├── README.md ├── RapidAndroidApp.iml ├── app ├── build.gradle ├── proguard-rules.pro └── src │ ├── debug │ └── res │ │ └── values │ │ ├── api_keys.xml │ │ └── external_sources.xml │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── soi │ │ │ └── rapidandroidapp │ │ │ ├── BaseApplication.java │ │ │ ├── api │ │ │ ├── GsonInstance.java │ │ │ ├── common │ │ │ │ ├── AbstractApiManager.java │ │ │ │ ├── ApiRequestAttrs.java │ │ │ │ └── BaseApiManager.java │ │ │ ├── errorhandlers │ │ │ │ └── ApiErrorHandler.java │ │ │ ├── interceptors │ │ │ │ ├── ApiRequestInterceptor.java │ │ │ │ └── FoursquareApiRequestInterceptor.java │ │ │ ├── managers │ │ │ │ ├── ApiManager.java │ │ │ │ ├── FoursquareApiManager.java │ │ │ │ ├── common │ │ │ │ │ ├── AbstractAsyncTask.java │ │ │ │ │ └── BaseEvent.java │ │ │ │ ├── events │ │ │ │ │ ├── FoursquareExploreEvent.java │ │ │ │ │ ├── FoursquareSearchEvent.java │ │ │ │ │ └── common │ │ │ │ │ │ ├── HttpNotfoundEvent.java │ │ │ │ │ │ ├── HttpServerErrorEvent.java │ │ │ │ │ │ ├── HttpUnauthorizedEvent.java │ │ │ │ │ │ ├── HttpUpgradeRequiredEvent.java │ │ │ │ │ │ └── NotInternetEvent.java │ │ │ │ ├── foursquare │ │ │ │ │ └── FoursquareResources.java │ │ │ │ └── net │ │ │ │ │ └── response │ │ │ │ │ └── foursquare │ │ │ │ │ ├── explore │ │ │ │ │ ├── Explore.java │ │ │ │ │ └── common │ │ │ │ │ │ ├── Category.java │ │ │ │ │ │ ├── Group.java │ │ │ │ │ │ ├── Icon.java │ │ │ │ │ │ ├── Item.java │ │ │ │ │ │ ├── Location.java │ │ │ │ │ │ ├── Response.java │ │ │ │ │ │ └── Venue.java │ │ │ │ │ └── search │ │ │ │ │ ├── SearchResult.java │ │ │ │ │ └── common │ │ │ │ │ ├── SearchMeta.java │ │ │ │ │ └── SearchResponse.java │ │ │ └── services │ │ │ │ ├── AppApiService.java │ │ │ │ └── FoursquareApiService.java │ │ │ ├── database │ │ │ ├── TABLE_NAMES.java │ │ │ └── UserContract.java │ │ │ ├── events │ │ │ └── common │ │ │ │ └── BusProvider.java │ │ │ ├── managers │ │ │ ├── AnalyticsManager.java │ │ │ ├── EnvironmentManager.java │ │ │ ├── LoggerWrapper.java │ │ │ ├── NetworkManager.java │ │ │ └── SessionManager.java │ │ │ ├── models │ │ │ ├── SocialShareModel.java │ │ │ ├── SocialType.java │ │ │ ├── User.java │ │ │ └── common │ │ │ │ ├── DBModel.java │ │ │ │ ├── Environment.java │ │ │ │ └── IBaseModel.java │ │ │ ├── modules │ │ │ ├── AndroidModule.java │ │ │ ├── AppModule.java │ │ │ ├── Injector.java │ │ │ ├── RootModule.java │ │ │ └── SocialManager.java │ │ │ ├── ui │ │ │ ├── LoginActivity.java │ │ │ ├── MainActivity.java │ │ │ ├── adapters │ │ │ │ ├── NavigationDrawerAdapter.java │ │ │ │ └── PlacesAdapter.java │ │ │ ├── common │ │ │ │ ├── AbstractActivity.java │ │ │ │ ├── AbstractFragmentActivity.java │ │ │ │ └── BaseFragment.java │ │ │ ├── dialog │ │ │ │ ├── AlertDialogFragment.java │ │ │ │ ├── ErrorDialogFragment.java │ │ │ │ └── ProgressDialogFragment.java │ │ │ └── fragments │ │ │ │ ├── HomeFragment.java │ │ │ │ ├── ItemActivity.java │ │ │ │ └── ItemViewFragment.java │ │ │ └── utilities │ │ │ ├── Constants.java │ │ │ ├── DialogsHelper.java │ │ │ ├── ReflectionUtils.java │ │ │ ├── StringUtils.java │ │ │ └── Utils.java │ └── res │ │ ├── anim │ │ └── rotate.xml │ │ ├── drawable-hdpi │ │ ├── drawer_user.png │ │ ├── fb_icon.png │ │ ├── ic_launcher.png │ │ └── twitter_icon.png │ │ ├── drawable-mdpi │ │ └── ic_launcher.png │ │ ├── drawable-xhdpi │ │ └── ic_launcher.png │ │ ├── drawable-xxhdpi │ │ └── ic_launcher.png │ │ ├── drawable │ │ ├── dialog_background.xml │ │ ├── list_item_bg_normal.xml │ │ ├── list_item_bg_pressed.xml │ │ ├── list_selector.xml │ │ └── loader.png │ │ ├── layout │ │ ├── activity_fragment.xml │ │ ├── activity_login.xml │ │ ├── activity_main.xml │ │ ├── activity_navigation_drawer.xml │ │ ├── activity_scroll_fragment.xml │ │ ├── drawer_list_item.xml │ │ ├── fragment_home.xml │ │ ├── fragment_item_view.xml │ │ ├── item_venue.xml │ │ └── layout_dialog.xml │ │ ├── menu │ │ ├── login.xml │ │ └── menu_main.xml │ │ ├── values-v21 │ │ └── styles.xml │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── api_keys.xml │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── external_sources.xml │ │ ├── generic_strings.xml │ │ ├── strings.xml │ │ └── styles.xml │ ├── release │ └── res │ │ └── values │ │ ├── api_integration_keys.xml │ │ ├── api_keys.xml │ │ └── external_sources.xml │ └── test │ └── java │ └── com │ └── soi │ └── rapidandroidapp │ ├── TestBaseApplication.java │ ├── api │ └── managers │ │ └── FoursquareApiManagerTest.java │ ├── managers │ └── EnvironmentManagerTest.java │ ├── models │ └── UserModelTest.java │ ├── modules │ ├── MockAppTestModule.java │ └── RootTestModule.java │ └── test │ └── support │ ├── RobolectricDataBindingTestRunner.java │ ├── ShadowMultiDex.java │ └── UnitTestSpecification.java ├── build.gradle ├── circle.yml ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── scripts ├── robolectric-support.gradle └── run-circleci.sh └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | /captures 2 | 3 | #built application files 4 | *.apk 5 | *.ap_ 6 | 7 | # files for the dex VM 8 | *.dex 9 | 10 | # Java class files 11 | *.class 12 | 13 | # generated files 14 | bin/ 15 | gen/ 16 | 17 | # Local configuration file (sdk path, etc) 18 | /local.properties 19 | 20 | # Windows thumbnail db 21 | Thumbs.db 22 | 23 | # OSX files 24 | .DS_Store 25 | 26 | # Eclipse project files 27 | .classpath 28 | .project 29 | 30 | # Android Studio 31 | *.iml 32 | .idea 33 | #.idea/workspace.xml - remove # and delete .idea if it better suit your needs. 34 | .gradle 35 | build/ 36 | 37 | /app/fabric.properties 38 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "libraries/facebook-android-sdk"] 2 | path = libraries/facebook-android-sdk 3 | url = git@github.com:facebook/facebook-android-sdk.git 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: android 2 | 3 | android: 4 | components: 5 | - tools 6 | - build-tools-23.0.2 7 | - android-23 8 | - extra-google-google_play_services 9 | - extra-google-m2repository 10 | - extra-android-m2repository 11 | 12 | script: 13 | ./gradlew :app:testDebug :app:connectedAndroidTest -PtravisCi -PdisablePreDex -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Rapid Android Development Template [NOT SUPPORTED] 2 | ================================== 3 | 4 | **master:** [![Build Status](https://travis-ci.org/spirosoik/RapidAndroidFramework.svg?branch=master)](https://travis-ci.org/spirosoik/RapidAndroidFramework) 5 | 6 | **Published in:** [![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-RapidAndroidFramework-green.svg?style=flat)](https://android-arsenal.com/details/1/2258) 7 | 8 | ## Tools 9 | Android Studio 1.x and Gradle 2.x 10 | 11 | ## IDE Tools 12 | * [Dagger Plugin] (https://github.com/square/dagger-intellij-plugin) 13 | * [Android ButterKnife Zelezny] (http://plugins.jetbrains.com/plugin/7369) 14 | 15 | ## Libraries 16 | * [Ollie 0.3.2-SNAPSHOT](https://github.com/pardom/Ollie) 17 | * [Retrofit 1.9.0](http://square.github.io/retrofit/) 18 | * [OkHttp 2.4.0](http://square.github.io/okhttp/) 19 | * [Otto Eventbus 1.3.8](http://square.github.io/otto/) 20 | * [Dagger 1.2.2](http://square.github.io/dagger/) 21 | * [ButterKnife 6.1.0](https://github.com/JakeWharton/butterknife) 22 | * [Otto Picasso 2.5.2] (http://square.github.io/picasso/) 23 | * [UI validation library Saripaar](https://github.com/ragunathjawahar/android-saripaar) 24 | 25 | ## 3rd Parties Social (as gradle imports) 26 | * Facebook SDK 27 | * Twitter SDK by Fabric 28 | * Crashlytics SDK by Fabric 29 | 30 | Note: You can change the keys into ```api_keys.xml```. For Crashlytics you can change it into ```AndroidManifest.xml```. There is a ```SocialManager``` class 31 | to use for social actions. 32 | 33 | ## Check the documentation 34 | 35 | * [Wiki](https://github.com/spirosoik/RapidAndroidApp/wiki) 36 | 37 | ## Testing 38 | * Robolectric for unit testing 39 | * Shell scripts to run tests fast. Check ```scripts``` folder. 40 | * CircleCI continuous integration server 41 | * Calabash (SOON) 42 | 43 | ## Proguard 44 | * Proguard enable for ```LIVE```, ```UAT``` environments to minify the build 45 | 46 | 47 | ### Gradle 48 | * Gradle configuration for multi-environment support 49 | 50 | ### Environment Manager 51 | * Multi-environment support (```LIVE```, ```UAT```, ```STAGING```) 52 | * Assigns dynamically environment for the current build 53 | * Assigns dynamically the API URL for the current build 54 | * Assigns dynamically the API logging level for the current build 55 | * Assigns dynamically the logging level for the current build 56 | * Decides if the app according to the environment can track in analytics 57 | * Decides if the app according to the environment can receive notifications 58 | * Decides if the app according to the environment can track bugs in crashlytics 59 | 60 | ### API Managers 61 | * OkHttpClient support to make the HTTP requests for API 62 | * ```AbstractApiManager``` with Retrofit based on the Environment manager API URL 63 | * ```FULL/NONE``` logging for API based on the Environment manager ```LOGLEVEL``` of API 64 | * AbstractAsyncTask which produces events in a public BUS 65 | * Event Base architecture with Otto for each response after an ```AbstractAsyncTask``` 66 | * Access to API methods via Reflection. The only thing you must set up is the ```ApiRequestAttrs```. Example in wiki 67 | 68 | ### Activities 69 | * Dagger for dependency injection 70 | * ButterKnife views injection to use this -> ```@InjectView(R.id.btnTest)``` to minimize and remove the old ```(Button) findViewById(R.id.btnTest)``` 71 | * Each Activity/FragmentActivity registered to listen the Event BUS 72 | * Customizable/Overridable action bar for each Activity/FragmentActivity 73 | * ```AbstractFragmentActivity``` to extended by each Fragment activity and it can contains the fragment you want. You must implement only the createFragment method 74 | * ```BaseFragment``` to be extended by each fragment as generic fragment 75 | 76 | ### Google Analytics 77 | * Support for google analytics track events and pageviews. Use ```AnalyticsManager``` 78 | 79 | License 80 | ------- 81 | 82 | Copyright 2015 Economakis Spyridon 83 | 84 | Licensed under the Apache License, Version 2.0 (the "License"); 85 | you may not use this file except in compliance with the License. 86 | You may obtain a copy of the License at 87 | 88 | http://www.apache.org/licenses/LICENSE-2.0 89 | 90 | Unless required by applicable law or agreed to in writing, software 91 | distributed under the License is distributed on an "AS IS" BASIS, 92 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 93 | See the License for the specific language governing permissions and 94 | limitations under the License. 95 | -------------------------------------------------------------------------------- /RapidAndroidApp.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /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: 'com.jakewharton.hugo' 12 | apply plugin: 'com.getkeepsafe.dexcount' 13 | 14 | repositories { 15 | maven { url 'https://maven.fabric.io/public' } 16 | } 17 | 18 | apply plugin: 'io.fabric' 19 | 20 | android { 21 | 22 | packagingOptions { 23 | exclude 'META-INF/services/javax.annotation.processing.Processor' 24 | exclude 'LICENSE.txt' 25 | exclude 'META-INF/LICENSE' 26 | exclude 'META-INF/LICENSE.txt' 27 | exclude 'META-INF/NOTICE' 28 | exclude 'LICENSE' 29 | exclude 'NOTICE' 30 | exclude 'asm-license.txt' 31 | } 32 | 33 | dexOptions { 34 | jumboMode true 35 | javaMaxHeapSize "4g" 36 | } 37 | 38 | compileSdkVersion rootProject.ext.compileSdkVersion 39 | buildToolsVersion rootProject.ext.buildToolsVersion 40 | 41 | defaultConfig { 42 | applicationId "com.soi.rapidandroidapp" 43 | minSdkVersion 14 44 | targetSdkVersion 23 45 | versionCode 1 46 | versionName "1.0" 47 | multiDexEnabled true 48 | testInstrumentationRunner "com.google.android.apps.common.testing.testrunner.GoogleInstrumentationTestRunner" 49 | } 50 | 51 | buildTypes { 52 | release { 53 | ext.enableCrashlytics = false 54 | minifyEnabled true 55 | buildConfigField "String", "ENVIRONMENT", "\"LIVE\"" 56 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 57 | } 58 | debug { 59 | buildConfigField "String", "ENVIRONMENT", "\"STAGING\"" 60 | testCoverageEnabled = true 61 | } 62 | uat { 63 | minifyEnabled true 64 | buildConfigField "String", "ENVIRONMENT", "\"UAT\"" 65 | proguardFiles getDefaultProguardFile('proguard-project.txt'), 'proguard-rules.pro' 66 | } 67 | } 68 | 69 | lintOptions { 70 | disable 'InvalidPackage' 71 | } 72 | 73 | sourceSets { main { res.srcDirs = ['src/main/res', 'src/main/res/anim'] } } 74 | 75 | productFlavors {} 76 | } 77 | 78 | dependencies { 79 | repositories { 80 | mavenCentral() 81 | } 82 | 83 | compile 'com.android.support:multidex:1.0.1' 84 | compile 'com.android.support:support-v4:23.1.1' 85 | compile 'com.android.support:appcompat-v7:23.1.1' 86 | compile 'com.android.support:recyclerview-v7:23.1.1' 87 | compile 'com.google.android.gms:play-services:8.3.0' 88 | compile 'com.mobsandgeeks:android-saripaar:1.0.2' 89 | compile 'com.michaelpardo:ollie:0.3.2-SNAPSHOT' 90 | provided 'com.michaelpardo:ollie-compiler:0.3.2-SNAPSHOT' 91 | compile 'com.squareup.picasso:picasso:2.5.2' 92 | compile 'com.squareup.retrofit:retrofit:1.9.0' 93 | compile 'com.squareup.okio:okio:1.4.0' 94 | compile 'com.squareup.okhttp:okhttp-urlconnection:2.2.0' 95 | compile 'com.squareup.okhttp:okhttp:2.4.0' 96 | compile 'com.squareup:otto:1.3.8' 97 | compile 'com.squareup.dagger:dagger:1.2.2' 98 | provided 'com.squareup.dagger:dagger-compiler:1.2.2' 99 | // Butterknife 100 | compile('com.jakewharton:butterknife:6.1.0') { 101 | exclude module: 'support-v4' 102 | } 103 | // Crashlytics Kit 104 | compile('com.crashlytics.sdk.android:crashlytics:2.3.2@aar') { 105 | transitive = true 106 | } 107 | // Twitter 108 | compile('com.twitter.sdk.android:twitter:1.6.0@aar') { 109 | transitive = true; 110 | } 111 | // Twitter compose dialog 112 | compile('com.twitter.sdk.android:tweet-composer:0.8.0@aar') { 113 | transitive = true; 114 | } 115 | // Facebook 116 | compile('com.facebook.android:facebook-android-sdk:4.1.2') { 117 | exclude module: 'bolts-android' 118 | } 119 | compile fileTree(dir: 'libs', include: ['*.jar']) 120 | testCompile 'junit:junit:4.12' 121 | testCompile 'org.mockito:mockito-core:1.9.5' 122 | testCompile('com.squareup:fest-android:1.0.+') { exclude module: 'support-v4' } 123 | testCompile('org.robolectric:robolectric:3.0') { 124 | exclude module: 'classworlds' 125 | exclude module: 'maven-artifact' 126 | exclude module: 'maven-artifact-manager' 127 | exclude module: 'maven-error-diagnostics' 128 | exclude module: 'maven-model' 129 | exclude module: 'maven-plugin-registry' 130 | exclude module: 'maven-profile' 131 | exclude module: 'maven-project' 132 | exclude module: 'maven-settings' 133 | exclude module: 'nekohtml' 134 | exclude module: 'plexus-container-default' 135 | exclude module: 'plexus-interpolation' 136 | exclude module: 'plexus-utils' 137 | exclude module: 'support-v4' 138 | // crazy but my android studio don't like this dependency and to fix it remove .idea and re import project 139 | exclude module: 'wagon-file' 140 | exclude module: 'wagon-http-lightweight' 141 | exclude module: 'wagon-http-shared' 142 | exclude module: 'wagon-provider-api' 143 | } 144 | } -------------------------------------------------------------------------------- /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 D:/Program Files (x86)/Android/android-studio/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the ProGuard 5 | # include property in project.properties. 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 | -ignorewarnings 19 | -dontoptimize 20 | -dontobfuscate 21 | -dontskipnonpubliclibraryclasses 22 | 23 | -ignorewarnings 24 | 25 | -keepattributes Exceptions, Signature, InnerClasses, *Annotation* 26 | # Allow obfuscation of android.support.v7.internal.view.menu.** 27 | # to avoid problem on Samsung 4.2.2 devices with appcompat v21 28 | # see https://code.google.com/p/android/issues/detail?id=78377 29 | -keep class !android.support.v7.internal.view.menu.MenuBuilder, !android.support.v7.internal.view.menu.SubMenuBuilder, android.support.v7.** { *; } 30 | -keep interface android.support.v7.** { *; } 31 | 32 | 33 | #BUTTERKNIFE 34 | -dontwarn butterknife.internal.** 35 | -keep class **$$ViewInjector { *; } 36 | -keepnames class * { @butterknife.InjectView *;} 37 | ###################### 38 | 39 | #OTTO BUS 40 | -keepclassmembers class ** { 41 | @com.squareup.otto.Subscribe public *; 42 | @com.squareup.otto.Produce public *; 43 | } 44 | ###################### 45 | 46 | #KOMENSKY 47 | -keep class eu.inmite.android.lib.validations.form.annotations.** { *; } 48 | -keep class * implements eu.inmite.android.lib.validations.form.iface.ICondition 49 | -keep class * implements eu.inmite.android.lib.validations.form.iface.IValidator 50 | -keep class * implements eu.inmite.android.lib.validations.form.iface.IFieldAdapter 51 | -keepclassmembers class ** { 52 | @eu.inmite.android.lib.validations.form.annotations.** *; 53 | } 54 | ###################### 55 | 56 | #DAGGER 57 | -dontwarn dagger.internal.codegen.** 58 | -keep @interface dagger.*,javax.inject.* 59 | 60 | #Keep the Modules intact 61 | -keep @dagger.Module class * 62 | 63 | #-Keep the fields annotated with @Inject of any class that is not deleted. 64 | -keepclassmembers class * { 65 | @javax.inject.* ; 66 | } 67 | 68 | #-Keep the names of classes that have fields annotated with @Inject and the fields themselves. 69 | -keepclasseswithmembernames class * { 70 | @javax.inject.* ; 71 | } 72 | 73 | #Keep the generated classes by dagger-compile 74 | -keep class **$$ModuleAdapter 75 | -keep class **$$InjectAdapter 76 | -keep class **$$StaticInjection 77 | ###################### 78 | 79 | # OKHTTP 80 | -dontwarn com.squareup.okhttp.** 81 | ###################### 82 | 83 | 84 | -------------------------------------------------------------------------------- /app/src/debug/res/values/api_keys.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 1f22812da16ce068a0369d078ed2829f224738e2 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/debug/res/values/external_sources.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 216896791667977 4 | audioboxlive 5 | http://www.youtube.com/user/audioboxliveradio 6 | soundcloud://users:7697512 7 | 8 | https://soundcloud.com/audioboxlive/abc 9 | http://audioboxlive.podbean.com 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 19 | 20 | 24 | 28 | 32 | 36 | 40 | 41 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 59 | 60 | 61 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/BaseApplication.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp; 2 | 3 | 4 | import android.app.Instrumentation; 5 | import android.content.Context; 6 | 7 | import com.crashlytics.android.Crashlytics; 8 | import com.google.android.gms.analytics.GoogleAnalytics; 9 | import com.google.android.gms.analytics.Tracker; 10 | import com.soi.rapidandroidapp.managers.EnvironmentManager; 11 | import com.soi.rapidandroidapp.models.common.Environment; 12 | import com.soi.rapidandroidapp.modules.Injector; 13 | import com.soi.rapidandroidapp.modules.RootModule; 14 | import com.soi.rapidandroidapp.modules.SocialManager; 15 | 16 | import com.soi.rapidandroidapp.utilities.Constants; 17 | import java.util.HashMap; 18 | 19 | import javax.inject.Inject; 20 | 21 | import io.fabric.sdk.android.Fabric; 22 | 23 | import android.support.multidex.MultiDex; 24 | import android.support.multidex.MultiDexApplication; 25 | import ollie.Ollie; 26 | 27 | /** 28 | * Created by spirosoikonomakis on 3/9/14. 29 | */ 30 | public class BaseApplication extends MultiDexApplication { 31 | 32 | @Inject 33 | EnvironmentManager environmentManager; 34 | 35 | @Inject 36 | SocialManager mSocialManager; 37 | 38 | /** 39 | * Setting this to true when a test runs 40 | */ 41 | public Boolean isRunningTests = false; 42 | 43 | public final static String APP_NAME = "RapidAndroid"; 44 | private static BaseApplication instance; 45 | HashMap mTrackers = new HashMap(); 46 | 47 | public BaseApplication() { 48 | 49 | } 50 | 51 | /** 52 | * Create main application 53 | * 54 | * @param context 55 | */ 56 | public BaseApplication(final Context context) { 57 | super(); 58 | attachBaseContext(context); 59 | 60 | } 61 | 62 | /** 63 | * Create main application 64 | * 65 | * @param instrumentation 66 | */ 67 | public BaseApplication(final Instrumentation instrumentation) { 68 | super(); 69 | attachBaseContext(instrumentation.getTargetContext()); 70 | } 71 | 72 | public static BaseApplication getInstance() { 73 | return instance; 74 | } 75 | 76 | @Override 77 | public void onCreate() { 78 | super.onCreate(); 79 | Ollie.with(getApplicationContext()) 80 | .setName(Constants.DB_NAME) 81 | .setVersion(Constants.DB_VERSION) 82 | .init(); 83 | instance = this; 84 | 85 | // Perform injection 86 | Injector.init(getRootModule(), this); 87 | 88 | mSocialManager.facebookInit(); 89 | if (environmentManager.getEnvironment() == Environment.LIVE) { 90 | Fabric.with(this, new Crashlytics(), mSocialManager.twitterInit()); 91 | } else { 92 | Fabric.with(this, mSocialManager.twitterInit(), new Crashlytics()); 93 | } 94 | } 95 | 96 | public synchronized Tracker getTracker(TrackerName trackerId) { 97 | 98 | if (!mTrackers.containsKey(trackerId)) { 99 | 100 | GoogleAnalytics analytics = GoogleAnalytics.getInstance(this); 101 | Tracker t = analytics.newTracker(getString(R.string.ga_property_id)); 102 | mTrackers.put(trackerId, t); 103 | } 104 | return mTrackers.get(trackerId); 105 | } 106 | 107 | public Object getRootModule() 108 | { 109 | return new RootModule(); 110 | } 111 | 112 | public void inject(Object object) 113 | { 114 | Injector.inject(object); 115 | } 116 | 117 | public enum TrackerName { 118 | APP_TRACKER, // Tracker used only in this app. 119 | GLOBAL_TRACKER, // Tracker used by all the apps from a company. eg: roll-up tracking. 120 | ECOMMERCE_TRACKER, // Tracker used by all ecommerce transactions from a company. 121 | } 122 | 123 | /** 124 | * Support for pre-Lollipop multidex 125 | * 126 | * @param context 127 | */ 128 | protected void attachBaseContext(Context context) { 129 | super.attachBaseContext(context); 130 | MultiDex.install(this); 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/api/GsonInstance.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.api; 2 | 3 | import com.google.gson.FieldNamingPolicy; 4 | import com.google.gson.Gson; 5 | import com.google.gson.GsonBuilder; 6 | import com.google.gson.internal.bind.DateTypeAdapter; 7 | 8 | import java.util.Date; 9 | 10 | public class GsonInstance { 11 | 12 | public static Gson gson; 13 | 14 | public GsonInstance() { 15 | gson = new GsonBuilder() 16 | .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) 17 | .serializeNulls() 18 | .registerTypeAdapter(Date.class, new DateTypeAdapter()) 19 | .create(); 20 | } 21 | } -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/api/common/AbstractApiManager.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.api.common; 2 | 3 | import android.util.Log; 4 | 5 | import com.soi.rapidandroidapp.api.GsonInstance; 6 | import com.soi.rapidandroidapp.api.errorhandlers.ApiErrorHandler; 7 | import com.soi.rapidandroidapp.api.managers.common.AbstractAsyncTask; 8 | import com.soi.rapidandroidapp.events.common.BusProvider; 9 | import com.soi.rapidandroidapp.managers.EnvironmentManager; 10 | import com.soi.rapidandroidapp.modules.Injector; 11 | import com.soi.rapidandroidapp.utilities.ReflectionUtils; 12 | import com.squareup.okhttp.OkHttpClient; 13 | 14 | import java.util.Map; 15 | 16 | import javax.inject.Inject; 17 | 18 | import retrofit.RestAdapter; 19 | import retrofit.client.OkClient; 20 | import retrofit.converter.GsonConverter; 21 | 22 | /** 23 | * Created by Spiros I. Oikonomakis on 11/4/14. 24 | * An abstract API manager which can be extended by each new API manager 25 | */ 26 | public abstract class AbstractApiManager extends AbstractAsyncTask implements BaseApiManager { 27 | 28 | protected static final String TAG_LOG_NAME = Class.class.getSimpleName(); 29 | 30 | protected T service; 31 | 32 | @Inject 33 | EnvironmentManager environmentManager; 34 | 35 | private GsonInstance gsonInstance = new GsonInstance(); 36 | 37 | /** 38 | * Get current url for the requested api manager 39 | * @return 40 | */ 41 | public abstract String getApiUrl(); 42 | 43 | /** 44 | * Returns the custom header which will be intercept in each request from 45 | * the api manager 46 | * @return 47 | */ 48 | protected abstract Map getHeaders(); 49 | 50 | protected AbstractApiManager() 51 | { 52 | Injector.inject(this); 53 | } 54 | 55 | @Override 56 | public RestAdapter.Builder getDefaultRestAdapterBuilder() 57 | { 58 | OkHttpClient httpClient = new OkHttpClient(); 59 | 60 | RestAdapter.Builder builder = new RestAdapter.Builder() 61 | .setEndpoint(getApiUrl()) 62 | .setErrorHandler(new ApiErrorHandler(BusProvider.getInstance())) 63 | .setClient(new OkClient(httpClient)) 64 | .setConverter(new GsonConverter(GsonInstance.gson)) 65 | .setLogLevel(environmentManager.getEnvironmentApiLogLevel()) 66 | .setLog(new RestAdapter.Log() { // 67 | @Override 68 | public void log(String msg) { 69 | Log.i(TAG_LOG_NAME, msg); 70 | } 71 | }); 72 | return builder; 73 | } 74 | 75 | @Override 76 | public T getApiService() 77 | { 78 | return this.service; 79 | } 80 | 81 | @Override 82 | public void setApiService(T service) 83 | { 84 | this.service = service; 85 | } 86 | 87 | @Override 88 | public Object execute(Object target, String methodName, Object... args) 89 | { 90 | return ReflectionUtils.tryInvoke(target, methodName, args); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/api/common/ApiRequestAttrs.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.api.common; 2 | 3 | /** 4 | * Created by Spiros I. Oikonomakis on 11/17/14. 5 | */ 6 | public class ApiRequestAttrs { 7 | 8 | public AbstractApiManager apiManager; 9 | public String resource; 10 | public Object[] params; 11 | 12 | public ApiRequestAttrs(AbstractApiManager apiManager, String resource, Object... params) { 13 | this.apiManager = apiManager; 14 | this.resource = resource; 15 | this.params = params; 16 | } 17 | 18 | public ApiRequestAttrs(String resource) { 19 | this.resource = resource; 20 | } 21 | 22 | public AbstractApiManager getApiManager() { 23 | return apiManager; 24 | } 25 | 26 | public void setApiManager(AbstractApiManager apiManager) { 27 | this.apiManager = apiManager; 28 | } 29 | 30 | public String getResource() { 31 | return resource; 32 | } 33 | 34 | public void setResource(String resource) { 35 | this.resource = resource; 36 | } 37 | 38 | public Object[] getParams() { 39 | return params; 40 | } 41 | 42 | public void setParams(Object[] params) { 43 | this.params = params; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/api/common/BaseApiManager.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.api.common; 2 | 3 | import retrofit.RestAdapter; 4 | 5 | /** 6 | * Created by Spiros I. Oikonomakis on 11/4/14. 7 | */ 8 | public interface BaseApiManager { 9 | 10 | /** 11 | * return the current api service 12 | * 13 | * @return 14 | */ 15 | T getApiService(); 16 | 17 | /** 18 | * Sets the current api service 19 | */ 20 | void setApiService(T service); 21 | 22 | /** 23 | * Initialize rest adapter and returns the RetroFit rest adapter 24 | * 25 | * @return 26 | */ 27 | RestAdapter.Builder getDefaultRestAdapterBuilder(); 28 | 29 | /** 30 | * Executes the proper API resource via Reflection 31 | * 32 | * @param target 33 | * @param methodName 34 | * @param args 35 | */ 36 | Object execute(Object target, String methodName, Object... args); 37 | 38 | /** 39 | * Executes the proper API resource for each action separately 40 | * 41 | * @param action 42 | * @param args 43 | */ 44 | Object execute(String action, Object... args); 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/api/errorhandlers/ApiErrorHandler.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.api.errorhandlers; 2 | 3 | import com.soi.rapidandroidapp.api.managers.events.common.HttpNotfoundEvent; 4 | import com.soi.rapidandroidapp.api.managers.events.common.HttpServerErrorEvent; 5 | import com.soi.rapidandroidapp.api.managers.events.common.HttpUnauthorizedEvent; 6 | import com.soi.rapidandroidapp.api.managers.events.common.HttpUpgradeRequiredEvent; 7 | import com.soi.rapidandroidapp.api.managers.events.common.NotInternetEvent; 8 | import com.squareup.otto.Bus; 9 | 10 | import java.net.HttpURLConnection; 11 | 12 | import retrofit.ErrorHandler; 13 | import retrofit.RetrofitError; 14 | import retrofit.client.Response; 15 | 16 | /** 17 | * Created by Spiros I. Oikonomakis on 1/6/15. 18 | */ 19 | public class ApiErrorHandler implements ErrorHandler 20 | { 21 | 22 | private Bus eventBus; 23 | 24 | public ApiErrorHandler(Bus bus) 25 | { 26 | this.eventBus = bus; 27 | } 28 | 29 | @Override 30 | public Throwable handleError(RetrofitError error) 31 | { 32 | Response r = error.getResponse(); 33 | if (r == null && error.getMessage() != null && error.getMessage().contains("No address")) { 34 | eventBus.post(new NotInternetEvent()); 35 | return error; 36 | } 37 | 38 | if (r != null) { 39 | if (r.getStatus() == HttpURLConnection.HTTP_UNAUTHORIZED) { 40 | eventBus.post(new HttpUnauthorizedEvent()); 41 | return error; 42 | } 43 | 44 | if (r.getStatus() == HttpURLConnection.HTTP_NOT_FOUND) { 45 | eventBus.post(new HttpNotfoundEvent()); 46 | return error; 47 | } 48 | 49 | if (r.getStatus() >= HttpURLConnection.HTTP_INTERNAL_ERROR) { 50 | eventBus.post(new HttpServerErrorEvent()); 51 | return error; 52 | } 53 | 54 | if (r.getStatus() == 426) { 55 | eventBus.post(new HttpUpgradeRequiredEvent()); 56 | return error; 57 | } 58 | } 59 | return error; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/api/interceptors/ApiRequestInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.api.interceptors; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import retrofit.RequestInterceptor; 7 | 8 | /** 9 | * Created by Spiros I. Oikonomakis on 10/31/14. 10 | *

11 | * RequestInterceptor with HTTP headers for the BASE API 12 | */ 13 | public class ApiRequestInterceptor implements RequestInterceptor { 14 | 15 | /** 16 | * Custom HTTP Headers map with key and value 17 | */ 18 | private Map headers = new HashMap(); 19 | 20 | public ApiRequestInterceptor() { 21 | } 22 | 23 | public ApiRequestInterceptor(Map headers) 24 | { 25 | this.headers = headers; 26 | } 27 | 28 | @Override 29 | public void intercept(RequestFacade request) 30 | { 31 | if (headers.size() > 0) { 32 | for (Map.Entry header : headers.entrySet()) { 33 | request.addHeader(header.getKey(), header.getValue()); 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/api/interceptors/FoursquareApiRequestInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.api.interceptors; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import retrofit.RequestInterceptor; 7 | 8 | /** 9 | * Created by Spiros I. Oikonomakis on 10/31/14. 10 | *

11 | * RequestInterceptor with HTTP headers for the BASE API 12 | */ 13 | public class FoursquareApiRequestInterceptor implements RequestInterceptor { 14 | 15 | /** 16 | * Custom HTTP Headers map with key and value 17 | */ 18 | private Map headers = new HashMap(); 19 | 20 | public FoursquareApiRequestInterceptor() { 21 | } 22 | 23 | public FoursquareApiRequestInterceptor(Map headers) { 24 | this.headers = headers; 25 | } 26 | 27 | @Override 28 | public void intercept(RequestFacade request) { 29 | if (headers.size() > 0) { 30 | for (Map.Entry header : headers.entrySet()) { 31 | request.addHeader(header.getKey(), header.getValue()); 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/api/managers/ApiManager.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.api.managers; 2 | 3 | 4 | import android.content.Context; 5 | 6 | import com.soi.rapidandroidapp.api.common.AbstractApiManager; 7 | import com.soi.rapidandroidapp.api.interceptors.ApiRequestInterceptor; 8 | import com.soi.rapidandroidapp.api.services.AppApiService; 9 | import com.soi.rapidandroidapp.managers.EnvironmentManager; 10 | import com.soi.rapidandroidapp.utilities.Constants; 11 | 12 | import java.util.HashMap; 13 | import java.util.Map; 14 | 15 | import javax.inject.Inject; 16 | 17 | import retrofit.RestAdapter; 18 | 19 | /** 20 | * Created by Spiros I. Oikonomakis on 10/17/14. 21 | *

22 | * This class handles all the api requests 23 | */ 24 | public class ApiManager extends AbstractApiManager { 25 | 26 | @Inject 27 | EnvironmentManager environmentManager; 28 | 29 | private Context mContext; 30 | 31 | public ApiManager(Context context) { 32 | this.mContext = context; 33 | RestAdapter.Builder restAdapterBuilder = getDefaultRestAdapterBuilder(); 34 | // Add extra options to rest adapter 35 | RestAdapter restAdapter = restAdapterBuilder.setRequestInterceptor(new ApiRequestInterceptor(getHeaders())).build(); 36 | this.service = restAdapter.create(AppApiService.class); 37 | } 38 | 39 | @Override 40 | public Object execute(String action, Object... args) { 41 | return null; 42 | } 43 | 44 | 45 | @Override 46 | public String getApiUrl() 47 | { 48 | return environmentManager.getEnviromentApiUrl(); 49 | } 50 | 51 | @Override 52 | protected Map getHeaders() 53 | { 54 | Map headers = new HashMap(); 55 | headers.put(Constants.API_HEADER_HTTP_ACCEPT, Constants.API_HEADER_HTTP_ACCEPT_VALUE); 56 | return headers; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/api/managers/FoursquareApiManager.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.api.managers; 2 | 3 | import android.content.Context; 4 | 5 | import com.soi.rapidandroidapp.api.common.AbstractApiManager; 6 | import com.soi.rapidandroidapp.api.common.ApiRequestAttrs; 7 | import com.soi.rapidandroidapp.api.interceptors.FoursquareApiRequestInterceptor; 8 | import com.soi.rapidandroidapp.api.managers.events.FoursquareExploreEvent; 9 | import com.soi.rapidandroidapp.api.managers.events.FoursquareSearchEvent; 10 | import com.soi.rapidandroidapp.api.managers.foursquare.FoursquareResources; 11 | import com.soi.rapidandroidapp.api.managers.net.response.foursquare.explore.Explore; 12 | import com.soi.rapidandroidapp.api.managers.net.response.foursquare.search.SearchResult; 13 | import com.soi.rapidandroidapp.api.services.FoursquareApiService; 14 | import com.soi.rapidandroidapp.utilities.Constants; 15 | import com.soi.rapidandroidapp.utilities.ReflectionUtils; 16 | import com.soi.rapidandroidapp.utilities.StringUtils; 17 | 18 | import java.text.SimpleDateFormat; 19 | import java.util.Map; 20 | 21 | import retrofit.RestAdapter; 22 | 23 | /** 24 | * Created by Spiros I. Oikonomakis on 10/17/14. 25 | *

26 | * This class handles all the api requests 27 | */ 28 | public class FoursquareApiManager extends AbstractApiManager { 29 | 30 | 31 | public static SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyyMMdd"); 32 | private Context mContext; 33 | 34 | public FoursquareApiManager(Context context) { 35 | this.mContext = context; 36 | RestAdapter.Builder restAdapterBuilder = getDefaultRestAdapterBuilder(); 37 | // Add extra options to rest adapter 38 | RestAdapter restAdapter = restAdapterBuilder 39 | .setRequestInterceptor(new FoursquareApiRequestInterceptor()).build(); 40 | this.service = restAdapter.create(FoursquareApiService.class); 41 | } 42 | 43 | @Override 44 | public String getApiUrl() { 45 | return Constants.FOURSQUARE_API_URL; 46 | } 47 | 48 | @Override 49 | protected Map getHeaders() { 50 | return null; 51 | } 52 | 53 | @Override 54 | public Object execute(String action, Object... args) { 55 | Object o = ReflectionUtils.tryInvoke(getApiService(), action, args); 56 | if (StringUtils.equals(action, FoursquareResources.EXPLORE)) { 57 | return new FoursquareExploreEvent((Explore) o); 58 | } else if (StringUtils.equals(action, FoursquareResources.SEARCH)) { 59 | return new FoursquareSearchEvent((SearchResult) o); 60 | } else { 61 | throw new UnsupportedOperationException(); 62 | } 63 | } 64 | 65 | /** 66 | * Get places from Foursquare 67 | */ 68 | public void explore(String ll, String clientId, String clientSecret, 69 | int limit, int sortByDistance, String v) { 70 | ApiRequestAttrs attrs = new ApiRequestAttrs(this, FoursquareResources.EXPLORE, ll, clientId, 71 | clientSecret, limit, sortByDistance, v); 72 | super.execute(attrs); 73 | } 74 | 75 | /** 76 | * Get places from Foursquare 77 | */ 78 | public void search(String intent, Integer radius, String ll, String clientId, String clientSecret, // 79 | String query, Integer limit, Integer sortByDistance, String v) { 80 | ApiRequestAttrs attrs = new ApiRequestAttrs(this, FoursquareResources.SEARCH, intent, radius, 81 | ll, clientId, clientSecret, query, limit, sortByDistance, v); 82 | super.execute(attrs); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/api/managers/common/AbstractAsyncTask.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.api.managers.common; 2 | 3 | import android.os.AsyncTask; 4 | 5 | import com.soi.rapidandroidapp.api.common.AbstractApiManager; 6 | import com.soi.rapidandroidapp.api.common.ApiRequestAttrs; 7 | import com.soi.rapidandroidapp.events.common.BusProvider; 8 | 9 | /** 10 | * Created by Spiros I. Oikonomakis on 11/16/14. 11 | */ 12 | public abstract class AbstractAsyncTask extends AsyncTask { 13 | 14 | @Override 15 | protected void onPreExecute() { 16 | super.onPreExecute(); 17 | } 18 | 19 | @Override 20 | protected Object doInBackground(ApiRequestAttrs... params) { 21 | ApiRequestAttrs apiRequestAttrs = params[0]; 22 | AbstractApiManager apiManager = apiRequestAttrs.getApiManager(); 23 | String resource = apiRequestAttrs.getResource(); 24 | Object[] args = apiRequestAttrs.getParams(); 25 | return apiManager.execute(resource, args); 26 | } 27 | 28 | @Override 29 | protected void onPostExecute(Object o) { 30 | super.onPostExecute(o); 31 | if (o != null) { 32 | BusProvider.getInstance().post(o); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/api/managers/common/BaseEvent.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.api.managers.common; 2 | 3 | /** 4 | * Created by Spiros I. Oikonomakis on 12/1/14. 5 | */ 6 | public class BaseEvent { 7 | 8 | public Object response; 9 | 10 | public BaseEvent(Object response) { 11 | this.response = response; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/api/managers/events/FoursquareExploreEvent.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.api.managers.events; 2 | 3 | import com.soi.rapidandroidapp.api.managers.common.BaseEvent; 4 | import com.soi.rapidandroidapp.api.managers.net.response.foursquare.explore.Explore; 5 | 6 | /** 7 | * Created by Spiros I. Oikonomakis on 11/25/14. 8 | */ 9 | public class FoursquareExploreEvent extends BaseEvent { 10 | 11 | public Explore response; 12 | 13 | public FoursquareExploreEvent(Explore response) { 14 | super(response); 15 | this.response = response; 16 | } 17 | 18 | public Explore getResponse() { 19 | return response; 20 | } 21 | 22 | public void setResponse(Explore response) { 23 | this.response = response; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/api/managers/events/FoursquareSearchEvent.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.api.managers.events; 2 | 3 | import com.soi.rapidandroidapp.api.managers.common.BaseEvent; 4 | import com.soi.rapidandroidapp.api.managers.net.response.foursquare.search.SearchResult; 5 | 6 | /** 7 | * Created by Spiros I. Oikonomakis on 11/25/14. 8 | */ 9 | public class FoursquareSearchEvent extends BaseEvent { 10 | public SearchResult response; 11 | 12 | public FoursquareSearchEvent(SearchResult response) { 13 | super(response); 14 | this.response = response; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/api/managers/events/common/HttpNotfoundEvent.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.api.managers.events.common; 2 | 3 | /** 4 | * Created by Spiros I. Oikonomakis on 1/6/15. 5 | */ 6 | public class HttpNotfoundEvent { 7 | } 8 | -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/api/managers/events/common/HttpServerErrorEvent.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.api.managers.events.common; 2 | 3 | /** 4 | * Created by Spiros I. Oikonomakis on 1/6/15. 5 | */ 6 | public class HttpServerErrorEvent { 7 | } 8 | -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/api/managers/events/common/HttpUnauthorizedEvent.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.api.managers.events.common; 2 | 3 | /** 4 | * Created by Spiros I. Oikonomakis on 1/6/15. 5 | */ 6 | public class HttpUnauthorizedEvent { 7 | } 8 | -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/api/managers/events/common/HttpUpgradeRequiredEvent.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.api.managers.events.common; 2 | 3 | /** 4 | * Created by Spiros I. Oikonomakis on 2/10/15. 5 | */ 6 | public class HttpUpgradeRequiredEvent { 7 | 8 | public String msg = "We did major changes and you need to upgrade the app to the newest version."; 9 | } -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/api/managers/events/common/NotInternetEvent.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.api.managers.events.common; 2 | 3 | /** 4 | * Created by Spiros I. Oikonomakis on 2/10/15. 5 | */ 6 | public class NotInternetEvent { 7 | } -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/api/managers/foursquare/FoursquareResources.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.api.managers.foursquare; 2 | 3 | /** 4 | * Created by Spiros I. Oikonomakis on 11/17/14. 5 | */ 6 | public interface FoursquareResources { 7 | 8 | public final static String EXPLORE = "explore"; 9 | public final static String SEARCH = "search"; 10 | 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/api/managers/net/response/foursquare/explore/Explore.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.api.managers.net.response.foursquare.explore; 2 | 3 | import com.soi.rapidandroidapp.api.managers.net.response.foursquare.explore.common.Response; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * Created by Spiros I. Oikonomakis on 11/16/14. 9 | */ 10 | public class Explore implements Serializable { 11 | 12 | public Response response; 13 | 14 | @Override 15 | public String toString() { 16 | return "Explore [response=" + response + "]"; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/api/managers/net/response/foursquare/explore/common/Category.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.api.managers.net.response.foursquare.explore.common; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Created by Spiros I. Oikonomakis on 11/16/14. 7 | */ 8 | public class Category implements Serializable { 9 | 10 | public String id; 11 | public String name; 12 | 13 | public Icon icon; 14 | 15 | @Override 16 | public String toString() { 17 | return "Categories [id=" + id + ", name=" + name + ", icon=" + icon 18 | + "]"; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/api/managers/net/response/foursquare/explore/common/Group.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.api.managers.net.response.foursquare.explore.common; 2 | 3 | import java.io.Serializable; 4 | import java.util.ArrayList; 5 | 6 | /** 7 | * Created by Spiros I. Oikonomakis on 11/16/14. 8 | */ 9 | public class Group implements Serializable { 10 | 11 | public String type; 12 | public String name; 13 | public ArrayList items; 14 | 15 | @Override 16 | public String toString() { 17 | return "Group [type=" + type + ", name=" + name + ", items=" + items 18 | + "]"; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/api/managers/net/response/foursquare/explore/common/Icon.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.api.managers.net.response.foursquare.explore.common; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Created by Spiros I. Oikonomakis on 11/16/14. 7 | */ 8 | public class Icon implements Serializable { 9 | public String prefix; 10 | public String suffix; 11 | 12 | public String getUrl(int size, boolean bg) { 13 | String background = bg ? "bg" : ""; 14 | return prefix + background + "_" + size + suffix; 15 | } 16 | 17 | @Override 18 | public String toString() { 19 | return "Icon [prefix=" + prefix + ", suffix=" + suffix + "]"; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/api/managers/net/response/foursquare/explore/common/Item.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.api.managers.net.response.foursquare.explore.common; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Created by Spiros I. Oikonomakis on 11/16/14. 7 | */ 8 | public class Item implements Serializable { 9 | public Venue venue; 10 | 11 | @Override 12 | public String toString() { 13 | return "Item [venue=" + venue + "]"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/api/managers/net/response/foursquare/explore/common/Location.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.api.managers.net.response.foursquare.explore.common; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Created by Spiros I. Oikonomakis on 11/16/14. 7 | */ 8 | public class Location implements Serializable { 9 | 10 | public String address; 11 | public float lat; 12 | public float lng; 13 | public int distance; 14 | public String city; 15 | public String country; 16 | 17 | @Override 18 | public String toString() { 19 | return "Location [address=" + address + ", lat=" + lat + ", lng=" + lng 20 | + ", distance=" + distance + ", city=" + city + ", country=" 21 | + country + "]"; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/api/managers/net/response/foursquare/explore/common/Response.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.api.managers.net.response.foursquare.explore.common; 2 | 3 | import java.io.Serializable; 4 | import java.util.ArrayList; 5 | 6 | /** 7 | * Created by Spiros I. Oikonomakis on 11/16/14. 8 | */ 9 | public class Response implements Serializable { 10 | 11 | public ArrayList groups; 12 | 13 | @Override 14 | public String toString() { 15 | return "Response [groups=" + groups + "]"; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/api/managers/net/response/foursquare/explore/common/Venue.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.api.managers.net.response.foursquare.explore.common; 2 | 3 | import java.io.Serializable; 4 | import java.util.ArrayList; 5 | 6 | /** 7 | * Created by Spiros I. Oikonomakis on 11/16/14. 8 | */ 9 | public class Venue implements Serializable { 10 | 11 | public String id; 12 | public String name; 13 | public Location location; 14 | public ArrayList categories; 15 | 16 | @Override 17 | public String toString() { 18 | return "Venue [id=" + id + ", name=" + name + ", location=" + location 19 | + ", categories=" + categories + "]"; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/api/managers/net/response/foursquare/search/SearchResult.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.api.managers.net.response.foursquare.search; 2 | 3 | import com.soi.rapidandroidapp.api.managers.net.response.foursquare.search.common.SearchMeta; 4 | import com.soi.rapidandroidapp.api.managers.net.response.foursquare.search.common.SearchResponse; 5 | 6 | import java.io.Serializable; 7 | 8 | /** 9 | * Created by Spiros I. Oikonomakis on 11/16/14. 10 | */ 11 | public class SearchResult implements Serializable { 12 | 13 | public SearchMeta meta; 14 | public SearchResponse response; 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/api/managers/net/response/foursquare/search/common/SearchMeta.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.api.managers.net.response.foursquare.search.common; 2 | 3 | /** 4 | * Created by Spiros I. Oikonomakis on 11/16/14. 5 | */ 6 | public class SearchMeta { 7 | public int code; 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/api/managers/net/response/foursquare/search/common/SearchResponse.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.api.managers.net.response.foursquare.search.common; 2 | 3 | import com.soi.rapidandroidapp.api.managers.net.response.foursquare.explore.common.Venue; 4 | 5 | import java.io.Serializable; 6 | import java.util.List; 7 | 8 | /** 9 | * Created by Spiros I. Oikonomakis on 11/16/14. 10 | */ 11 | public class SearchResponse implements Serializable { 12 | 13 | public List venues; 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/api/services/AppApiService.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.api.services; 2 | 3 | import com.soi.rapidandroidapp.models.User; 4 | 5 | import retrofit.http.Field; 6 | import retrofit.http.POST; 7 | 8 | /** 9 | * Created by Spiros I. Oikonomakis on 10/31/14. 10 | */ 11 | public interface AppApiService { 12 | 13 | @POST("/login") 14 | User login( 15 | @Field("email") String email, 16 | @Field("password") String password 17 | ); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/api/services/FoursquareApiService.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.api.services; 2 | 3 | 4 | import com.soi.rapidandroidapp.api.managers.net.response.foursquare.explore.Explore; 5 | import com.soi.rapidandroidapp.api.managers.net.response.foursquare.search.SearchResult; 6 | 7 | import retrofit.http.GET; 8 | import retrofit.http.Query; 9 | 10 | public interface FoursquareApiService { 11 | 12 | @GET("/venues/explore") 13 | Explore explore( // 14 | @Query("ll") String ll, // 15 | @Query("client_id") String clientId, // 16 | @Query("client_secret") String clientSecret, // 17 | @Query("limit") Integer limit, // 18 | @Query("sortByDistance") Integer sortByDistance, // 19 | @Query("v") String date // 20 | ); 21 | 22 | @GET("/venues/search") 23 | SearchResult search( // 24 | @Query("intent") String intent, // 25 | @Query("radius") Integer radius, // 26 | @Query("ll") String ll, // 27 | @Query("client_id") String clientId, // 28 | @Query("client_secret") String clientSecret, // 29 | @Query("query") String query, // 30 | @Query("limit") Integer limit, // 31 | @Query("sortByDistance") Integer sortByDistance, // 32 | @Query("v") String date// 33 | ); 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/database/TABLE_NAMES.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.database; 2 | 3 | /** 4 | * Created by Spiros I. Oikonomakis on 11/14/14. 5 | */ 6 | public interface TABLE_NAMES { 7 | 8 | public final static String USER = "user"; 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/database/UserContract.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.database; 2 | 3 | import android.provider.BaseColumns; 4 | 5 | /** 6 | * Created by Spiros I. Oikonomakis on 12/9/14. 7 | */ 8 | public final class UserContract { 9 | 10 | public static abstract class UserEntry implements BaseColumns { 11 | public static final String TABLE_NAME = "user"; 12 | public static final String COLUMN_NAME_USERID = "user_id"; 13 | public static final String COLUMN_NAME_TOKEN = "token"; 14 | public static final String COLUMN_NAME_EMAIL = "email"; 15 | public static final String COLUMN_NAME_FNAME = "fname"; 16 | public static final String COLUMN_NAME_LNAME = "lname"; 17 | public static final String COLUMN_NAME_AVATAR = "avatar"; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/events/common/BusProvider.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.events.common; 2 | 3 | import android.os.Handler; 4 | import android.os.Looper; 5 | 6 | import com.squareup.otto.Bus; 7 | 8 | /** 9 | * Maintains a singleton instance for obtaining the bus. Ideally this would be replaced with a more efficient means 10 | * such as through injection directly into interested classes. 11 | */ 12 | public final class BusProvider { 13 | public static final String BUS_TAG = BusProvider.class.getSimpleName(); 14 | private static final Bus BUS = new MainThreadBus(new Bus()); 15 | 16 | private BusProvider() { 17 | // No instances. 18 | } 19 | 20 | public static Bus getInstance() { 21 | return BUS; 22 | } 23 | 24 | /** 25 | * This bus CAN be called from all threads and it will call subscribe methods on the MAIN thread. 26 | */ 27 | public static class MainThreadBus extends Bus { 28 | private final Bus mBus; 29 | private final Handler mHandler = new Handler(Looper.getMainLooper()); 30 | 31 | public MainThreadBus(final Bus bus) { 32 | if (bus == null) { 33 | throw new NullPointerException("bus must not be null"); 34 | } 35 | mBus = bus; 36 | } 37 | 38 | @Override 39 | public void register(Object obj) { 40 | mBus.register(obj); 41 | } 42 | 43 | @Override 44 | public void unregister(Object obj) { 45 | mBus.unregister(obj); 46 | } 47 | 48 | @Override 49 | public void post(final Object event) { 50 | if (Looper.myLooper() == Looper.getMainLooper()) { 51 | mBus.post(event); 52 | } else { 53 | mHandler.post(new Runnable() { 54 | @Override 55 | public void run() { 56 | mBus.post(event); 57 | } 58 | }); 59 | } 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/managers/AnalyticsManager.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.managers; 2 | 3 | import android.app.Activity; 4 | 5 | import com.google.android.gms.analytics.HitBuilders; 6 | import com.google.android.gms.analytics.Tracker; 7 | import com.soi.rapidandroidapp.BaseApplication; 8 | 9 | /** 10 | * Created by soikonomakis on 5/5/14. 11 | */ 12 | public class AnalyticsManager { 13 | 14 | private static AnalyticsManager _instance; 15 | private Activity act; 16 | private Tracker tracker; 17 | 18 | public static synchronized AnalyticsManager getInstance() { 19 | if (_instance == null) 20 | _instance = new AnalyticsManager(); 21 | return _instance; 22 | } 23 | 24 | /** 25 | * Initialize the google analytics tracked 26 | * 27 | * @param act 28 | * @param trackerName 29 | * @return 30 | */ 31 | public AnalyticsManager initTracker(Activity act, BaseApplication.TrackerName trackerName) { 32 | this.act = act; 33 | tracker = ((BaseApplication) act.getApplication()).getTracker(trackerName); 34 | return _instance; 35 | } 36 | 37 | /** 38 | * Send an event of an actions 39 | * 40 | * @param category 41 | * @param action 42 | * @param label 43 | * @return 44 | */ 45 | public AnalyticsManager trackEvent(String category, String action, String label) { 46 | tracker.send(new HitBuilders.EventBuilder() 47 | .setCategory(category) 48 | .setAction(action) 49 | .setLabel(label).build()); 50 | return _instance; 51 | } 52 | 53 | /** 54 | * Sends a screen page view 55 | * 56 | * @param screenName 57 | */ 58 | public void trackScreenView(String screenName) { 59 | tracker.setScreenName(screenName); 60 | 61 | // Send a screen view. 62 | tracker.send(new HitBuilders.AppViewBuilder().build()); 63 | } 64 | 65 | } -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/managers/EnvironmentManager.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.managers; 2 | 3 | 4 | import android.util.Log; 5 | 6 | import com.soi.rapidandroidapp.BuildConfig; 7 | import com.soi.rapidandroidapp.models.common.Environment; 8 | import com.soi.rapidandroidapp.utilities.Constants; 9 | 10 | import hugo.weaving.DebugLog; 11 | import retrofit.RestAdapter; 12 | 13 | /** 14 | * Created by Spiros I. Oikonomakis on 11/4/14. 15 | *

16 | * This class handles all the available enviroments according 17 | * to the build types. 18 | *

19 | * TODO: maybe use variants also 20 | */ 21 | public class EnvironmentManager { 22 | 23 | private static EnvironmentManager mInstance; 24 | 25 | /** 26 | * Singleton 27 | * 28 | * @return EnvironmentManager 29 | */ 30 | @DebugLog 31 | public static synchronized EnvironmentManager getInstance() { 32 | if (mInstance == null) { 33 | mInstance = new EnvironmentManager(); 34 | } 35 | return mInstance; 36 | } 37 | 38 | /** 39 | * Returns the url of the current build type. 40 | * eg. 41 | * if BuildConfig.environment = "debug" => returns staging Environment 42 | * 43 | * @return Environment 44 | */ 45 | @DebugLog 46 | public Environment getEnvironment() { 47 | Environment environment = null; 48 | if (BuildConfig.ENVIRONMENT.equals("STAGING")) { 49 | environment = Environment.STAGING; 50 | } else if (BuildConfig.ENVIRONMENT.equals("LIVE")) { 51 | environment = Environment.LIVE; 52 | } else if (BuildConfig.ENVIRONMENT.equals("UAT")) { 53 | environment = Environment.UAT; 54 | } 55 | return environment; 56 | } 57 | 58 | /** 59 | * Returns the url of the current build type. 60 | * eg. 61 | * if BuildConfig.environment = "debug" => returns staging URL 62 | * 63 | * @return String 64 | */ 65 | @DebugLog 66 | public String getEnviromentApiUrl() { 67 | String apiUrl = null; 68 | if (BuildConfig.ENVIRONMENT.equals("STAGING")) { 69 | apiUrl = Constants.API_STAGING_URL; 70 | } else if (BuildConfig.ENVIRONMENT.equals("LIVE")) { 71 | apiUrl = Constants.API_LIVE_URL; 72 | } else if (BuildConfig.ENVIRONMENT.equals("UAT")) { 73 | apiUrl = Constants.API_UAT_URL; 74 | } 75 | return apiUrl; 76 | } 77 | 78 | /** 79 | * Returns the API log level according to the current build environment. 80 | * eg. 81 | * if BuildConfig.environment = "debug" => returns FULL Logging 82 | * 83 | * @return RestAdapter.LogLevel 84 | */ 85 | @DebugLog 86 | public RestAdapter.LogLevel getEnvironmentApiLogLevel() { 87 | RestAdapter.LogLevel logLevel = null; 88 | if (BuildConfig.ENVIRONMENT.equals("STAGING")) { 89 | logLevel = RestAdapter.LogLevel.FULL; 90 | } else if (BuildConfig.ENVIRONMENT.equals("LIVE")) { 91 | logLevel = RestAdapter.LogLevel.BASIC; 92 | } else if (BuildConfig.ENVIRONMENT.equals("UAT")) { 93 | logLevel = RestAdapter.LogLevel.FULL; 94 | } 95 | return logLevel; 96 | } 97 | 98 | /** 99 | * Returns the API log level according to the current build environment. 100 | * eg. 101 | * if BuildConfig.environment = "debug" => returns FULL Logging 102 | * 103 | * @return RestAdapter.LogLevel 104 | */ 105 | @DebugLog 106 | public int getEnvironmentLogLevel() { 107 | int logLevel = 0; 108 | if (BuildConfig.ENVIRONMENT.equals("STAGING")) { 109 | logLevel = Log.DEBUG; 110 | } else if (BuildConfig.ENVIRONMENT.equals("LIVE")) { 111 | logLevel = Log.INFO; 112 | } else if (BuildConfig.ENVIRONMENT.equals("UAT")) { 113 | logLevel = Log.VERBOSE; 114 | } 115 | return logLevel; 116 | } 117 | 118 | /** 119 | * Returns true of false if I can track in google 120 | * analytics according to the environment 121 | * You can change it as you want 122 | * 123 | * @return 124 | */ 125 | @DebugLog 126 | public boolean canTrackGA() { 127 | boolean canTrack = false; 128 | if (BuildConfig.ENVIRONMENT.equals("STAGING")) { 129 | canTrack = false; 130 | } else if (BuildConfig.ENVIRONMENT.equals("LIVE")) { 131 | canTrack = true; 132 | } else if (BuildConfig.ENVIRONMENT.equals("UAT")) { 133 | canTrack = true; 134 | } 135 | return canTrack; 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/managers/LoggerWrapper.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.managers; 2 | 3 | import android.util.Log; 4 | 5 | import com.soi.rapidandroidapp.BaseApplication; 6 | 7 | import javax.inject.Inject; 8 | 9 | public class LoggerWrapper { 10 | 11 | private static LoggerWrapper _instance; 12 | 13 | public int LOGGER_LEVEL = EnvironmentManager.getInstance().getEnvironmentLogLevel(); 14 | 15 | @Inject 16 | protected EnvironmentManager environmentManager; 17 | 18 | private String _tag = BaseApplication.APP_NAME; 19 | 20 | private LoggerWrapper() { 21 | } 22 | 23 | /** 24 | * Singleton 25 | */ 26 | public synchronized static void getInstance() { 27 | if (_instance == null) { 28 | _instance = new LoggerWrapper(); 29 | } 30 | } 31 | 32 | /** 33 | * Logs with [INFO][tag] msg 34 | * 35 | * @param tag The tag which the logger will shown in logcat 36 | * @param msgFormat the format the message will be appeared "Hello %s, isn't %s cool? 37 | * @param args the arguments which you want to use 38 | */ 39 | public void logInfo(String tag, String msgFormat, Object... args) { 40 | Log.i(tag, String.format(msgFormat, args)); 41 | } 42 | 43 | /** 44 | * Logs with [INFO][_tag] msg 45 | * 46 | * @param msgFormat the format the message will be appeared "Hello %s, isn't %s cool? 47 | * @param args the arguments which you want to use 48 | */ 49 | public void logInfo(String msgFormat, Object... args) { 50 | Log.i(_tag, String.format(msgFormat, args)); 51 | } 52 | 53 | /** 54 | * Logs with [DEBUG][tag] msg 55 | * 56 | * @param tag The tag which the logger will shown in logcat 57 | * @param msgFormat the format the message will be appeared "Hello %s, isn't %s cool? 58 | * @param args the arguments which you want to use 59 | */ 60 | public void logDebug(String tag, String msgFormat, Object... args) { 61 | if (LOGGER_LEVEL <= Log.DEBUG) 62 | Log.d(tag, String.format(msgFormat, args)); 63 | } 64 | 65 | /** 66 | * Logs with [DEBUG][_tag] msg 67 | * 68 | * @param msgFormat the format the message will be appeared "Hello %s, isn't %s cool? 69 | * @param args the arguments which you want to use 70 | */ 71 | public void logDebug(String msgFormat, Object... args) { 72 | if (LOGGER_LEVEL <= Log.WARN) 73 | Log.d(_tag, String.format(msgFormat, args)); 74 | } 75 | 76 | /** 77 | * Logs with [ERROR][tag] msg exception 78 | * 79 | * @param tag The tag which the logger will shown in logcat 80 | * @param msgFormat the format the message will be appeared "Hello %s, isn't %s cool? 81 | * @param args the arguments which you want to use 82 | */ 83 | public void logError(String tag, String msgFormat, Exception ex, Object... args) { 84 | Log.e(tag, String.format(msgFormat, args), ex); 85 | } 86 | 87 | /** 88 | * Logs with [ERROR][tag] msg exception 89 | * 90 | * @param msgFormat the format the message will be appeared "Hello %s, isn't %s cool? 91 | * @param args the arguments which you want to use 92 | */ 93 | public void logError(String msgFormat, Exception ex, Object... args) { 94 | Log.e(_tag, String.format(msgFormat, args), ex); 95 | } 96 | } -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/managers/NetworkManager.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.managers; 2 | 3 | import android.content.Context; 4 | import android.net.ConnectivityManager; 5 | import android.net.NetworkInfo; 6 | 7 | /** 8 | * Check device's network connectivity and speed 9 | */ 10 | public class NetworkManager { 11 | 12 | /** 13 | * A static instance of the class for the Singlettion 14 | */ 15 | private static NetworkManager _instance; 16 | /** 17 | * Current context where is used 18 | */ 19 | private Context context; 20 | 21 | private NetworkManager(Context context) { 22 | this.context = context; 23 | } 24 | 25 | /** 26 | * Singletton Pattern 27 | * 28 | * @param ctx 29 | * @return 30 | */ 31 | public synchronized static NetworkManager getInstance(Context ctx) { 32 | if (_instance == null) { 33 | _instance = new NetworkManager(ctx); 34 | } 35 | return _instance; 36 | } 37 | 38 | /** 39 | * Returns the network info 40 | * 41 | * @return 42 | */ 43 | public NetworkInfo getNetworkInfo() { 44 | ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); 45 | return cm.getActiveNetworkInfo(); 46 | } 47 | 48 | /** 49 | * Returns true if it's connected 50 | * 51 | * @return 52 | */ 53 | public boolean isConnected() { 54 | NetworkInfo info = getNetworkInfo(); 55 | return (info != null && info.isConnected()); 56 | } 57 | 58 | /** 59 | * Returns if it's connected via Wifi 60 | * 61 | * @return 62 | */ 63 | public boolean isConnectedWifi() { 64 | NetworkInfo info = getNetworkInfo(); 65 | return (info != null && info.isConnected() && info.getType() == ConnectivityManager.TYPE_WIFI); 66 | } 67 | 68 | /** 69 | * Returns if it's connected via Mobile Network 70 | * 71 | * @return 72 | */ 73 | public boolean isConnectedMobile() { 74 | NetworkInfo info = getNetworkInfo(); 75 | return (info != null && info.isConnected() && info.getType() == ConnectivityManager.TYPE_MOBILE); 76 | } 77 | } -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/managers/SessionManager.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.managers; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.content.SharedPreferences; 6 | import android.content.SharedPreferences.Editor; 7 | 8 | 9 | import com.soi.rapidandroidapp.ui.LoginActivity; 10 | 11 | import java.util.HashMap; 12 | 13 | public class SessionManager { 14 | 15 | // User name 16 | public static final String KEY_NAME = "name"; 17 | // Login session token 18 | public static final String KEY_TOKEN = "auth_token"; 19 | public static final String KEY_USER_EMAIL = "email"; 20 | public static final String KEY_PASSWORD = "password"; 21 | public static final String KEY_USER_ID = "userId"; 22 | public static final String KEY_SESSION_COOKIE_ID = "cookieId"; 23 | public static final String KEY_FB_TOKEN = "fbToken"; 24 | public static final String KEY_FIRST_TIME = "firstTime"; 25 | public static final String KEY_USER_FB_EMAIL = "mail"; 26 | public static final String KEY_USER_CURRENT_LOCATION = "currentLocation"; 27 | private static final String PREF_NAME = "RapidAndroidAppPref"; 28 | // All shared preferences key 29 | private static final String IS_LOGIN = "IsLoggedIn"; 30 | // Shared pref mode 31 | protected int PRIVATE_MODE = 0; 32 | // Android's Shared preferences 33 | // to create a new session for a user 34 | private SharedPreferences _pref; 35 | // The shared preferences editor 36 | private Editor _editor; 37 | private Context _context; 38 | 39 | 40 | public SessionManager(Context context) { 41 | super(); 42 | this._context = context; 43 | _pref = _context.getSharedPreferences(PREF_NAME, PRIVATE_MODE); 44 | _editor = _pref.edit(); 45 | } 46 | 47 | /** 48 | * Create login session 49 | * 50 | * @param name 51 | * @param email 52 | * @param token 53 | */ 54 | public void createLoginSession(String name, String email, String token, String userId) { 55 | _editor.putBoolean(IS_LOGIN, true); 56 | _editor.putString(KEY_NAME, name); 57 | _editor.putString(KEY_USER_EMAIL, email); 58 | _editor.putString(KEY_TOKEN, token); 59 | _editor.putString(KEY_USER_ID, userId); 60 | _editor.commit(); 61 | } 62 | 63 | /** 64 | * Create FB session 65 | * 66 | * @param userEmail 67 | */ 68 | public void createFbEmailSession(String userEmail) { 69 | _editor.putString(KEY_USER_FB_EMAIL, userEmail); 70 | _editor.commit(); 71 | 72 | } 73 | 74 | public void setUserFullName(String fullName) { 75 | _editor.putString(KEY_NAME, fullName); 76 | _editor.commit(); 77 | } 78 | 79 | /** 80 | * Get Stored Session data 81 | */ 82 | public HashMap getUserDetails() { 83 | 84 | HashMap user = new HashMap(); 85 | 86 | user.put(KEY_USER_EMAIL, _pref.getString(KEY_USER_EMAIL, null)); 87 | user.put(KEY_PASSWORD, _pref.getString(KEY_PASSWORD, null)); 88 | user.put(KEY_USER_ID, _pref.getString(KEY_USER_ID, null)); 89 | user.put(KEY_TOKEN, _pref.getString(KEY_TOKEN, null)); 90 | user.put(KEY_NAME, _pref.getString(KEY_NAME, null)); 91 | return user; 92 | } 93 | 94 | /** 95 | * Check login method will check user login status 96 | * If false it will redirect user to login page 97 | * Else won't do anything 98 | */ 99 | public void checkLogin() { 100 | // Check login status 101 | if (!this.isLoggedIn()) { 102 | Intent i = new Intent(_context, LoginActivity.class); 103 | i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 104 | i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 105 | _context.startActivity(i); 106 | } 107 | } 108 | 109 | /** 110 | * Clear session details 111 | */ 112 | public void logoutUser() { 113 | // Clearing all data from Shared Preferences 114 | _editor.clear(); 115 | _editor.commit(); 116 | 117 | Intent i = new Intent(_context, LoginActivity.class); 118 | i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 119 | i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 120 | _context.startActivity(i); 121 | } 122 | 123 | /** 124 | * Check if user is logged in 125 | * 126 | * @return 127 | */ 128 | public boolean isLoggedIn() { 129 | return _pref.getBoolean(IS_LOGIN, false); 130 | } 131 | 132 | /** 133 | * Sets the current location of a user 134 | * @param latlng 135 | * @return 136 | */ 137 | public boolean setCurrentLocation(String latlng) 138 | { 139 | return _editor.putString(KEY_USER_CURRENT_LOCATION, latlng).commit(); 140 | } 141 | 142 | /** 143 | * Returns the saved current location 144 | * @return 145 | */ 146 | public String getCurrentLocation() 147 | { 148 | return _pref.getString(KEY_USER_CURRENT_LOCATION,null); 149 | } 150 | } -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/models/SocialShareModel.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.models; 2 | 3 | import android.graphics.drawable.Drawable; 4 | 5 | /** 6 | * This models will be used to create a custom UI element 7 | * like a dialog/spinner which will contains the social entities 8 | * which can be selected to share on each one. 9 | * TODO: support for multiple selection and share 10 | */ 11 | public class SocialShareModel { 12 | 13 | /** 14 | * The title of the social entity 15 | * eg. 16 | * Share on facebook 17 | */ 18 | private String title; 19 | 20 | /** 21 | * The drawable which will be associated 22 | * for this social model. 23 | * TODO: support url as images 24 | */ 25 | private Drawable image; 26 | 27 | private SocialType type; 28 | 29 | public SocialShareModel() { 30 | } 31 | 32 | public SocialShareModel(String title, Drawable image, SocialType type) { 33 | this.title = title; 34 | this.image = image; 35 | this.type = type; 36 | } 37 | 38 | public String getTitle() { 39 | return title; 40 | } 41 | 42 | public void setTitle(String title) { 43 | this.title = title; 44 | } 45 | 46 | public Drawable getImage() { 47 | return image; 48 | } 49 | 50 | public void setImage(Drawable image) { 51 | this.image = image; 52 | } 53 | 54 | public SocialType getType() { 55 | return type; 56 | } 57 | 58 | public void setType(SocialType type) { 59 | this.type = type; 60 | } 61 | } -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/models/SocialType.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.models; 2 | 3 | /** 4 | * Created by soikonomakis on 3/21/14. 5 | */ 6 | public enum SocialType { 7 | FACEBOOK, 8 | TWITTER, 9 | EMAIL 10 | } -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/models/User.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.models; 2 | 3 | import com.soi.rapidandroidapp.database.UserContract; 4 | import com.soi.rapidandroidapp.models.common.DBModel; 5 | import ollie.annotation.Column; 6 | import ollie.annotation.NotNull; 7 | import ollie.annotation.Table; 8 | import ollie.annotation.Unique; 9 | 10 | @Table(UserContract.UserEntry.TABLE_NAME) 11 | public class User extends DBModel { 12 | 13 | public static String AUTH_TOKEN_KEY = "auth_token"; 14 | 15 | @Column(value= UserContract.UserEntry.COLUMN_NAME_USERID) 16 | @Unique 17 | @NotNull 18 | public Long userId; 19 | 20 | @Column(value= UserContract.UserEntry.COLUMN_NAME_TOKEN) 21 | @Unique 22 | @NotNull 23 | public String authToken; 24 | 25 | @Column(value= UserContract.UserEntry.COLUMN_NAME_EMAIL) 26 | @Unique 27 | @NotNull 28 | public String email; 29 | 30 | @Column(value= UserContract.UserEntry.COLUMN_NAME_FNAME) 31 | public String fname; 32 | 33 | @Column(value= UserContract.UserEntry.COLUMN_NAME_LNAME) 34 | public String lname; 35 | 36 | @Column(value= UserContract.UserEntry.COLUMN_NAME_AVATAR) 37 | public String avatar; 38 | 39 | public User() { 40 | } 41 | 42 | public User(Long userId, String authToken) { 43 | this.userId = userId; 44 | this.authToken = authToken; 45 | } 46 | 47 | public Long getUserId() { 48 | return userId; 49 | } 50 | 51 | public String getAuthToken() { 52 | return authToken; 53 | } 54 | 55 | public String getEmail() { 56 | return email; 57 | } 58 | 59 | public String getFname() { 60 | return fname; 61 | } 62 | 63 | public String getLname() { 64 | return lname; 65 | } 66 | 67 | public String getAvatar() { 68 | return avatar; 69 | } 70 | 71 | } -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/models/common/DBModel.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.models.common; 2 | 3 | 4 | import java.io.Serializable; 5 | import java.util.Date; 6 | import java.util.HashMap; 7 | import java.util.List; 8 | import java.util.Map; 9 | import ollie.Model; 10 | import ollie.annotation.Column; 11 | import ollie.query.Delete; 12 | import ollie.query.Select; 13 | 14 | /** 15 | * This is Abstract Model for the app's database. 16 | * Supports the ActiveRecord for android 17 | * 18 | * @param It's the type of the current Object you want to be used as a Database Model 19 | */ 20 | public class DBModel extends Model implements IBaseModel, Comparable, Serializable { 21 | 22 | private static final DBModel instance = new DBModel(); 23 | 24 | private Map singletonHolder = new HashMap(); 25 | 26 | /** 27 | * Singletton pattern for each model which extends this DBModel class 28 | * 29 | * @param classOf 30 | * @param 31 | * @return 32 | * @throws InstantiationException 33 | * @throws IllegalAccessException 34 | */ 35 | public static T getInstance(Class classOf) throws InstantiationException, IllegalAccessException { 36 | synchronized (instance) { 37 | if (!instance.singletonHolder.containsKey(classOf)) { 38 | T obj = classOf.newInstance(); 39 | instance.singletonHolder.put(classOf, obj); 40 | } 41 | return (T) instance.singletonHolder.get(classOf); 42 | } 43 | } 44 | 45 | @Override 46 | public DBModel findOne(Long mId) { 47 | return find(getClass(), mId); 48 | } 49 | 50 | @Override 51 | public List findAll() { 52 | return Select.from(getClass()).fetch(); 53 | } 54 | 55 | @Override 56 | public void deleteOne(Long mId) { 57 | Delete.from(getClass()).where("_id = ?", mId).execute(); 58 | } 59 | 60 | @Override 61 | public void deleteAll() { 62 | Delete.from(getClass()).execute(); 63 | } 64 | 65 | @Override 66 | public int compareTo(T another) { 67 | return this.compareTo(another); 68 | } 69 | 70 | @Override 71 | public String toString() { 72 | return super.toString(); 73 | } 74 | } -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/models/common/Environment.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.models.common; 2 | 3 | /** 4 | * Created by Spiros I. Oikonomakis on 11/4/14. 5 | */ 6 | public enum Environment { 7 | LIVE, 8 | STAGING, 9 | UAT 10 | } 11 | -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/models/common/IBaseModel.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.models.common; 2 | 3 | import java.util.Date; 4 | import java.util.List; 5 | 6 | public interface IBaseModel { 7 | 8 | /** 9 | * @param mId The primary key of the table 10 | * @return the record by the primary key 11 | */ 12 | public T findOne(Long mId); 13 | 14 | /** 15 | * @return all the records for the type T 16 | */ 17 | public List findAll(); 18 | 19 | /** 20 | * @param mId The primary key of the table 21 | * @return boolean if it's deleted successfully 22 | */ 23 | public void deleteOne(Long mId); 24 | 25 | /** 26 | * @return boolean if table is deleted successfully 27 | */ 28 | public void deleteAll(); 29 | 30 | } -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/modules/AndroidModule.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.modules; 2 | 3 | import android.accounts.AccountManager; 4 | import android.app.NotificationManager; 5 | import android.content.Context; 6 | import android.content.SharedPreferences; 7 | import android.content.pm.ApplicationInfo; 8 | import android.content.pm.PackageInfo; 9 | import android.content.pm.PackageManager; 10 | import android.preference.PreferenceManager; 11 | import android.telephony.TelephonyManager; 12 | import android.view.inputmethod.InputMethodManager; 13 | 14 | import com.soi.rapidandroidapp.BaseApplication; 15 | 16 | import javax.inject.Singleton; 17 | 18 | import dagger.Module; 19 | import dagger.Provides; 20 | 21 | /** 22 | * Created by spirosoikonomakis on 3/9/14. 23 | */ 24 | 25 | /** 26 | * Module for all Android related provisions 27 | */ 28 | @Module 29 | ( 30 | complete = false, 31 | library = true 32 | ) 33 | public class AndroidModule { 34 | 35 | @Provides 36 | @Singleton 37 | Context provideAppContext() { 38 | return BaseApplication.getInstance().getApplicationContext(); 39 | } 40 | 41 | @Provides 42 | SharedPreferences provideDefaultSharedPreferences(final Context context) { 43 | return PreferenceManager.getDefaultSharedPreferences(context); 44 | } 45 | 46 | @Provides 47 | PackageInfo providePackageInfo(Context context) { 48 | try { 49 | return context.getPackageManager().getPackageInfo(context.getPackageName(), 0); 50 | } catch (PackageManager.NameNotFoundException e) { 51 | throw new RuntimeException(e); 52 | } 53 | } 54 | 55 | @Provides 56 | TelephonyManager provideTelephonyManager(Context context) { 57 | return getSystemService(context, Context.TELEPHONY_SERVICE); 58 | } 59 | 60 | @SuppressWarnings("unchecked") 61 | public T getSystemService(Context context, String serviceConstant) { 62 | return (T) context.getSystemService(serviceConstant); 63 | } 64 | 65 | @Provides 66 | InputMethodManager provideInputMethodManager(final Context context) { 67 | return (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); 68 | } 69 | 70 | @Provides 71 | ApplicationInfo provideApplicationInfo(final Context context) { 72 | return context.getApplicationInfo(); 73 | } 74 | 75 | @Provides 76 | AccountManager provideAccountManager(final Context context) { 77 | return AccountManager.get(context); 78 | } 79 | 80 | @Provides 81 | ClassLoader provideClassLoader(final Context context) { 82 | return context.getClassLoader(); 83 | } 84 | 85 | @Provides 86 | NotificationManager provideNotificationManager(final Context context) { 87 | return (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); 88 | } 89 | 90 | } -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/modules/AppModule.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.modules; 2 | 3 | import android.content.Context; 4 | 5 | import com.soi.rapidandroidapp.BaseApplication; 6 | import com.soi.rapidandroidapp.api.managers.ApiManager; 7 | import com.soi.rapidandroidapp.api.managers.FoursquareApiManager; 8 | import com.soi.rapidandroidapp.events.common.BusProvider; 9 | import com.soi.rapidandroidapp.managers.EnvironmentManager; 10 | import com.soi.rapidandroidapp.managers.LoggerWrapper; 11 | import com.soi.rapidandroidapp.managers.NetworkManager; 12 | import com.soi.rapidandroidapp.managers.SessionManager; 13 | import com.soi.rapidandroidapp.ui.LoginActivity; 14 | import com.soi.rapidandroidapp.ui.MainActivity; 15 | import com.soi.rapidandroidapp.ui.common.AbstractActivity; 16 | import com.soi.rapidandroidapp.ui.common.AbstractFragmentActivity; 17 | import com.soi.rapidandroidapp.ui.fragments.HomeFragment; 18 | import com.soi.rapidandroidapp.ui.fragments.ItemActivity; 19 | import com.soi.rapidandroidapp.ui.fragments.ItemViewFragment; 20 | import com.soi.rapidandroidapp.utilities.DialogsHelper; 21 | import com.soi.rapidandroidapp.utilities.Utils; 22 | import com.squareup.otto.Bus; 23 | 24 | import javax.inject.Singleton; 25 | 26 | import dagger.Module; 27 | import dagger.Provides; 28 | 29 | /** 30 | * Created by spirosoikonomakis on 3/9/14. 31 | */ 32 | @Module 33 | ( 34 | complete = false, 35 | 36 | injects = { 37 | BaseApplication.class, 38 | AbstractActivity.class, 39 | AbstractFragmentActivity.class, 40 | MainActivity.class, 41 | LoginActivity.class, 42 | ItemActivity.class, 43 | HomeFragment.class, 44 | ItemViewFragment.class, 45 | LoggerWrapper.class, 46 | FoursquareApiManager.class, 47 | ApiManager.class, 48 | }, 49 | library = true 50 | ) 51 | public class AppModule { 52 | 53 | /** 54 | * Provides a SessionManager for injection based on context 55 | * 56 | * @param context 57 | * @return 58 | */ 59 | @Provides 60 | SessionManager provideSessionManager(Context context) 61 | { 62 | return new SessionManager(context); 63 | } 64 | 65 | /** 66 | * Provides a singleton of FoursquareApiManager for injection 67 | * 68 | * @return 69 | */ 70 | @Provides 71 | FoursquareApiManager provideFoursquareApiManager(Context context) 72 | { 73 | return new FoursquareApiManager(context); 74 | } 75 | 76 | /** 77 | * Provides a singleton of ApiManager for injection 78 | * 79 | * @return 80 | */ 81 | @Provides 82 | ApiManager provideApiManager(Context context) 83 | { 84 | return new ApiManager(context); 85 | } 86 | 87 | /** 88 | * Provides a singleton of NetworkManager for injection based on context 89 | * 90 | * @param context 91 | * @return 92 | */ 93 | @Provides 94 | @Singleton 95 | NetworkManager provideNetworkManager(Context context) 96 | { 97 | return NetworkManager.getInstance(context); 98 | } 99 | 100 | /** 101 | * Provides a singleton of EnvironmentManager for injection 102 | * 103 | * @return 104 | */ 105 | @Provides 106 | @Singleton 107 | EnvironmentManager provideEnvironmentManager() 108 | { 109 | return EnvironmentManager.getInstance(); 110 | } 111 | 112 | /** 113 | * Provides a singleton of Utilities for injection 114 | * 115 | * @return 116 | */ 117 | @Provides 118 | @Singleton 119 | Utils provideUtilities() 120 | { 121 | 122 | return Utils.getInstance(); 123 | } 124 | 125 | /** 126 | * Provides a singleton of Dialogs for injection 127 | * 128 | * @return 129 | */ 130 | @Provides 131 | @Singleton 132 | DialogsHelper provideDialogs() 133 | { 134 | 135 | return DialogsHelper.getInstance(); 136 | } 137 | 138 | /** 139 | * Provides a singleton of NetworkManager for injection based on context 140 | * 141 | * @param context 142 | * @return 143 | */ 144 | @Provides 145 | @Singleton 146 | SocialManager provideSocialManager(Context context) 147 | { 148 | return SocialManager.getInstance(context); 149 | } 150 | 151 | /** 152 | * Returns a bus instance 153 | * @return 154 | */ 155 | @Provides 156 | @Singleton 157 | Bus provideBusMain() 158 | { 159 | return BusProvider.getInstance(); 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/modules/Injector.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.modules; 2 | 3 | import dagger.ObjectGraph; 4 | 5 | /** 6 | * Created by spirosoikonomakis on 3/9/14. 7 | */ 8 | public class Injector { 9 | 10 | public static ObjectGraph objectGraph; 11 | 12 | public static void init(Object rootModule) { 13 | if (objectGraph == null) { 14 | objectGraph = ObjectGraph.create(rootModule); 15 | } else { 16 | objectGraph = objectGraph.plus(rootModule); 17 | } 18 | 19 | objectGraph.injectStatics(); 20 | } 21 | 22 | public static void init(final Object rootModule, final Object target) { 23 | init(rootModule); 24 | inject(target); 25 | } 26 | 27 | public static void inject(final Object target) { 28 | objectGraph.inject(target); 29 | } 30 | 31 | public static T resolve(Class type) { 32 | return objectGraph.get(type); 33 | } 34 | } -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/modules/RootModule.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.modules; 2 | 3 | import dagger.Module; 4 | 5 | /** 6 | * Created by spirosoikonomakis on 3/9/14. 7 | */ 8 | @Module 9 | ( 10 | includes = { 11 | AndroidModule.class, 12 | AppModule.class 13 | } 14 | ) 15 | public class RootModule { 16 | } -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/modules/SocialManager.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.modules; 2 | 3 | import android.app.Activity; 4 | import android.content.ActivityNotFoundException; 5 | import android.content.ComponentName; 6 | import android.content.Context; 7 | import android.content.Intent; 8 | import android.content.pm.PackageManager; 9 | import android.content.pm.ResolveInfo; 10 | import android.net.Uri; 11 | import android.os.StrictMode; 12 | import android.text.Html; 13 | 14 | import com.facebook.FacebookSdk; 15 | import com.facebook.share.model.ShareLinkContent; 16 | import com.soi.rapidandroidapp.R; 17 | import com.soi.rapidandroidapp.models.SocialShareModel; 18 | import com.soi.rapidandroidapp.models.SocialType; 19 | import com.soi.rapidandroidapp.utilities.StringUtils; 20 | import com.soi.rapidandroidapp.utilities.Utils; 21 | import com.twitter.sdk.android.Twitter; 22 | import com.twitter.sdk.android.core.TwitterAuthConfig; 23 | import com.twitter.sdk.android.tweetcomposer.TweetComposer; 24 | 25 | import java.util.ArrayList; 26 | import java.util.List; 27 | import java.util.Map; 28 | 29 | import javax.inject.Inject; 30 | 31 | /** 32 | * Created by Spiros I. Oikonomakis on 11/8/14. 33 | */ 34 | public class SocialManager { 35 | 36 | @Inject 37 | Utils utils; 38 | 39 | public static final String FEED_DESC = "description"; 40 | public static final String FEED_TITLE = "title"; 41 | public static final String FEED_CAPTION = "caption"; 42 | public static final String FEED_DESCR = "description"; 43 | public static final String FEED_PICTURE = "picture"; 44 | public static final String FEED_LINK = "link"; 45 | 46 | private static SocialManager _instance; 47 | private Context mContext; 48 | 49 | public synchronized static SocialManager getInstance(Context context) 50 | { 51 | if (_instance == null) { 52 | _instance = new SocialManager(context); 53 | } 54 | return _instance; 55 | } 56 | 57 | private SocialManager() { 58 | } 59 | 60 | 61 | /** 62 | * Initialises facebook configuration 63 | */ 64 | public void facebookInit() 65 | { 66 | FacebookSdk.sdkInitialize(mContext); 67 | } 68 | 69 | /** 70 | * Initialises twitter configuration 71 | */ 72 | public Twitter twitterInit() 73 | { 74 | TwitterAuthConfig twitterAuthConfig = new TwitterAuthConfig(mContext.getString(R.string.twitter_consumer_key), 75 | mContext.getString(R.string.twitter_consumer_secret)); 76 | return new Twitter(twitterAuthConfig); 77 | } 78 | 79 | /** 80 | * Returns the ShareLinkContent for FB sharing 81 | * @param params 82 | * @return 83 | */ 84 | public ShareLinkContent getFbShareLinKContent(Map params) 85 | { 86 | ShareLinkContent.Builder builder = new ShareLinkContent.Builder(); 87 | if (params.containsKey(FEED_DESCR)) 88 | builder.setContentDescription(params.get(FEED_DESCR)); 89 | 90 | if (params.containsKey(FEED_TITLE)) 91 | builder.setContentTitle(params.get(FEED_TITLE)); 92 | 93 | if (params.containsKey(FEED_PICTURE)) 94 | builder.setImageUrl(Uri.parse(params.get(FEED_PICTURE))); 95 | 96 | 97 | if (params.containsKey(FEED_LINK)) 98 | builder.setContentUrl(Uri.parse(params.get(FEED_LINK))); 99 | 100 | 101 | return builder.build(); 102 | } 103 | 104 | /** 105 | * Returns the tweet composer 106 | * @param message 107 | * @return TweetComposer.Builder 108 | */ 109 | public TweetComposer.Builder getTweetContent(String message) 110 | { 111 | return new TweetComposer.Builder(mContext).text(message); 112 | } 113 | 114 | /** 115 | * Returns the standard text with the given sponsor code 116 | * @return 117 | */ 118 | public ShareLinkContent getFbShareLinKContent(String descr, String url) 119 | { 120 | return new ShareLinkContent.Builder() 121 | .setContentDescription(descr) 122 | .setContentUrl(Uri.parse(url)).build(); 123 | } 124 | 125 | private SocialManager(Context mContext) { 126 | this.mContext = mContext; 127 | } 128 | 129 | /** 130 | * Open each social app or browser to share 131 | * content 132 | * @param act current activity 133 | * @param socialToShare the type of the share 134 | * @param title the title if is the Facebook or anything else 135 | * @param text the text which will be shared 136 | * @param shareUrl the url which will be shared 137 | */ 138 | public void shareSocial(Activity act, 139 | SocialType socialToShare, 140 | String title, 141 | String text, 142 | String shareUrl, 143 | String[] recipients, 144 | boolean fromGmail) 145 | { 146 | switch (socialToShare) { 147 | case TWITTER: 148 | this._tweetShare(act, title, text); 149 | break; 150 | case EMAIL: 151 | this._emailShare(act, title, text, recipients, fromGmail); 152 | break; 153 | } 154 | } 155 | 156 | 157 | /** 158 | * Share via twitter app and fail over scenario 159 | * to open the browser for sharing 160 | * @param act 161 | * @param title 162 | * @param description 163 | */ 164 | private void _tweetShare(Activity act, String title, String description) 165 | { 166 | try { 167 | Intent shareIntent = new Intent(Intent.ACTION_SEND); 168 | shareIntent.setType("text/plain"); 169 | shareIntent.setPackage("com.twitter.android"); 170 | shareIntent.putExtra(Intent.EXTRA_TITLE, title); 171 | shareIntent.putExtra(Intent.EXTRA_TEXT, description); 172 | act.startActivity(shareIntent); 173 | } catch (ActivityNotFoundException ex) { 174 | String tweetUrl = StringUtils.join(" ", "https://twitter.com/intent/tweet?text=", title, description); 175 | Uri uri = Uri.parse(tweetUrl); 176 | act.startActivity(new Intent(Intent.ACTION_VIEW, uri)); 177 | } 178 | } 179 | 180 | /** 181 | * Share via email 182 | * @param act 183 | * @param title 184 | * @param text 185 | */ 186 | private void _emailShare(Activity act, String title, String text, String[] recipients, boolean fromGmail) 187 | { 188 | 189 | if ( fromGmail ) { 190 | this.emailFromGmail(act, title, text, recipients); 191 | return; 192 | } 193 | 194 | // Email to Send 195 | Intent emailIntent = new Intent(); 196 | emailIntent.setAction(Intent.ACTION_SEND); 197 | if ( recipients.length > 0) { 198 | emailIntent.putExtra(Intent.EXTRA_EMAIL, recipients); 199 | } 200 | emailIntent.putExtra(Intent.EXTRA_SUBJECT, title); 201 | emailIntent.putExtra(Intent.EXTRA_TEXT, Html.fromHtml(text)); 202 | emailIntent.setType("message/rfc822"); 203 | act.startActivity(emailIntent); 204 | } 205 | 206 | private void emailFromGmail(Activity act, String title, String text, String[] recipients) { 207 | Intent sendIntent = new Intent(Intent.ACTION_VIEW); 208 | sendIntent.setType("plain/text"); 209 | sendIntent.setClassName("com.google.android.gm", "com.google.android.gm.ComposeActivityGmail"); 210 | sendIntent.putExtra(Intent.EXTRA_EMAIL, recipients); 211 | sendIntent.putExtra(Intent.EXTRA_SUBJECT, title); 212 | sendIntent.putExtra(Intent.EXTRA_TEXT, text); 213 | act.startActivity(sendIntent); 214 | } 215 | 216 | 217 | /** 218 | * Open youtube page from the app 219 | * otherwise in browser 220 | * @param activity 221 | */ 222 | public final void openYoutube(Activity activity, String url) { 223 | Intent intent = new Intent( 224 | Intent.ACTION_VIEW , 225 | Uri.parse(url)); 226 | intent.setComponent(new ComponentName("com.google.android.youtube","com.google.android.youtube.PlayerActivity")); 227 | 228 | PackageManager manager = activity.getPackageManager(); 229 | List infos = manager.queryIntentActivities(intent, 0); 230 | if (infos.size() > 0) { 231 | activity.startActivity(intent); 232 | } else{ 233 | activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); 234 | } 235 | } 236 | 237 | /** 238 | * Open twitter page from the app 239 | * otherwise in browser 240 | * @param act 241 | */ 242 | public final void openTwitter(Activity act, String twitterId) 243 | { 244 | Intent intent = null; 245 | try { 246 | // get the Twitter app if possible 247 | act.getPackageManager().getPackageInfo("com.twitter.android", 0); 248 | intent = new Intent(Intent.ACTION_VIEW, Uri.parse("twitter://user?screen_name=" + twitterId)); 249 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 250 | } catch (Exception e) { 251 | // no Twitter app, revert to browser 252 | intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://twitter.com/"+twitterId)); 253 | } 254 | act.startActivity(intent); 255 | } 256 | 257 | 258 | /** 259 | * Open facebook page from the app 260 | * otherwise in browser 261 | * @param act 262 | */ 263 | public final void openFacebook(Activity act, String pageName) { 264 | final String urlFb = "fb://profile/"+pageName; 265 | Intent intent = new Intent(Intent.ACTION_VIEW); 266 | intent.setData(Uri.parse(urlFb)); 267 | 268 | // If Facebook application is installed, use that else launch a browser 269 | final PackageManager packageManager = act.getPackageManager(); 270 | List list = 271 | packageManager.queryIntentActivities(intent, 272 | PackageManager.MATCH_DEFAULT_ONLY); 273 | if (list.size() == 0) { 274 | final String urlBrowser = "https://www.facebook.com/"+pageName; 275 | intent.setData(Uri.parse(urlBrowser)); 276 | } 277 | 278 | act.startActivity(intent); 279 | } 280 | 281 | public List getAvailableSocialList(Context context) 282 | { 283 | List socialList = new ArrayList(); 284 | socialList.add(new SocialShareModel("Share on facebook", context.getResources().getDrawable(R.drawable.fb_icon), SocialType.FACEBOOK)); 285 | socialList.add(new SocialShareModel("Share on twitter", context.getResources().getDrawable(R.drawable.twitter_icon), SocialType.TWITTER)); 286 | return socialList; 287 | } 288 | 289 | } -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/ui/LoginActivity.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.ui; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.view.Menu; 6 | import android.view.MenuItem; 7 | 8 | import com.soi.rapidandroidapp.R; 9 | 10 | 11 | public class LoginActivity extends Activity { 12 | 13 | @Override 14 | protected void onCreate(Bundle savedInstanceState) { 15 | super.onCreate(savedInstanceState); 16 | setContentView(R.layout.activity_login); 17 | } 18 | 19 | 20 | @Override 21 | public boolean onCreateOptionsMenu(Menu menu) { 22 | getMenuInflater().inflate(R.menu.login, menu); 23 | return true; 24 | } 25 | 26 | @Override 27 | public boolean onOptionsItemSelected(MenuItem item) { 28 | int id = item.getItemId(); 29 | if (id == R.id.action_settings) { 30 | return true; 31 | } 32 | return super.onOptionsItemSelected(item); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/ui/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.ui; 2 | 3 | import android.os.Bundle; 4 | import android.support.v4.app.FragmentManager; 5 | 6 | import com.soi.rapidandroidapp.ui.common.AbstractFragmentActivity; 7 | import com.soi.rapidandroidapp.ui.common.BaseFragment; 8 | import com.soi.rapidandroidapp.ui.fragments.HomeFragment; 9 | 10 | public class MainActivity extends AbstractFragmentActivity { 11 | 12 | /** 13 | * This si the fragment which is now into the fragment container 14 | * and it's shown up to the user 15 | */ 16 | private BaseFragment currentFragment; 17 | 18 | @Override 19 | public void initListeners() { 20 | 21 | } 22 | 23 | @Override 24 | protected void selectItem(int position) { 25 | 26 | } 27 | 28 | @Override 29 | public void onBackPressed() { 30 | if (currentFragment.allowBackPressed()) { 31 | currentFragment.onBackPressed(); 32 | } else if (getSupportFragmentManager().getBackStackEntryCount() > 0) { 33 | getSupportFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); 34 | } else { 35 | super.onBackPressed(); 36 | } 37 | } 38 | 39 | @Override 40 | protected void onCreate(Bundle savedInstanceState) { 41 | super.onCreate(savedInstanceState); 42 | 43 | currentFragment = HomeFragment.newInstance(null); 44 | createFragment(currentFragment, HomeFragment.class.getName(), true, false); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/ui/adapters/NavigationDrawerAdapter.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.ui.adapters; 2 | 3 | import android.content.Context; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.ImageView; 9 | import android.widget.LinearLayout; 10 | import android.widget.TextView; 11 | 12 | 13 | import com.soi.rapidandroidapp.R; 14 | 15 | import butterknife.ButterKnife; 16 | import butterknife.InjectView; 17 | 18 | /** 19 | * Created by Spiros I. Oikonomakis on 1/27/15. 20 | */ 21 | public class NavigationDrawerAdapter extends RecyclerView.Adapter 22 | { 23 | private Context ctx; 24 | private String[] navigationItems; 25 | private String[] navigationItemsSubtitle; 26 | private Integer[] navigationItemIcons; 27 | private OnNavItemClickListener mListener; 28 | 29 | /** 30 | * Interface for receiving click events from cells. 31 | */ 32 | public interface OnNavItemClickListener { 33 | public void onNavigationClick(View view, int position); 34 | } 35 | 36 | public NavigationDrawerAdapter(Context ctx, String[] navigationItems, 37 | String[] navigationItemsSubtitle, Integer[] navigationItemIcons) { 38 | this.ctx = ctx; 39 | this.navigationItems = navigationItems; 40 | this.navigationItemsSubtitle = navigationItemsSubtitle; 41 | this.navigationItemIcons = navigationItemIcons; 42 | } 43 | 44 | public static class ViewHolder extends RecyclerView.ViewHolder { 45 | 46 | View root; 47 | 48 | @InjectView(R.id.txtMenuTitle) 49 | TextView txtMenuTitle; 50 | 51 | @InjectView(R.id.txtMenuSubtitle) 52 | TextView txtMenuSubtitle; 53 | 54 | @InjectView(R.id.imgIcon) 55 | ImageView imgIcon; 56 | 57 | public ViewHolder(View v) { 58 | super(v); 59 | 60 | root = v; 61 | ButterKnife.inject(this, v); 62 | 63 | } 64 | } 65 | 66 | @Override 67 | public ViewHolder onCreateViewHolder(ViewGroup parent, int i) { 68 | 69 | View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.drawer_list_item, parent, false); 70 | return new ViewHolder(view); 71 | } 72 | 73 | @Override 74 | public void onBindViewHolder(ViewHolder viewHolder, final int position) { 75 | if (navigationItems != null && navigationItems.length > 0) { 76 | viewHolder.txtMenuTitle.setText(navigationItems[position]); 77 | viewHolder.txtMenuSubtitle.setText(navigationItemsSubtitle[position]); 78 | viewHolder.imgIcon.setImageDrawable(ctx.getResources().getDrawable(navigationItemIcons[position])); 79 | } 80 | } 81 | 82 | @Override 83 | public int getItemCount() { 84 | return navigationItems.length; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/ui/adapters/PlacesAdapter.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.ui.adapters; 2 | 3 | import android.content.Context; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.widget.BaseAdapter; 8 | import android.widget.ImageView; 9 | import android.widget.TextView; 10 | 11 | import com.soi.rapidandroidapp.R; 12 | import com.soi.rapidandroidapp.api.managers.net.response.foursquare.explore.common.Category; 13 | import com.soi.rapidandroidapp.api.managers.net.response.foursquare.explore.common.Item; 14 | import com.soi.rapidandroidapp.api.managers.net.response.foursquare.explore.common.Venue; 15 | import com.soi.rapidandroidapp.utilities.StringUtils; 16 | import com.squareup.picasso.Picasso; 17 | 18 | import java.util.List; 19 | 20 | import butterknife.ButterKnife; 21 | import butterknife.InjectView; 22 | 23 | /** 24 | * Created by Spiros I. Oikonomakis on 1/29/15. 25 | */ 26 | public class PlacesAdapter extends BaseAdapter { 27 | 28 | private Context mContext; 29 | private List items; 30 | 31 | static class ViewHolder { 32 | @InjectView(R.id.txtName) 33 | TextView txtName; 34 | 35 | @InjectView(R.id.txtCategoryName) 36 | TextView txtCategoryName; 37 | 38 | @InjectView(R.id.imgPlace) 39 | ImageView imgPlace; 40 | 41 | public ViewHolder(View v) { 42 | ButterKnife.inject(this, v); 43 | } 44 | } 45 | 46 | public PlacesAdapter(Context mContext, List items) { 47 | this.mContext = mContext; 48 | this.items = items; 49 | } 50 | 51 | @Override 52 | public int getCount() { 53 | return items != null ? items.size() : 0; 54 | } 55 | 56 | @Override 57 | public Object getItem(int position) { 58 | return items.get(position); 59 | } 60 | 61 | @Override 62 | public long getItemId(int position) { 63 | return items.get(position).hashCode(); 64 | } 65 | 66 | @Override 67 | public View getView(int position, View convertView, ViewGroup parent) { 68 | ViewHolder holder = null; 69 | if (convertView == null) { 70 | LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 71 | 72 | convertView = inflater.inflate(R.layout.item_venue, parent, false); 73 | holder = new ViewHolder(convertView); 74 | 75 | convertView.setTag(holder); 76 | } else { 77 | holder = (ViewHolder) convertView.getTag(); 78 | } 79 | Venue venue = items.get(position).venue; 80 | 81 | holder.txtName.setText(venue.name); 82 | 83 | if (venue.categories != null && venue.categories.size() > 0) { 84 | Category category = venue.categories.get(0); 85 | 86 | holder.txtCategoryName.setText(category.name); 87 | if (category.icon != null) { 88 | Picasso.with(mContext).load(StringUtils.join("", category.icon.prefix, "bg_88", category.icon.suffix)) 89 | .into(holder.imgPlace); 90 | } 91 | } 92 | 93 | return convertView; 94 | } 95 | } -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/ui/common/AbstractActivity.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.ui.common; 2 | 3 | import android.app.Activity; 4 | import android.app.AlertDialog; 5 | import android.app.Dialog; 6 | import android.content.DialogInterface; 7 | import android.os.Bundle; 8 | import android.support.v4.app.Fragment; 9 | import android.support.v4.app.FragmentTransaction; 10 | import android.support.v7.app.ActionBar; 11 | import android.support.v7.app.ActionBarActivity; 12 | import android.support.v7.app.AppCompatActivity; 13 | import android.view.MenuItem; 14 | import android.widget.Toast; 15 | 16 | import com.soi.rapidandroidapp.BaseApplication; 17 | import com.soi.rapidandroidapp.R; 18 | import com.soi.rapidandroidapp.api.managers.events.common.HttpNotfoundEvent; 19 | import com.soi.rapidandroidapp.api.managers.events.common.HttpServerErrorEvent; 20 | import com.soi.rapidandroidapp.api.managers.events.common.HttpUnauthorizedEvent; 21 | import com.soi.rapidandroidapp.api.managers.events.common.HttpUpgradeRequiredEvent; 22 | import com.soi.rapidandroidapp.api.managers.events.common.NotInternetEvent; 23 | import com.soi.rapidandroidapp.events.common.BusProvider; 24 | import com.soi.rapidandroidapp.managers.AnalyticsManager; 25 | import com.soi.rapidandroidapp.managers.EnvironmentManager; 26 | import com.soi.rapidandroidapp.modules.Injector; 27 | import com.soi.rapidandroidapp.utilities.DialogsHelper; 28 | import com.soi.rapidandroidapp.utilities.Utils; 29 | import com.squareup.otto.Bus; 30 | import com.squareup.otto.Subscribe; 31 | 32 | import javax.inject.Inject; 33 | 34 | import butterknife.ButterKnife; 35 | 36 | public abstract class AbstractActivity extends AppCompatActivity { 37 | 38 | @Inject 39 | protected EnvironmentManager environmentManager; 40 | 41 | @Inject 42 | protected Utils utils; 43 | 44 | @Inject 45 | protected DialogsHelper dialogsHelper; 46 | 47 | /** 48 | * Waiting dialog to show before go to next screen 49 | */ 50 | private Dialog waitingDialog; 51 | 52 | @Inject 53 | Bus mBus; 54 | 55 | // Obtain same Singleton eventBus 56 | private Bus apiErrorBus = BusProvider.getInstance(); 57 | 58 | private ApiErrorHandler apiErrorHandler; 59 | 60 | /** 61 | * The current action bar of the screen if it's 62 | * exist 63 | */ 64 | protected ActionBar actionBar; 65 | 66 | /** 67 | * The title of the actionbar if it's exist 68 | */ 69 | protected String actionBarTitle; 70 | 71 | /** 72 | * The screen name you want to track in google analytics 73 | * or logging 74 | */ 75 | protected String SCREEN_NAME = null; 76 | 77 | @Override 78 | protected void onCreate(Bundle savedInstanceState) { 79 | super.onCreate(savedInstanceState); 80 | initActionBar(); 81 | 82 | Injector.inject(this); 83 | 84 | apiErrorHandler = new ApiErrorHandler(); 85 | 86 | if (environmentManager.canTrackGA()) { 87 | AnalyticsManager.getInstance().initTracker(this, BaseApplication.TrackerName.APP_TRACKER); 88 | 89 | if (SCREEN_NAME != null) 90 | AnalyticsManager.getInstance().trackScreenView(SCREEN_NAME); 91 | } 92 | } 93 | 94 | 95 | @Override 96 | protected void onResume() 97 | { 98 | super.onResume(); 99 | mBus.register(this); 100 | apiErrorBus.register(apiErrorHandler); 101 | } 102 | 103 | @Override 104 | protected void onPause() 105 | { 106 | super.onPause(); 107 | mBus.unregister(this); 108 | apiErrorBus.unregister(apiErrorHandler); 109 | } 110 | 111 | @Override 112 | public void setContentView(int layoutResId) { 113 | super.setContentView(layoutResId); 114 | 115 | ButterKnife.inject(this); 116 | if (this.actionBarTitle != null && this.actionBar != null) { 117 | this.actionBar.setTitle(actionBarTitle); 118 | } 119 | } 120 | 121 | @Override 122 | public boolean onOptionsItemSelected(MenuItem item) { 123 | switch (item.getItemId()) { 124 | case android.R.id.home: 125 | onBackPressed(); 126 | break; 127 | } 128 | return super.onOptionsItemSelected(item); 129 | } 130 | 131 | protected void createFragment(Fragment targetFragment, boolean mustAddToBackStack) 132 | { 133 | FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); 134 | 135 | if (mustAddToBackStack) { 136 | transaction.addToBackStack(null); 137 | } 138 | targetFragment.setRetainInstance(true); 139 | transaction.replace(R.id.fragmentContainer, targetFragment) 140 | .setTransitionStyle(FragmentTransaction.TRANSIT_FRAGMENT_FADE) 141 | .commit(); 142 | } 143 | 144 | /** 145 | * Initializes action bar if it exists with some defaults 146 | */ 147 | public void initActionBar() { 148 | 149 | this.actionBar = getSupportActionBar(); 150 | 151 | if (this.actionBar != null && this.actionBar.isShowing()) { 152 | this.actionBar.setDisplayHomeAsUpEnabled(true); 153 | this.actionBar.setDisplayShowHomeEnabled(true); 154 | this.actionBar.setDisplayUseLogoEnabled(true); 155 | 156 | } 157 | } 158 | 159 | /** 160 | * Just shows a waiting dialog 161 | * @param title 162 | * @param text 163 | */ 164 | protected void showWaitingDialog(String title, String text) 165 | { 166 | waitingDialog = dialogsHelper.getCustomDialog(this, title, text); 167 | waitingDialog.show(); 168 | } 169 | 170 | /** 171 | * Just dismisses a waiting dialog 172 | */ 173 | protected void dismissWaitingDialog() 174 | { 175 | if (waitingDialog != null && waitingDialog.isShowing()) 176 | waitingDialog.dismiss(); 177 | } 178 | 179 | private class ApiErrorHandler { 180 | // API ERROR HANDLING 181 | @Subscribe 182 | public void onHttpUnauthorized(HttpUnauthorizedEvent event) { 183 | Toast.makeText(AbstractActivity.this, getString(R.string.txt_unauthorized_error), Toast.LENGTH_SHORT).show(); 184 | } 185 | 186 | @Subscribe 187 | public void onHttpServerError(HttpServerErrorEvent event) { 188 | Toast.makeText(AbstractActivity.this, getString(R.string.txt_server_error), Toast.LENGTH_SHORT).show(); 189 | } 190 | 191 | @Subscribe 192 | public void onHttpNotFound(HttpNotfoundEvent event) { 193 | Toast.makeText(AbstractActivity.this, getString(R.string.txt_notfound_error), Toast.LENGTH_SHORT).show(); 194 | } 195 | 196 | @Subscribe 197 | public void onHttpUpgradeRequired(HttpUpgradeRequiredEvent event) { 198 | final AlertDialog.Builder alertDialog = new AlertDialog.Builder(getBaseContext()); 199 | alertDialog.setCancelable(false); 200 | alertDialog.setMessage(event.msg); 201 | alertDialog.setPositiveButton("Upgrade", new DialogInterface.OnClickListener() { 202 | @Override 203 | public void onClick(DialogInterface dialog, int which) { 204 | utils.openURL(AbstractActivity.this, getString(R.string.app_url)); 205 | } 206 | }); 207 | alertDialog.show(); 208 | } 209 | @Subscribe 210 | public void onNoInternetEvent(NotInternetEvent event) { 211 | dialogsHelper.toastMakeAndShow(AbstractActivity.this, "No internet connection", Toast.LENGTH_SHORT); 212 | } 213 | } 214 | } 215 | -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/ui/common/BaseFragment.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.ui.common; 2 | 3 | import android.os.Bundle; 4 | import android.support.v4.app.Fragment; 5 | 6 | import com.soi.rapidandroidapp.events.common.BusProvider; 7 | import com.soi.rapidandroidapp.ui.dialog.AlertDialogFragment; 8 | import com.soi.rapidandroidapp.ui.dialog.ProgressDialogFragment; 9 | 10 | import java.io.Serializable; 11 | import java.util.Map; 12 | 13 | /** 14 | * A placeholder fragment containing a simple view. 15 | */ 16 | public class BaseFragment extends Fragment { 17 | 18 | 19 | private static final String PROGRESS_DIALOG_TAG = "PROGRESS_DIALOG_TAG"; 20 | 21 | protected boolean mSocialNetworkManagerInitialized = false; 22 | 23 | public BaseFragment() { 24 | } 25 | 26 | @Override 27 | public void onResume() 28 | { 29 | super.onResume(); 30 | BusProvider.getInstance().register(this); 31 | } 32 | 33 | @Override 34 | public void onPause() 35 | { 36 | super.onPause(); 37 | BusProvider.getInstance().unregister(this); 38 | } 39 | 40 | @Override 41 | public void onDestroy() 42 | { 43 | super.onDestroy(); 44 | } 45 | 46 | public boolean allowBackPressed() 47 | { 48 | return false; 49 | } 50 | 51 | public void onBackPressed() 52 | { 53 | getActivity().onBackPressed(); 54 | } 55 | 56 | /** 57 | * Show progress 58 | * @param text 59 | */ 60 | protected void showProgress(String text) { 61 | ProgressDialogFragment progressDialogFragment = ProgressDialogFragment.newInstance(text); 62 | progressDialogFragment.setTargetFragment(this, 0); 63 | progressDialogFragment.show(getFragmentManager(), PROGRESS_DIALOG_TAG); 64 | } 65 | 66 | /** 67 | * Hide progress indicator 68 | */ 69 | protected void hideProgress() { 70 | Fragment fragment = getFragmentManager().findFragmentByTag(PROGRESS_DIALOG_TAG); 71 | 72 | if (fragment != null) { 73 | getFragmentManager().beginTransaction().remove(fragment).commit(); 74 | } 75 | } 76 | 77 | /** 78 | * Handle error 79 | * @param text 80 | */ 81 | protected void handleError(String text) { 82 | AlertDialogFragment.newInstance("Error", text, false).show(getActivity().getSupportFragmentManager(), null); 83 | } 84 | 85 | /** 86 | * Handle success messages 87 | * @param title 88 | * @param message 89 | */ 90 | protected void handleSuccess(String title, String message) { 91 | AlertDialogFragment.newInstance(title, message,false).show(getActivity().getSupportFragmentManager(), null); 92 | } 93 | } -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/ui/dialog/AlertDialogFragment.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.ui.dialog; 2 | 3 | import android.app.AlertDialog; 4 | import android.app.Dialog; 5 | import android.content.DialogInterface; 6 | import android.os.Bundle; 7 | import android.support.annotation.NonNull; 8 | import android.support.v4.app.DialogFragment; 9 | import android.view.View; 10 | 11 | public class AlertDialogFragment extends DialogFragment implements Dialog.OnClickListener { 12 | 13 | private static final String PARAM_TITLE = "PARAM_TITLE"; 14 | private static final String PARAM_MESSAGE = "PARAM_MESSAGE"; 15 | private static final String PARAM_ACTION = "PARAM_ACTION"; 16 | 17 | private boolean mForceClose; 18 | 19 | public static AlertDialogFragment newInstance(String title, String message, boolean forceClose) { 20 | Bundle args = new Bundle(); 21 | args.putString(PARAM_TITLE, title); 22 | args.putString(PARAM_MESSAGE, message); 23 | args.putBoolean(PARAM_ACTION, forceClose); 24 | 25 | AlertDialogFragment alertDialogFragment = new AlertDialogFragment(); 26 | alertDialogFragment.setArguments(args); 27 | return alertDialogFragment; 28 | } 29 | 30 | @NonNull 31 | @Override 32 | public Dialog onCreateDialog(Bundle savedInstanceState) { 33 | final Bundle args = getArguments(); 34 | 35 | final String paramTitle = args.getString(PARAM_TITLE); 36 | final String paramMessage = args.getString(PARAM_MESSAGE); 37 | mForceClose = args.getBoolean(PARAM_ACTION); 38 | 39 | AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); 40 | builder.setTitle(paramTitle); 41 | builder.setMessage(paramMessage); 42 | builder.setPositiveButton(android.R.string.ok, this); 43 | return builder.create(); 44 | } 45 | 46 | @Override 47 | public void onClick(DialogInterface dialog, int which) { 48 | if (mForceClose) { 49 | getActivity().finish(); 50 | } 51 | } 52 | 53 | @Override 54 | public void onActivityCreated(Bundle savedInstanceState) { 55 | if (getDialog() == null ) { 56 | setShowsDialog(false); 57 | } 58 | super.onActivityCreated(savedInstanceState); 59 | } 60 | } -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/ui/dialog/ErrorDialogFragment.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.ui.dialog; 2 | 3 | import android.app.Dialog; 4 | import android.content.DialogInterface; 5 | import android.os.Bundle; 6 | import android.support.annotation.NonNull; 7 | import android.support.v4.app.DialogFragment; 8 | 9 | import com.google.android.gms.common.GooglePlayServicesUtil; 10 | 11 | import java.io.Serializable; 12 | import java.util.HashMap; 13 | 14 | /* A fragment to display an error dialog */ 15 | public class ErrorDialogFragment extends DialogFragment { 16 | 17 | public static final String KEY_DIALOG_ERROR = "dialogError"; 18 | public static final String KEY_REQUEST_RESOLVE_ERROR = "requestResolveError"; 19 | 20 | public static ErrorDialogFragment newInstance(HashMap params) 21 | { 22 | ErrorDialogFragment fragment = new ErrorDialogFragment(); 23 | if (params != null && params.size() > 0) { 24 | 25 | Bundle args = new Bundle(); 26 | for (String key : params.keySet()) { 27 | args.putSerializable(key, (Serializable) params.get(key)); 28 | } 29 | fragment.setArguments(args); 30 | } 31 | return fragment; 32 | } 33 | 34 | public ErrorDialogFragment() { } 35 | 36 | @NonNull 37 | @Override 38 | public Dialog onCreateDialog(Bundle savedInstanceState) { 39 | int errorCode = this.getArguments().getInt(KEY_DIALOG_ERROR); 40 | int requestCode = this.getArguments().getInt(KEY_REQUEST_RESOLVE_ERROR); 41 | return GooglePlayServicesUtil.getErrorDialog(errorCode, this.getActivity(), requestCode); 42 | } 43 | 44 | @Override 45 | public void onDismiss(DialogInterface dialog) { 46 | dialog.dismiss(); 47 | } 48 | 49 | @Override 50 | public void onActivityCreated(Bundle savedInstanceState) { 51 | if (getDialog() == null ) { 52 | setShowsDialog( false ); 53 | } 54 | super.onActivityCreated(savedInstanceState); 55 | } 56 | } -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/ui/dialog/ProgressDialogFragment.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.ui.dialog; 2 | 3 | import android.app.Dialog; 4 | import android.app.ProgressDialog; 5 | import android.os.Bundle; 6 | import android.support.annotation.NonNull; 7 | import android.support.v4.app.DialogFragment; 8 | 9 | 10 | public class ProgressDialogFragment extends DialogFragment { 11 | 12 | private static final String PARAM_MESSAGE = "ProgressDialogFragment.PARAM_MESSAGE"; 13 | 14 | public static ProgressDialogFragment newInstance(String message) { 15 | 16 | Bundle args = new Bundle(); 17 | args.putString(PARAM_MESSAGE, message); 18 | 19 | ProgressDialogFragment progressDialogFragment = new ProgressDialogFragment(); 20 | progressDialogFragment.setArguments(args); 21 | return progressDialogFragment; 22 | } 23 | 24 | @NonNull 25 | @Override 26 | public Dialog onCreateDialog(Bundle savedInstanceState) { 27 | 28 | final Bundle args = getArguments(); 29 | 30 | final String paramMessage = args.getString(PARAM_MESSAGE); 31 | 32 | Dialog dialog = ProgressDialog.show(getActivity(), "gRateFriends", paramMessage); 33 | dialog.setCancelable(true); 34 | return dialog; 35 | } 36 | 37 | @Override 38 | public void onActivityCreated(Bundle savedInstanceState) { 39 | if (getDialog() == null ) { 40 | setShowsDialog( false ); 41 | } 42 | super.onActivityCreated(savedInstanceState); 43 | } 44 | } -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/ui/fragments/HomeFragment.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.ui.fragments; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.AdapterView; 9 | import android.widget.ListView; 10 | import android.widget.TextView; 11 | 12 | import com.soi.rapidandroidapp.R; 13 | import com.soi.rapidandroidapp.api.managers.ApiManager; 14 | import com.soi.rapidandroidapp.api.managers.FoursquareApiManager; 15 | import com.soi.rapidandroidapp.api.managers.events.FoursquareExploreEvent; 16 | import com.soi.rapidandroidapp.api.managers.net.response.foursquare.explore.common.Item; 17 | import com.soi.rapidandroidapp.modules.Injector; 18 | import com.soi.rapidandroidapp.ui.adapters.PlacesAdapter; 19 | import com.soi.rapidandroidapp.ui.common.BaseFragment; 20 | import com.soi.rapidandroidapp.utilities.Constants; 21 | import com.squareup.otto.Subscribe; 22 | 23 | import java.io.Serializable; 24 | import java.text.SimpleDateFormat; 25 | import java.util.Date; 26 | import java.util.HashMap; 27 | 28 | import javax.inject.Inject; 29 | import javax.inject.Provider; 30 | 31 | import butterknife.ButterKnife; 32 | import butterknife.InjectView; 33 | 34 | public class HomeFragment extends BaseFragment implements AdapterView.OnItemClickListener{ 35 | 36 | @InjectView(R.id.txtWelcomeMsg) 37 | TextView mTxtWelcomeMsg; 38 | 39 | @InjectView(R.id.lvPlaces) 40 | ListView lvPlaces; 41 | 42 | @Inject 43 | Provider foursquareApiManagerProvider; 44 | 45 | private PlacesAdapter mPlacesAdapter; 46 | 47 | public static HomeFragment newInstance(HashMap params) { 48 | HomeFragment fragment = new HomeFragment(); 49 | 50 | Bundle args = new Bundle(); 51 | if (params != null) { 52 | for (String key : params.keySet()) { 53 | args.putSerializable(key, (Serializable) params.get(key)); 54 | } 55 | fragment.setArguments(args); 56 | } 57 | return fragment; 58 | } 59 | 60 | 61 | public HomeFragment() { 62 | } 63 | 64 | @Override 65 | public void onCreate(Bundle savedInstanceState) 66 | { 67 | super.onCreate(savedInstanceState); 68 | 69 | Injector.inject(this); 70 | } 71 | 72 | @Override 73 | public boolean allowBackPressed() 74 | { 75 | return true; 76 | } 77 | 78 | @Override 79 | public void onBackPressed() 80 | { 81 | getActivity().finish(); 82 | } 83 | 84 | @Override 85 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 86 | Bundle savedInstanceState) { 87 | View view = inflater.inflate(R.layout.fragment_home, container, false); 88 | 89 | ButterKnife.inject(this, view); 90 | 91 | mTxtWelcomeMsg.setText("HELLOOOOOO FOURSQUARE"); 92 | 93 | if (foursquareApiManagerProvider != null && foursquareApiManagerProvider.get() != null) { 94 | String ll = "40.7,-74"; 95 | String clientId = Constants.FOURSQUARE_API_CLIENT_ID; 96 | String clientSecret = Constants.FOURSQUARE_API_CLIENT_SECRET; 97 | int limit = 15; 98 | int sortByDistance = 1; 99 | String v = FoursquareApiManager.dateFormatter.format(new Date()); 100 | 101 | if (foursquareApiManagerProvider.get() != null) { 102 | foursquareApiManagerProvider.get().explore(ll, clientId, clientSecret, limit, sortByDistance, v); 103 | } 104 | } 105 | 106 | return view; 107 | } 108 | 109 | @Subscribe 110 | public void onFoursquareExploreEvent(FoursquareExploreEvent event) 111 | { 112 | if (event.getResponse() != null) { 113 | 114 | if (event.getResponse().response != null && event.getResponse().response.groups != null) { 115 | mPlacesAdapter = new PlacesAdapter(getActivity(), event.getResponse().response.groups.get(0).items); 116 | lvPlaces.setAdapter(mPlacesAdapter); 117 | lvPlaces.setOnItemClickListener(this); 118 | } 119 | } 120 | } 121 | 122 | 123 | @Override 124 | public void onItemClick(AdapterView parent, View view, int position, long id) { 125 | Item item = (Item) mPlacesAdapter.getItem(position); 126 | Intent intent = new Intent(getActivity(), ItemActivity.class); 127 | intent.putExtra(ItemActivity.KEY_ITEM, item); 128 | startActivity(intent); 129 | } 130 | } -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/ui/fragments/ItemActivity.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.ui.fragments; 2 | 3 | import android.os.Bundle; 4 | import android.view.Menu; 5 | import android.view.MenuItem; 6 | 7 | 8 | import com.soi.rapidandroidapp.R; 9 | import com.soi.rapidandroidapp.api.managers.net.response.foursquare.explore.common.Item; 10 | import com.soi.rapidandroidapp.ui.common.AbstractActivity; 11 | import com.soi.rapidandroidapp.ui.common.AbstractFragmentActivity; 12 | 13 | import java.util.HashMap; 14 | 15 | public class ItemActivity extends AbstractFragmentActivity { 16 | 17 | public static final String KEY_ITEM = "KEY_ITEM"; 18 | 19 | @Override 20 | public void initListeners() { 21 | 22 | } 23 | 24 | @Override 25 | protected void selectItem(int position) { 26 | 27 | } 28 | 29 | @Override 30 | protected void onCreate(Bundle savedInstanceState) { 31 | super.onCreate(savedInstanceState); 32 | 33 | Bundle bundle = getIntent().getExtras(); 34 | 35 | if (bundle.containsKey(KEY_ITEM)) { 36 | 37 | Item item = (Item)bundle.get(KEY_ITEM); 38 | HashMap data = new HashMap(); 39 | data.put(KEY_ITEM, item); 40 | createFragment(ItemViewFragment.newInstance(data), HomeFragment.class.getName(), false, true); 41 | } 42 | } 43 | 44 | @Override 45 | public boolean onCreateOptionsMenu(Menu menu) { 46 | getMenuInflater().inflate(R.menu.menu_main, menu); 47 | return true; 48 | } 49 | 50 | @Override 51 | public boolean onOptionsItemSelected(MenuItem item) { 52 | int id = item.getItemId(); 53 | if (id == R.id.action_settings) { 54 | return true; 55 | } 56 | 57 | return super.onOptionsItemSelected(item); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/ui/fragments/ItemViewFragment.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.ui.fragments; 2 | 3 | 4 | import android.os.Bundle; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.TextView; 9 | 10 | import com.soi.rapidandroidapp.R; 11 | import com.soi.rapidandroidapp.api.managers.net.response.foursquare.explore.common.Item; 12 | import com.soi.rapidandroidapp.ui.common.BaseFragment; 13 | 14 | import java.io.Serializable; 15 | import java.util.HashMap; 16 | 17 | import butterknife.ButterKnife; 18 | import butterknife.InjectView; 19 | 20 | public class ItemViewFragment extends BaseFragment { 21 | 22 | @InjectView(R.id.txtVenueName) 23 | TextView txtVenueName; 24 | 25 | @InjectView(R.id.txtCategoryName) 26 | TextView txtCategoryName; 27 | 28 | @InjectView(R.id.txtAddress) 29 | TextView txtAddress; 30 | 31 | 32 | public static ItemViewFragment newInstance(HashMap params) 33 | { 34 | ItemViewFragment fragment = new ItemViewFragment(); 35 | if (params != null && params.size() > 0) { 36 | 37 | Bundle args = new Bundle(); 38 | for (String key : params.keySet()) { 39 | args.putSerializable(key, (Serializable) params.get(key)); 40 | } 41 | fragment.setArguments(args); 42 | } 43 | return fragment; 44 | } 45 | 46 | public ItemViewFragment() { 47 | } 48 | 49 | @Override 50 | public void onCreate(Bundle savedInstanceState) { 51 | super.onCreate(savedInstanceState); 52 | 53 | } 54 | 55 | @Override 56 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 57 | Bundle savedInstanceState) { 58 | 59 | View parentView = inflater.inflate(R.layout.fragment_item_view, container, false); 60 | ButterKnife.inject(this, parentView); 61 | 62 | Bundle bundle = getArguments(); 63 | if (bundle.containsKey(ItemActivity.KEY_ITEM)) { 64 | Item item = (Item) bundle.get(ItemActivity.KEY_ITEM); 65 | 66 | if (item.venue != null) { 67 | txtVenueName.setText(item.venue.name); 68 | if (item.venue.categories != null && item.venue.categories.size() > 0) { 69 | txtCategoryName.setText(item.venue.categories.get(0).name); 70 | } 71 | if (item.venue.location != null) { 72 | txtAddress.setText(item.venue.location.address); 73 | } 74 | } 75 | } 76 | return parentView; 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/utilities/Constants.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.utilities; 2 | 3 | /** 4 | * Created by Spiros I. Oikonomakis on 10/18/14. 5 | */ 6 | public final class Constants { 7 | 8 | public final static String API_LIVE_URL = ""; 9 | public final static String API_STAGING_URL = ""; 10 | public final static String API_UAT_URL = ""; 11 | 12 | // Api headers which must be included in HTTP 13 | public static final String API_HEADER_HTTP_ACCEPT = "Accept"; 14 | public static final String API_HEADER_HTTP_ACCEPT_VALUE = "application/vnd.rapidandroid.v1"; 15 | 16 | // FOURSQUARE STATIC VARIABLES 17 | public final static String FOURSQUARE_API_URL = "https://api.foursquare.com/v2"; 18 | public final static String FOURSQUARE_API_CLIENT_ID = "NYTPRZJ23HJTUG2CWRITMW0EZUXYRPZOL4I0ECYKX2DAJMVI"; 19 | public final static String FOURSQUARE_API_CLIENT_SECRET = "IPF2YWWF2ELMRKM2KSI1QECUPTN4LSFRM5YO4HV3XVHQJDT4"; 20 | // 21 | 22 | 23 | public static final String DB_NAME = "rapidandroid.db"; 24 | public static final int DB_VERSION = 1; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/utilities/DialogsHelper.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.utilities; 2 | 3 | import android.app.Activity; 4 | import android.app.AlertDialog; 5 | import android.app.AlertDialog.Builder; 6 | import android.app.Dialog; 7 | import android.app.ProgressDialog; 8 | import android.content.Context; 9 | import android.content.DialogInterface; 10 | import android.graphics.drawable.ColorDrawable; 11 | import android.view.View; 12 | import android.view.Window; 13 | import android.view.animation.AnimationUtils; 14 | import android.view.inputmethod.InputMethodManager; 15 | import android.widget.Button; 16 | import android.widget.EditText; 17 | import android.widget.ImageView; 18 | import android.widget.TextView; 19 | import android.widget.Toast; 20 | 21 | import com.soi.rapidandroidapp.R; 22 | 23 | 24 | public class DialogsHelper { 25 | 26 | public static ProgressDialog waitingDialog; 27 | private static DialogsHelper _instance; 28 | 29 | /** 30 | * Singleton pattern for static methods and variables 31 | * You must run the singletons which you will use in the first Activity 32 | */ 33 | public static DialogsHelper getInstance() { 34 | if (_instance == null) { 35 | _instance = new DialogsHelper(); 36 | } 37 | return _instance; 38 | } 39 | /** 40 | * Close waiting dialog 41 | */ 42 | public static void closeWaitingDialog() { 43 | if (waitingDialog != null && waitingDialog.isShowing()) { 44 | waitingDialog.dismiss(); 45 | } 46 | } 47 | 48 | /** 49 | * Shows a dialog with a custom msg, two buttons (OK and Cancel) and the logo of the app 50 | * WARNING!!! Must show the dialog in Android's runOnUiThread method of the current activity 51 | * because of can't show a dialog out of the activity's ui thread 52 | * 53 | * @param act is the current activity eg. SoiActivity.this 54 | * @param msg is the msg which we want to show in our dialog 55 | */ 56 | public void showDialog(final Activity act, final String msg) { 57 | try { 58 | Builder builder = new Builder(act); 59 | builder.setMessage(msg) 60 | .setTitle(act.getResources().getString(R.string.app_name)) 61 | .setCancelable(true) 62 | .setPositiveButton(act.getResources().getString(R.string.txt_ok), 63 | new DialogInterface.OnClickListener() { 64 | public void onClick(DialogInterface dialog, int id) { 65 | 66 | } 67 | }); 68 | final AlertDialog alert = builder.create(); 69 | act.runOnUiThread(new Runnable() { 70 | 71 | @Override 72 | public void run() { 73 | alert.show(); 74 | } 75 | }); 76 | } catch (Exception e) { 77 | e.printStackTrace(); 78 | } 79 | } 80 | 81 | /** 82 | * Shows a dialog with a default msg for "No Internet Access", two buttons (OK and Cancel) and the logo of the app 83 | * WARNING!!! Must show the dialog in Android's runOnUiThread method of the current activity 84 | * 85 | * @param act is the current activity eg. SoiActivity.this 86 | */ 87 | public void showNoInternet(final Activity act) { 88 | try { 89 | Builder builder = new Builder(act); 90 | builder.setMessage(act.getResources().getString(R.string.txt_no_internet)) 91 | .setTitle(act.getResources().getString(R.string.app_name)) 92 | .setCancelable(false) 93 | //.setIcon(R.drawable.logoicon) 94 | .setPositiveButton(act.getResources().getString(R.string.txt_ok), 95 | new DialogInterface.OnClickListener() { 96 | public void onClick(DialogInterface dialog, int id) { 97 | 98 | } 99 | }); 100 | final AlertDialog alert = builder.create(); 101 | act.runOnUiThread(new Runnable() { 102 | 103 | @Override 104 | public void run() { 105 | alert.show(); 106 | } 107 | }); 108 | } catch (Exception e) { 109 | e.printStackTrace(); 110 | } 111 | } 112 | 113 | /** 114 | * Showing a custom styled dialog and adding actions to the buttons 115 | * @param context 116 | * @param title 117 | * @param text 118 | */ 119 | public Dialog getCustomDialog(Context context, String title, String text) { 120 | 121 | final Dialog dialog = new Dialog(context, 122 | android.R.style.Theme_Translucent); 123 | dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); 124 | 125 | dialog.setCancelable(true); 126 | dialog.setContentView(R.layout.layout_dialog); 127 | 128 | //Views 129 | Button btnCancel = (Button) dialog.findViewById(R.id.btncancel); 130 | TextView dialogTitle = (TextView) dialog.findViewById(R.id.dialog_title); 131 | TextView dialogText = (TextView) dialog.findViewById(R.id.dialog_text); 132 | 133 | dialogTitle.setText(title); 134 | dialogText.setText(text); 135 | 136 | btnCancel.setOnClickListener(new View.OnClickListener() { 137 | 138 | @Override 139 | public void onClick(View view) { 140 | dialog.cancel(); 141 | } 142 | 143 | }); 144 | 145 | final ImageView myImage = (ImageView) dialog.findViewById(R.id.loader); 146 | myImage.startAnimation(AnimationUtils.loadAnimation(context, R.anim.rotate) ); 147 | 148 | dialog.getWindow().setBackgroundDrawable(new ColorDrawable(0x7f000000)); 149 | 150 | return dialog; 151 | } 152 | 153 | /** 154 | * Shows a progress dialog when must run tasks,jobs for some time like an async event 155 | * WARNING!!! Must show the dialog in Android's runOnUiThread method of the current activity 156 | * 157 | * @param act is the current activity eg. SoiActivity.this 158 | * @param message 159 | */ 160 | public void showWaitingDialog(Activity act, String message) { 161 | if (waitingDialog != null) { 162 | if (waitingDialog.isShowing()) 163 | return; 164 | } 165 | waitingDialog = ProgressDialog.show(act, act.getResources().getString(R.string.app_name), message, true); 166 | waitingDialog.setIndeterminate(true); 167 | new Thread(new Runnable() { 168 | 169 | @Override 170 | public void run() { 171 | try { 172 | Thread.sleep(40 * 1000); 173 | } catch (InterruptedException e) { 174 | e.printStackTrace(); 175 | } 176 | if (waitingDialog != null && waitingDialog.isShowing()) { 177 | closeWaitingDialog(); 178 | } 179 | } 180 | }).start(); 181 | act.runOnUiThread(new Runnable() { 182 | 183 | @Override 184 | public void run() { 185 | waitingDialog.show(); 186 | } 187 | }); 188 | waitingDialog.setCancelable(false); 189 | } 190 | 191 | /** 192 | * Show a toast message 193 | * @param c 194 | * @param text 195 | */ 196 | public void toastMakeAndShow(Context c ,String text, int duration) { 197 | Toast.makeText(c, text, duration).show(); 198 | } 199 | } -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/utilities/ReflectionUtils.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.utilities; 2 | 3 | import java.lang.reflect.InvocationTargetException; 4 | 5 | /** 6 | * A set of helper methods for best-effort method calls via reflection. 7 | */ 8 | public class ReflectionUtils { 9 | 10 | public static Object tryInvoke(Object target, String methodName, Object... args) { 11 | Class[] argTypes = new Class[args.length]; 12 | for (int i = 0; i < args.length; i++) { 13 | argTypes[i] = args[i].getClass(); 14 | } 15 | 16 | return tryInvoke(target, methodName, argTypes, args); 17 | } 18 | 19 | public static Object tryInvoke(Object target, String methodName, Class[] argTypes, Object... args) { 20 | try { 21 | return target.getClass().getMethod(methodName, argTypes).invoke(target, args); 22 | } catch (NoSuchMethodException ignored) { 23 | } catch (IllegalAccessException ignored) { 24 | } catch (InvocationTargetException ignored) { 25 | } 26 | 27 | return null; 28 | } 29 | 30 | @SuppressWarnings("unchecked") 31 | public static E callWithDefault(Object target, String methodName, E defaultValue) { 32 | try { 33 | // noinspection unchecked 34 | return (E) target.getClass().getMethod(methodName, (Class[]) null).invoke(target); 35 | } catch (NoSuchMethodException ignored) { 36 | } catch (IllegalAccessException ignored) { 37 | } catch (InvocationTargetException ignored) { 38 | } 39 | 40 | return defaultValue; 41 | } 42 | } -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/utilities/StringUtils.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.utilities; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.io.InputStreamReader; 6 | import java.io.Reader; 7 | import java.io.StringWriter; 8 | import java.io.Writer; 9 | import java.security.InvalidParameterException; 10 | import java.security.MessageDigest; 11 | import java.util.Arrays; 12 | import java.util.Collection; 13 | import java.util.HashMap; 14 | import java.util.Iterator; 15 | import java.util.Map; 16 | 17 | public class StringUtils { 18 | private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; 19 | 20 | /** 21 | * Originally from RoboGuice: https://github.com/roboguice/roboguice/blob/master/roboguice/src/main/java/roboguice/util/StringUtils.java 22 | * Like join, but allows for a distinct final delimiter. For english sentences such 23 | * as "Alice, Bob and Charlie" use ", " and " and " as the delimiters. 24 | * 25 | * @param delimiter usually ", " 26 | * @param lastDelimiter usually " and " 27 | * @param objs the objects 28 | * @param the type 29 | * @return a string 30 | */ 31 | public static String joinAnd(final String delimiter, final String lastDelimiter, final Collection objs) { 32 | if (objs == null || objs.isEmpty()) 33 | return ""; 34 | 35 | final Iterator iter = objs.iterator(); 36 | final StringBuilder buffer = new StringBuilder(StringUtils.toString(iter.next())); 37 | int i = 1; 38 | while (iter.hasNext()) { 39 | final T obj = iter.next(); 40 | if (notEmpty(obj)) 41 | buffer.append(++i == objs.size() ? lastDelimiter : delimiter).append(StringUtils.toString(obj)); 42 | } 43 | return buffer.toString(); 44 | } 45 | 46 | public static String joinAnd(final String delimiter, final String lastDelimiter, final T... objs) { 47 | return joinAnd(delimiter, lastDelimiter, Arrays.asList(objs)); 48 | } 49 | 50 | public static String join(final String delimiter, final Collection objs) { 51 | if (objs == null || objs.isEmpty()) 52 | return ""; 53 | 54 | final Iterator iter = objs.iterator(); 55 | final StringBuilder buffer = new StringBuilder(StringUtils.toString(iter.next())); 56 | 57 | while (iter.hasNext()) { 58 | final T obj = iter.next(); 59 | if (notEmpty(obj)) buffer.append(delimiter).append(StringUtils.toString(obj)); 60 | } 61 | return buffer.toString(); 62 | } 63 | 64 | public static String join(final String delimiter, final T... objects) { 65 | return join(delimiter, Arrays.asList(objects)); 66 | } 67 | 68 | public static String toString(InputStream input) { 69 | StringWriter sw = new StringWriter(); 70 | copy(new InputStreamReader(input), sw); 71 | return sw.toString(); 72 | } 73 | 74 | public static String toString(Reader input) { 75 | StringWriter sw = new StringWriter(); 76 | copy(input, sw); 77 | return sw.toString(); 78 | } 79 | 80 | public static int copy(Reader input, Writer output) { 81 | long count = copyLarge(input, output); 82 | return count > Integer.MAX_VALUE ? -1 : (int) count; 83 | } 84 | 85 | public static long copyLarge(Reader input, Writer output) throws RuntimeException { 86 | try { 87 | char[] buffer = new char[DEFAULT_BUFFER_SIZE]; 88 | long count = 0; 89 | int n; 90 | while (-1 != (n = input.read(buffer))) { 91 | output.write(buffer, 0, n); 92 | count += n; 93 | } 94 | return count; 95 | } catch (IOException e) { 96 | throw new RuntimeException(e); 97 | } 98 | } 99 | 100 | public static String toString(final Object o) { 101 | return toString(o, ""); 102 | } 103 | 104 | public static String toString(final Object o, final String def) { 105 | return o == null ? def : 106 | o instanceof InputStream ? toString((InputStream) o) : 107 | o instanceof Reader ? toString((Reader) o) : 108 | o instanceof Object[] ? StringUtils.join(", ", (Object[]) o) : 109 | o instanceof Collection ? StringUtils.join(", ", (Collection) o) : o.toString(); 110 | } 111 | 112 | public static boolean isEmpty(final Object o) { 113 | return toString(o).trim().length() == 0; 114 | } 115 | 116 | public static boolean notEmpty(final Object o) { 117 | return toString(o).trim().length() != 0; 118 | } 119 | 120 | public static String md5(String s) { 121 | // http://stackoverflow.com/questions/1057041/difference-between-java-and-php5-md5-hash 122 | // http://code.google.com/p/roboguice/issues/detail?id=89 123 | try { 124 | 125 | final byte[] hash = MessageDigest.getInstance("MD5").digest(s.getBytes("UTF-8")); 126 | final StringBuilder hashString = new StringBuilder(); 127 | 128 | for (byte aHash : hash) { 129 | String hex = Integer.toHexString(aHash); 130 | 131 | if (hex.length() == 1) { 132 | hashString.append('0'); 133 | hashString.append(hex.charAt(hex.length() - 1)); 134 | } else { 135 | hashString.append(hex.substring(hex.length() - 2)); 136 | } 137 | } 138 | 139 | return hashString.toString(); 140 | 141 | } catch (Exception e) { 142 | throw new RuntimeException(e); 143 | } 144 | } 145 | 146 | public static String capitalize(String s) { 147 | final String c = StringUtils.toString(s); 148 | return c.length() >= 2 ? c.substring(0, 1).toUpperCase() + c.substring(1) : c.length() >= 1 ? c.toUpperCase() : c; 149 | } 150 | 151 | public static boolean equals(Object a, Object b) { 152 | return StringUtils.toString(a).equals(StringUtils.toString(b)); 153 | } 154 | 155 | public static boolean equalsIgnoreCase(Object a, Object b) { 156 | return StringUtils.toString(a).toLowerCase().equals(StringUtils.toString(b).toLowerCase()); 157 | } 158 | 159 | public static String[] chunk(String str, int chunkSize) { 160 | if (isEmpty(str) || chunkSize == 0) 161 | return new String[0]; 162 | 163 | final int len = str.length(); 164 | final int arrayLen = ((len - 1) / chunkSize) + 1; 165 | final String[] array = new String[arrayLen]; 166 | for (int i = 0; i < arrayLen; ++i) 167 | array[i] = str.substring(i * chunkSize, (i * chunkSize) + chunkSize < len ? (i * chunkSize) + chunkSize : len); 168 | 169 | return array; 170 | } 171 | 172 | public static String namedFormat(String str, Map substitutions) { 173 | for (String key : substitutions.keySet()) 174 | str = str.replace('$' + key, substitutions.get(key)); 175 | 176 | return str; 177 | } 178 | 179 | public static String namedFormat(String str, Object... nameValuePairs) { 180 | if (nameValuePairs.length % 2 != 0) 181 | throw new InvalidParameterException("You must include one value for each parameter"); 182 | 183 | final HashMap map = new HashMap(nameValuePairs.length / 2); 184 | for (int i = 0; i < nameValuePairs.length; i += 2) 185 | map.put(StringUtils.toString(nameValuePairs[i]), StringUtils.toString(nameValuePairs[i + 1])); 186 | 187 | return namedFormat(str, map); 188 | } 189 | 190 | } -------------------------------------------------------------------------------- /app/src/main/java/com/soi/rapidandroidapp/utilities/Utils.java: -------------------------------------------------------------------------------- 1 | package com.soi.rapidandroidapp.utilities; 2 | 3 | import android.annotation.TargetApi; 4 | import android.app.Activity; 5 | import android.content.ComponentName; 6 | import android.content.Context; 7 | import android.content.Intent; 8 | import android.content.pm.LabeledIntent; 9 | import android.content.pm.PackageManager; 10 | import android.content.pm.ResolveInfo; 11 | import android.net.ConnectivityManager; 12 | import android.net.NetworkInfo; 13 | import android.net.Uri; 14 | import android.net.wifi.WifiManager; 15 | import android.os.Build; 16 | import android.os.Environment; 17 | import android.os.StrictMode; 18 | import android.util.Patterns; 19 | import android.view.WindowManager; 20 | 21 | import com.soi.rapidandroidapp.R; 22 | 23 | 24 | import java.io.IOException; 25 | import java.net.HttpURLConnection; 26 | import java.net.MalformedURLException; 27 | import java.net.ProtocolException; 28 | import java.net.URL; 29 | import java.util.ArrayList; 30 | import java.util.Calendar; 31 | import java.util.Date; 32 | import java.util.Formatter; 33 | import java.util.List; 34 | import java.util.regex.Pattern; 35 | 36 | import javax.inject.Inject; 37 | 38 | public class Utils { 39 | 40 | private static Utils _instance; 41 | @Inject 42 | DialogsHelper dialogs; 43 | 44 | /** 45 | * Singleton patter 46 | * 47 | * @return 48 | */ 49 | public static synchronized Utils getInstance() { 50 | if (_instance == null) 51 | _instance = new Utils(); 52 | return _instance; 53 | } 54 | 55 | /** 56 | * Returns Integer for a specific 57 | * value 58 | * 59 | * @param value 60 | * @param safeReturn 61 | * @return 62 | */ 63 | public synchronized static Integer getSafeInteger(int value, Integer safeReturn) { 64 | try { 65 | return Integer.valueOf(value).intValue(); 66 | } catch (NumberFormatException ex) { 67 | return safeReturn; 68 | } catch (Exception e) { 69 | return safeReturn; 70 | } 71 | } 72 | 73 | @TargetApi(Build.VERSION_CODES.GINGERBREAD) 74 | public void strictModeDisable() { 75 | StrictMode.ThreadPolicy policy = new StrictMode. 76 | ThreadPolicy.Builder().permitAll().build(); 77 | StrictMode.setThreadPolicy(policy); 78 | } 79 | 80 | /** 81 | * Get formatted date by Stirng pattern 82 | * 83 | * @param pattern 84 | * @return 85 | */ 86 | public String getFormattedDateByPattern(String pattern) { 87 | Date dt = Calendar.getInstance().getTime(); 88 | Formatter formatter = new Formatter(); 89 | return formatter.format(pattern, dt).toString(); 90 | } 91 | 92 | public void setKeepScreenOn(Activity activity, boolean keepScreenOn) { 93 | if (keepScreenOn) { 94 | activity.getWindow(). 95 | addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 96 | } else { 97 | activity.getWindow(). 98 | clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 99 | } 100 | } 101 | 102 | public boolean checkIfUrlExists(String url) { 103 | boolean result = false; 104 | HttpURLConnection connection = null; 105 | try { 106 | URL myurl = new URL(url); 107 | connection = (HttpURLConnection) myurl.openConnection(); 108 | //Set request to header to reduce load as Subirkumarsao said. 109 | connection.setRequestMethod("HEAD"); 110 | int code = connection.getResponseCode(); 111 | if (code == HttpURLConnection.HTTP_OK) { 112 | result = true; 113 | } 114 | } catch (MalformedURLException e) { 115 | e.printStackTrace(); 116 | } catch (ProtocolException e) { 117 | e.printStackTrace(); 118 | } catch (IOException e) { 119 | e.printStackTrace(); 120 | } 121 | return result; 122 | } 123 | 124 | /** 125 | * Check if there is an internet connection via 3G 126 | * 127 | * @param ctx current context 128 | * @return 129 | */ 130 | public final boolean isOn3G(Context ctx) { 131 | NetworkInfo info = ((ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE)) 132 | .getActiveNetworkInfo(); 133 | return info != null && info.getTypeName().toLowerCase().equals("mobile"); 134 | } 135 | 136 | /** 137 | * Check if mobile device is connected to internet 138 | * 139 | * @param act 140 | * @return 141 | */ 142 | public boolean isConnected(final Context act) { 143 | ConnectivityManager connec = (ConnectivityManager) act.getSystemService(Context.CONNECTIVITY_SERVICE); 144 | NetworkInfo netInfo = null; 145 | try { 146 | netInfo = connec.getActiveNetworkInfo(); 147 | } catch (NullPointerException e) { 148 | return false; 149 | } 150 | if (netInfo != null) { 151 | return netInfo.getState() == NetworkInfo.State.CONNECTED; 152 | } 153 | connec = null; 154 | netInfo = null; 155 | return false; 156 | } 157 | 158 | public final boolean isOnWifi(Context context) { 159 | ConnectivityManager connManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); 160 | NetworkInfo mWifi = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI); 161 | return mWifi.isConnected(); 162 | } 163 | 164 | /** 165 | * Open Url in Browser 166 | * 167 | * @param ctx 168 | * @param url 169 | */ 170 | public void openURL(Activity ctx, String url) { 171 | if (isConnected(ctx)) { 172 | try { 173 | Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); 174 | ctx.startActivity(browserIntent); 175 | } catch (Exception e) { 176 | 177 | } 178 | } else { 179 | dialogs.showNoInternet(ctx); 180 | } 181 | } 182 | 183 | /** 184 | * Lock unlock wifi for streaming 185 | * 186 | * @param context 187 | * @param unlock 188 | */ 189 | public void wifiLockUnlock(Context context, boolean unlock) { 190 | 191 | WifiManager.WifiLock wifiLock = ((WifiManager) context.getSystemService(Context.WIFI_SERVICE)) 192 | .createWifiLock(WifiManager.WIFI_MODE_FULL, "radioLock"); 193 | 194 | if (unlock) { 195 | if (wifiLock.isHeld()) { 196 | wifiLock.release(); 197 | } 198 | } else { 199 | wifiLock.acquire(); 200 | } 201 | } 202 | 203 | /** 204 | * Get the path of the application 205 | * in the Android OS filesystem 206 | * 207 | * @param ctx 208 | * @returnman 209 | */ 210 | public String getPath(Context ctx) { 211 | return Environment.getExternalStorageDirectory() + "/" + ctx.getApplicationInfo().packageName.replaceAll("\\.", "") + "/"; 212 | } 213 | 214 | /** 215 | * @param context 216 | * @param title 217 | * @param text 218 | * @return 219 | */ 220 | public Intent getIntentChooser(Context context, String title, String text, String shareUrl) { 221 | Intent sendIntent = new Intent(Intent.ACTION_SEND); 222 | sendIntent.setType("text/plain"); 223 | 224 | // Email to Send 225 | Intent emailIntent = new Intent(); 226 | emailIntent.setAction(Intent.ACTION_SEND); 227 | emailIntent.putExtra(Intent.EXTRA_TEXT, title + " " + shareUrl); 228 | emailIntent.putExtra(Intent.EXTRA_SUBJECT, title); 229 | emailIntent.setType("message/rfc822"); 230 | 231 | Intent openInChooser = Intent.createChooser(emailIntent, context.getResources().getString(R.string.txt_share)); 232 | PackageManager pm = context.getPackageManager(); 233 | 234 | List resInfo = pm.queryIntentActivities(sendIntent, 0); 235 | List intentList = new ArrayList(); 236 | 237 | for (int i = 0; i < resInfo.size(); i++) { 238 | ResolveInfo ri = resInfo.get(i); 239 | String packageName = ri.activityInfo.packageName; 240 | if (ri.activityInfo.packageName.endsWith(".gm") || ri.activityInfo.name.toLowerCase().contains("gmail")) { 241 | emailIntent.setClassName(ri.activityInfo.packageName, ri.activityInfo.name); 242 | } else if (packageName.contains("twitter") || packageName.contains("facebook")) { 243 | Intent intent = new Intent(); 244 | intent.setComponent(new ComponentName(packageName, ri.activityInfo.name)); 245 | intent.setAction(Intent.ACTION_SEND); 246 | intent.setType("text/plain"); 247 | 248 | if (packageName.contains("twitter")) { 249 | intent.putExtra(Intent.EXTRA_TEXT, title + " " + shareUrl); 250 | } else if (packageName.contains("facebook")) { 251 | intent.putExtra(Intent.EXTRA_TEXT, shareUrl); 252 | } 253 | intentList.add(new LabeledIntent(intent, packageName, ri.loadLabel(pm), ri.icon)); 254 | } 255 | } 256 | LabeledIntent[] extraIntents = intentList.toArray(new LabeledIntent[intentList.size()]); 257 | openInChooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, extraIntents); 258 | return openInChooser; 259 | } 260 | 261 | /** 262 | * Email text validation 263 | * 264 | * @param email 265 | * @return 266 | */ 267 | public boolean validEmail(String email) { 268 | Pattern pattern = Patterns.EMAIL_ADDRESS; 269 | return pattern.matcher(email).matches(); 270 | } 271 | } -------------------------------------------------------------------------------- /app/src/main/res/anim/rotate.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/drawer_user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spirosoik/RapidAndroidFramework/1dec90ab50b15f737858d689df270c29265bc4e4/app/src/main/res/drawable-hdpi/drawer_user.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/fb_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spirosoik/RapidAndroidFramework/1dec90ab50b15f737858d689df270c29265bc4e4/app/src/main/res/drawable-hdpi/fb_icon.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spirosoik/RapidAndroidFramework/1dec90ab50b15f737858d689df270c29265bc4e4/app/src/main/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/twitter_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spirosoik/RapidAndroidFramework/1dec90ab50b15f737858d689df270c29265bc4e4/app/src/main/res/drawable-hdpi/twitter_icon.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spirosoik/RapidAndroidFramework/1dec90ab50b15f737858d689df270c29265bc4e4/app/src/main/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spirosoik/RapidAndroidFramework/1dec90ab50b15f737858d689df270c29265bc4e4/app/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spirosoik/RapidAndroidFramework/1dec90ab50b15f737858d689df270c29265bc4e4/app/src/main/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/dialog_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/list_item_bg_normal.xml: -------------------------------------------------------------------------------- 1 | 3 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/list_item_bg_pressed.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/list_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/loader.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spirosoik/RapidAndroidFramework/1dec90ab50b15f737858d689df270c29265bc4e4/app/src/main/res/drawable/loader.png -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_fragment.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_login.xml: -------------------------------------------------------------------------------- 1 | 10 | 11 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 10 | 11 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_navigation_drawer.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 11 | 17 | 26 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_scroll_fragment.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/layout/drawer_list_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 14 | 15 | 21 | 22 | 33 | 34 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_home.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 12 | 13 | 22 | 23 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_item_view.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 11 | 20 | 21 | 29 | 30 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_venue.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 14 | 21 | 22 | 30 | 31 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_dialog.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 20 | 21 | 28 | 29 | 34 | 35 | 41 | 42 | 43 | 44 |