├── .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:** [](https://travis-ci.org/spirosoik/RapidAndroidFramework)
5 |
6 | **Published in:** [](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 |
7 |
8 |
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 extends DBModel> 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 extends DBModel> 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 |
54 |
55 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/login.xml:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v21/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/api_keys.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 1f22812da16ce068a0369d078ed2829f224738e2
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | #727272
5 |
6 | #FFFFFF
7 | #B6B6B6
8 | #272727
9 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/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/res/values/generic_strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | OK
6 | share
7 | no internet connection
8 | 3G/LTE
9 | WIFI
10 | Cancel
11 |
12 |
13 | Your email or your password was wrong
14 | No results found
15 | An error occurred
16 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | RapidAndroidApp
6 | Hello world!
7 | Settings
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/release/res/values/api_integration_keys.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/src/release/res/values/api_keys.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 1f22812da16ce068a0369d078ed2829f224738e2
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/release/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/test/java/com/soi/rapidandroidapp/TestBaseApplication.java:
--------------------------------------------------------------------------------
1 | package com.soi.rapidandroidapp;
2 |
3 | import com.soi.rapidandroidapp.modules.RootTestModule;
4 | import java.lang.reflect.Method;
5 | import org.robolectric.RuntimeEnvironment;
6 | import org.robolectric.TestLifecycleApplication;
7 |
8 | /**
9 | * Created by Spiros I. Oikonomakis on 5/22/15.
10 | */
11 | public class TestBaseApplication extends BaseApplication implements TestLifecycleApplication {
12 |
13 | @Override
14 | public void onCreate() {
15 | isRunningTests = true;
16 | super.onCreate();
17 | }
18 |
19 | @Override
20 | public void beforeTest(Method method) {
21 |
22 | }
23 |
24 | @Override
25 | public void prepareTest(Object test) {
26 | }
27 |
28 | @Override
29 | public void afterTest(Method method) {
30 |
31 | }
32 |
33 | @Override
34 | public Object getRootModule() {
35 | return new RootTestModule();
36 | }
37 |
38 | public static void injectMocks(Object object) {
39 | TestBaseApplication app = (TestBaseApplication) RuntimeEnvironment.application;
40 | app.inject(object);
41 | }
42 | }
--------------------------------------------------------------------------------
/app/src/test/java/com/soi/rapidandroidapp/api/managers/FoursquareApiManagerTest.java:
--------------------------------------------------------------------------------
1 | package com.soi.rapidandroidapp.api.managers;
2 |
3 | import android.os.Build;
4 | import com.soi.rapidandroidapp.BuildConfig;
5 | import com.soi.rapidandroidapp.TestBaseApplication;
6 | import com.soi.rapidandroidapp.api.managers.events.FoursquareExploreEvent;
7 | import com.soi.rapidandroidapp.api.managers.events.FoursquareSearchEvent;
8 | import com.soi.rapidandroidapp.api.managers.net.response.foursquare.explore.Explore;
9 | import com.soi.rapidandroidapp.api.managers.net.response.foursquare.explore.common.Response;
10 | import com.soi.rapidandroidapp.api.managers.net.response.foursquare.search.SearchResult;
11 | import com.soi.rapidandroidapp.api.managers.net.response.foursquare.search.common.SearchResponse;
12 | import com.soi.rapidandroidapp.events.common.BusProvider;
13 | import com.soi.rapidandroidapp.test.support.ShadowMultiDex;
14 | import com.soi.rapidandroidapp.test.support.UnitTestSpecification;
15 | import com.soi.rapidandroidapp.utilities.Constants;
16 | import com.squareup.otto.Subscribe;
17 | import java.util.Date;
18 | import java.util.concurrent.CountDownLatch;
19 | import java.util.concurrent.TimeUnit;
20 | import javax.inject.Inject;
21 | import org.junit.Before;
22 | import org.junit.Test;
23 | import org.mockito.MockitoAnnotations;
24 | import org.robolectric.annotation.Config;
25 | import org.robolectric.internal.Shadow;
26 |
27 | import static org.fest.assertions.api.Assertions.assertThat;
28 |
29 | /**
30 | * Created by Spiros I. Oikonomakis on 10/17/14.
31 | *
32 | * This class handles all the api requests
33 | */
34 | @Config(sdk = Build.VERSION_CODES.JELLY_BEAN, constants = BuildConfig.class, shadows = {
35 | ShadowMultiDex.class})
36 | public class FoursquareApiManagerTest
37 | extends UnitTestSpecification {
38 |
39 | @Inject FoursquareApiManager foursquareApiManager;
40 |
41 | private String intent;
42 | private Integer radius;
43 | private String ll;
44 | private String clientId;
45 | private String clientSecret;
46 | private int limit;
47 | private int sortByDistance;
48 | private String v;
49 | private CountDownLatch signal;
50 |
51 | @Before
52 | public void setup() throws Exception {
53 |
54 | MockitoAnnotations.initMocks(this);
55 |
56 | TestBaseApplication.injectMocks(this);
57 |
58 | intent = "global";
59 | radius = 5000;
60 | ll = "40.7,-74";
61 | clientId = Constants.FOURSQUARE_API_CLIENT_ID;
62 | clientSecret = Constants.FOURSQUARE_API_CLIENT_SECRET;
63 | limit = 15;
64 | sortByDistance = 1;
65 | v = FoursquareApiManager.dateFormatter.format(new Date());
66 | }
67 |
68 | @Test
69 | public void testFoursquareExplore() throws Throwable {
70 | signal = new CountDownLatch(1);
71 | new Runnable() {
72 | @Override public void run() {
73 | foursquareApiManager.explore(ll, clientId, clientSecret, limit, sortByDistance, v);
74 | BusProvider.getInstance().register(new Object() {
75 | @Subscribe public void onFoursquareExplore(FoursquareExploreEvent event) {
76 | signal.countDown();
77 | assertThat(event).isNotNull();
78 |
79 | Explore explore = event.response;
80 | assertThat(explore).isNotNull();
81 |
82 | Response response = explore.response;
83 | assertThat(response).isNotNull();
84 | assertThat(response.groups).isNotNull();
85 | }
86 | });
87 | }
88 | };
89 | signal.await(15, TimeUnit.SECONDS);
90 | }
91 |
92 | @Test
93 | public void testFoursquareSearch() throws Throwable {
94 | signal = new CountDownLatch(1);
95 | new Runnable() {
96 | @Override public void run() {
97 | foursquareApiManager.search(intent, radius, ll, clientId, clientSecret, "ath", limit,
98 | sortByDistance, v);
99 | BusProvider.getInstance().register(new Object() {
100 | @Subscribe public void onFoursquareExplore(FoursquareSearchEvent event) {
101 | signal.countDown();
102 | assertThat(event).isNotNull();
103 |
104 | SearchResult searchResult = event.response;
105 | assertThat(searchResult).isNotNull();
106 |
107 | SearchResponse response = searchResult.response;
108 | assertThat(response).isNotNull();
109 | assertThat(response.venues).isNotNull();
110 | }
111 | });
112 | }
113 | };
114 | signal.await(15, TimeUnit.SECONDS);
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/app/src/test/java/com/soi/rapidandroidapp/managers/EnvironmentManagerTest.java:
--------------------------------------------------------------------------------
1 | package com.soi.rapidandroidapp.managers;
2 |
3 | import android.os.Build;
4 | import android.util.Log;
5 | import com.soi.rapidandroidapp.BuildConfig;
6 | import com.soi.rapidandroidapp.TestBaseApplication;
7 | import com.soi.rapidandroidapp.models.common.Environment;
8 | import com.soi.rapidandroidapp.test.support.ShadowMultiDex;
9 | import com.soi.rapidandroidapp.test.support.UnitTestSpecification;
10 | import com.soi.rapidandroidapp.utilities.Constants;
11 | import javax.inject.Inject;
12 | import org.junit.Before;
13 | import org.junit.Test;
14 | import org.mockito.MockitoAnnotations;
15 | import org.robolectric.annotation.Config;
16 | import retrofit.RestAdapter;
17 |
18 | import static org.fest.assertions.api.Assertions.assertThat;
19 |
20 | /**
21 | * Created by Spiros I. Oikonomakis on 11/4/14.
22 | */
23 | @Config(sdk = Build.VERSION_CODES.JELLY_BEAN, constants = BuildConfig.class, shadows = {
24 | ShadowMultiDex.class})
25 | public class EnvironmentManagerTest
26 | extends UnitTestSpecification {
27 |
28 | @Inject EnvironmentManager environmentManager;
29 |
30 | @Before
31 | public void setup() throws Exception {
32 |
33 | MockitoAnnotations.initMocks(this);
34 |
35 | TestBaseApplication.injectMocks(this);
36 | }
37 |
38 | @Test
39 | public void testEnviroment() {
40 | Environment environment = environmentManager.getEnvironment();
41 | assertThat(environment).isNotNull();
42 | assertThat(environment.toString()).isEqualTo(BuildConfig.ENVIRONMENT);
43 | }
44 |
45 | @Test
46 | public void testApiEnvironment() {
47 | String apiUrl = environmentManager.getEnviromentApiUrl();
48 | assertThat(apiUrl);
49 |
50 | switch (environmentManager.getEnvironment()) {
51 | case LIVE:
52 | assertThat(apiUrl).matches(Constants.API_LIVE_URL);
53 | break;
54 | case STAGING:
55 | assertThat(apiUrl).matches(Constants.API_STAGING_URL);
56 | break;
57 | case UAT:
58 | assertThat(apiUrl).matches(Constants.API_STAGING_URL);
59 | break;
60 | }
61 | }
62 |
63 | @Test
64 | public void testApiLogLevel() {
65 | RestAdapter.LogLevel logLevel = environmentManager.getEnvironmentApiLogLevel();
66 | assertThat(logLevel);
67 |
68 | switch (environmentManager.getEnvironment()) {
69 | case LIVE:
70 | assertThat(logLevel).isEqualTo(RestAdapter.LogLevel.BASIC);
71 | break;
72 | case STAGING:
73 | assertThat(logLevel).isEqualTo(RestAdapter.LogLevel.FULL);
74 | break;
75 | case UAT:
76 | assertThat(logLevel).isEqualTo(RestAdapter.LogLevel.FULL);
77 | break;
78 | }
79 | }
80 |
81 | @Test
82 | public void testLogLevel() {
83 | int logLevel = environmentManager.getEnvironmentLogLevel();
84 | assertThat(logLevel);
85 |
86 | switch (environmentManager.getEnvironment()) {
87 | case LIVE:
88 | assertThat(logLevel).isEqualTo(Log.INFO);
89 | break;
90 | case STAGING:
91 | assertThat(logLevel).isEqualTo(Log.DEBUG);
92 | break;
93 | case UAT:
94 | assertThat(logLevel).isEqualTo(Log.VERBOSE);
95 | break;
96 | }
97 | }
98 |
99 | @Test
100 | public void testCanTrackGA() {
101 | boolean logLevel = environmentManager.canTrackGA();
102 | assertThat(logLevel);
103 |
104 | switch (environmentManager.getEnvironment()) {
105 | case LIVE:
106 | assertThat(logLevel).isEqualTo(true);
107 | break;
108 | case STAGING:
109 | assertThat(logLevel).isEqualTo(false);
110 | break;
111 | case UAT:
112 | assertThat(logLevel).isEqualTo(true);
113 | break;
114 | }
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/app/src/test/java/com/soi/rapidandroidapp/models/UserModelTest.java:
--------------------------------------------------------------------------------
1 | package com.soi.rapidandroidapp.models;
2 |
3 | import android.os.Build;
4 | import com.soi.rapidandroidapp.BuildConfig;
5 | import com.soi.rapidandroidapp.models.common.DBModel;
6 | import com.soi.rapidandroidapp.test.support.ShadowMultiDex;
7 | import com.soi.rapidandroidapp.test.support.UnitTestSpecification;
8 | import java.lang.reflect.Field;
9 | import java.util.Date;
10 | import java.util.List;
11 | import java.util.Random;
12 | import ollie.Ollie;
13 | import ollie.query.Select;
14 | import org.junit.After;
15 | import org.junit.Test;
16 | import org.robolectric.annotation.Config;
17 |
18 | import static org.fest.assertions.api.Assertions.assertThat;
19 |
20 | /**
21 | * Created by Spiros I. Oikonomakis on 11/14/14.
22 | */
23 | @Config(sdk = Build.VERSION_CODES.JELLY_BEAN, constants = BuildConfig.class, shadows = {
24 | ShadowMultiDex.class
25 | }) public class UserModelTest extends UnitTestSpecification {
26 |
27 | @After public void tearDown() {
28 | setPrivateField(Ollie.class, "sInitialized", false);
29 | }
30 |
31 | @Test public void testSave() {
32 | User user = createUser();
33 | assertThat(user.id).isNotNull();
34 | }
35 |
36 | @Test public void testFindOne() throws IllegalAccessException, InstantiationException {
37 | User user = createUser();
38 | assertThat(user.id).isNotNull();
39 |
40 | User searchUser = Select.from(User.class).where("_id = ?", user.id).fetchSingle();
41 | assertThat(user.id).isEqualTo(searchUser.id);
42 | }
43 |
44 | @Test public void testFindAll() throws IllegalAccessException, InstantiationException {
45 | }
46 |
47 | @Test public void testDeleteOne() throws IllegalAccessException, InstantiationException {
48 | User user = createUser();
49 | assertThat(user.id).isNotNull();
50 |
51 | Long userId = user.id;
52 | DBModel.getInstance(User.class).deleteOne(user.id);
53 |
54 | User searchUser = (User) DBModel.getInstance(User.class).findOne(userId);
55 | assertThat(searchUser).isNull();
56 | }
57 |
58 | @Test public void testDeleteAll() throws IllegalAccessException, InstantiationException {
59 | User user = createUser();
60 | assertThat(user.id).isNotNull();
61 |
62 | DBModel.getInstance(User.class).deleteAll();
63 |
64 | @SuppressWarnings("unchecked") List userList =
65 | (List) DBModel.getInstance(User.class).findAll();
66 | assertThat(0).isEqualTo(userList.size());
67 | }
68 |
69 | private User createUser() {
70 | Random randomizer = new Random();
71 | User user = new User();
72 | user.userId = randomizer.nextLong();
73 | user.authToken = String.valueOf(new Date().getTime()) + "_token";
74 | user.avatar = String.valueOf(new Date().getTime()) + ".jpg";
75 | user.email = new Date().getTime() + "@test.com";
76 | user.lname = String.valueOf(randomizer.nextLong());
77 | user.fname = String.valueOf(randomizer.nextLong());
78 | user.save();
79 | return user;
80 | }
81 |
82 | private void setPrivateField(Class clz, String fieldName, boolean value) {
83 | Field field;
84 | try {
85 | field = clz.getDeclaredField(fieldName);
86 | field.setAccessible(true);
87 | field.set(null, value);
88 | } catch (Exception e) {
89 | e.printStackTrace();
90 | }
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/app/src/test/java/com/soi/rapidandroidapp/modules/MockAppTestModule.java:
--------------------------------------------------------------------------------
1 | package com.soi.rapidandroidapp.modules;
2 |
3 | import android.content.Context;
4 |
5 | import com.soi.rapidandroidapp.TestBaseApplication;
6 | import com.soi.rapidandroidapp.api.managers.FoursquareApiManager;
7 | import com.soi.rapidandroidapp.api.managers.FoursquareApiManagerTest;
8 | import com.soi.rapidandroidapp.managers.EnvironmentManagerTest;
9 | import com.soi.rapidandroidapp.managers.EnvironmentManager;
10 |
11 | import org.mockito.Mockito;
12 |
13 | import dagger.Module;
14 |
15 | @Module(
16 | complete = false,
17 | includes = {AppModule.class},
18 | injects = {FoursquareApiManagerTest.class, EnvironmentManagerTest.class, TestBaseApplication.class},
19 | overrides = true
20 | )
21 | public class MockAppTestModule {
22 |
23 | FoursquareApiManager provideFoursquareApiManager(Context context)
24 | {
25 | return Mockito.mock(FoursquareApiManager.class);
26 | }
27 |
28 | EnvironmentManager provideEnvironmentManager(Context context)
29 | {
30 | return Mockito.mock(EnvironmentManager.class);
31 | }
32 |
33 | }
--------------------------------------------------------------------------------
/app/src/test/java/com/soi/rapidandroidapp/modules/RootTestModule.java:
--------------------------------------------------------------------------------
1 | package com.soi.rapidandroidapp.modules;
2 |
3 | import dagger.Module;
4 |
5 | /**
6 | * Created by Spiros I. Oikonomakis on 5/22/15.
7 | */
8 | @Module
9 | (
10 | includes = {
11 | AndroidModule.class,
12 | AppModule.class,
13 | MockAppTestModule.class
14 | }
15 | )
16 | public class RootTestModule {
17 | }
--------------------------------------------------------------------------------
/app/src/test/java/com/soi/rapidandroidapp/test/support/RobolectricDataBindingTestRunner.java:
--------------------------------------------------------------------------------
1 | package com.soi.rapidandroidapp.test.support;
2 |
3 | import org.junit.runners.model.InitializationError;
4 | import org.robolectric.RobolectricTestRunner;
5 | import org.robolectric.annotation.Config;
6 | import org.robolectric.manifest.AndroidManifest;
7 | import org.robolectric.res.FileFsFile;
8 | import org.robolectric.util.Logger;
9 | import org.robolectric.util.ReflectionHelpers;
10 |
11 | public class RobolectricDataBindingTestRunner extends RobolectricTestRunner {
12 |
13 | private static final String BUILD_OUTPUT = "build/intermediates";
14 |
15 | public RobolectricDataBindingTestRunner(Class> klass) throws InitializationError {
16 | super(klass);
17 | }
18 |
19 | @Override
20 | protected AndroidManifest getAppManifest(Config config) {
21 | if (config.constants() == Void.class) {
22 | Logger.error("Field 'constants' not specified in @Config annotation");
23 | Logger.error("This is required when using RobolectricGradleTestRunner!");
24 | throw new RuntimeException("No 'constants' field in @Config annotation!");
25 | }
26 |
27 | final String type = getType(config);
28 | final String flavor = getFlavor(config);
29 | final String applicationId = getApplicationId(config);
30 |
31 | final FileFsFile res;
32 | if (FileFsFile.from(BUILD_OUTPUT, "res", flavor, type).exists()) {
33 | res = FileFsFile.from(BUILD_OUTPUT, "res", flavor, type);
34 | } else {
35 | // Use res/merged if the output directory doesn't exist for Data Binding compatibility
36 | res = FileFsFile.from(BUILD_OUTPUT, "res/merged", flavor, type);
37 | }
38 | final FileFsFile assets = FileFsFile.from(BUILD_OUTPUT, "assets", flavor, type);
39 |
40 | final FileFsFile manifest;
41 | if (FileFsFile.from(BUILD_OUTPUT, "manifests").exists()) {
42 | manifest = FileFsFile.from(BUILD_OUTPUT, "manifests", "full", flavor, type, "AndroidManifest.xml");
43 | } else {
44 | // Fallback to the location for library manifests
45 | manifest = FileFsFile.from(BUILD_OUTPUT, "bundles", flavor, type, "AndroidManifest.xml");
46 | }
47 |
48 | Logger.debug("Robolectric assets directory: " + assets.getPath());
49 | Logger.debug(" Robolectric res directory: " + res.getPath());
50 | Logger.debug(" Robolectric manifest path: " + manifest.getPath());
51 | Logger.debug(" Robolectric package name: " + applicationId);
52 | return new AndroidManifest(manifest, res, assets, applicationId);
53 | }
54 |
55 | private String getType(Config config) {
56 | try {
57 | return ReflectionHelpers.getStaticField(config.constants(), "BUILD_TYPE");
58 | } catch (Throwable e) {
59 | return null;
60 | }
61 | }
62 |
63 | private String getFlavor(Config config) {
64 | try {
65 | return ReflectionHelpers.getStaticField(config.constants(), "FLAVOR");
66 | } catch (Throwable e) {
67 | return null;
68 | }
69 | }
70 |
71 | private String getApplicationId(Config config) {
72 | try {
73 | return ReflectionHelpers.getStaticField(config.constants(), "APPLICATION_ID");
74 | } catch (Throwable e) {
75 | return null;
76 | }
77 | }
78 | }
--------------------------------------------------------------------------------
/app/src/test/java/com/soi/rapidandroidapp/test/support/ShadowMultiDex.java:
--------------------------------------------------------------------------------
1 | package com.soi.rapidandroidapp.test.support;
2 |
3 | import android.content.Context;
4 | import android.support.multidex.MultiDex;
5 |
6 | import org.robolectric.annotation.Implementation;
7 | import org.robolectric.annotation.Implements;
8 |
9 | @Implements(MultiDex.class)
10 | public class ShadowMultiDex {
11 | @Implementation
12 | public static void install(Context context) {
13 | // Do nothing since with Robolectric nothing is dexed.
14 | }
15 | }
--------------------------------------------------------------------------------
/app/src/test/java/com/soi/rapidandroidapp/test/support/UnitTestSpecification.java:
--------------------------------------------------------------------------------
1 | package com.soi.rapidandroidapp.test.support;
2 |
3 | import org.junit.runner.RunWith;
4 | import org.robolectric.RobolectricGradleTestRunner;
5 | import org.robolectric.annotation.Config;
6 |
7 | import java.io.IOException;
8 | import java.util.logging.LogManager;
9 |
10 | /**
11 | * Created by Spiros I. Oikonomakis on 5/18/15.
12 | */
13 | @RunWith(value = RobolectricDataBindingTestRunner.class)
14 | public abstract class UnitTestSpecification {
15 |
16 | public UnitTestSpecification() {
17 | // found no other way to set LogManager configuration by property file
18 | try {
19 | if (getClass().getResourceAsStream("/logging.properties") != null) {
20 | LogManager.getLogManager().readConfiguration(getClass().getResourceAsStream("/logging.properties"));
21 | }
22 | } catch (IOException e) {
23 | throw new RuntimeException(e);
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | mavenCentral()
7 | maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
8 | }
9 | dependencies {
10 | classpath 'com.android.tools.build:gradle:1.3.0'
11 | classpath 'com.jakewharton.hugo:hugo-plugin:1.2.1'
12 | classpath 'com.getkeepsafe.dexcount:dexcount-gradle-plugin:0.3.0'
13 |
14 | // NOTE: Do not place your application dependencies here; they belong
15 | // in the individual module build.gradle files
16 | }
17 | }
18 |
19 | allprojects {
20 | repositories {
21 | jcenter()
22 | mavenCentral()
23 | maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
24 | }
25 | }
26 |
27 | //Controlling Android Properties of all your modules for the main project
28 | ext {
29 | compileSdkVersion = 23
30 | buildToolsVersion = "23.0.2"
31 | }
32 |
33 | //Improving Build Server performance
34 | project.ext.preDexLibs = !project.hasProperty('disablePreDex')
35 |
36 | subprojects {
37 | project.plugins.whenPluginAdded { plugin ->
38 | if ("com.android.build.gradle.AppPlugin".equals(plugin.class.name)) {
39 | project.android.dexOptions.preDexLibraries = rootProject.ext.preDexLibs
40 | } else if ("com.android.build.gradle.LibraryPlugin".equals(plugin.class.name)) {
41 | project.android.dexOptions.preDexLibraries = rootProject.ext.preDexLibs
42 | }
43 | }
44 | }
--------------------------------------------------------------------------------
/circle.yml:
--------------------------------------------------------------------------------
1 | general:
2 | branches:
3 | only:
4 | - master
5 | dependencies:
6 | pre:
7 | - echo y | android update sdk --no-ui --all --filter tool,extra-android-m2repository,extra-android-support,extra-google-google_play_services,extra-google-m2repository,android-23
8 | - echo y | android update sdk --no-ui --all --filter build-tools-23.0.2
9 | - sudo chmod +x gradlew
10 | - sudo chmod +x scripts/run-circleci.sh
11 | test:
12 | override:
13 | - ./gradlew clean assemble -PdisablePreDex
14 | # start the emulator
15 | - emulator -avd circleci-android23 -no-audio -no-window:
16 | background: true
17 | parallel: true
18 | # wait for it to have booted
19 | - circle-android wait-for-boot
20 | # run tests against the emulator.
21 | - ./scripts/run-circleci.sh
22 | # copy the build outputs to artifacts
23 | - cp -r app/build/outputs $CIRCLE_ARTIFACTS
24 | # copy the test results to the test results directory.
25 | - cp -r app/build/outputs/androidTest-results/* $CIRCLE_TEST_REPORTS
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
2 | org.gradle.daemon=true
3 | org.gradle.parallel=true
4 | org.gradle.configureondemand=true
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spirosoik/RapidAndroidFramework/1dec90ab50b15f737858d689df270c29265bc4e4/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Tue Dec 09 16:52:47 EET 2014
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/scripts/robolectric-support.gradle:
--------------------------------------------------------------------------------
1 | // workaround force compile the test classes in android studio
2 | tasks.testClasses.dependsOn(tasks.testDebugClasses)
3 |
4 | // workaround to force recognize correct output dirs for android studio
5 | task addTest {
6 | def file = file(project.name + ".iml")
7 | doLast {
8 | try {
9 | def parsedXml = (new XmlParser()).parse(file)
10 | def node = parsedXml.component[1]
11 | def outputNode = parsedXml.component[1].output[0]
12 | def outputTestNode = parsedXml.component[1].'output-test'[0]
13 | def rewrite = false
14 |
15 | new Node(node as Node, 'sourceFolder', ['url': 'file://$MODULE_DIR$/' + "${it}", 'isTestSource': "true"])
16 |
17 | if(outputNode == null) {
18 | new Node(node as Node, 'output', ['url': 'file://$MODULE_DIR$/build/resources/testDebug'])
19 | } else {
20 | if(outputNode.attributes['url'] != 'file://$MODULE_DIR$/build/resources/testDebug') {
21 | outputNode.attributes = ['url': 'file://$MODULE_DIR$/build/resources/testDebug']
22 | rewrite = true
23 | }
24 | }
25 |
26 | if(outputTestNode == null) {
27 | new Node(node as Node, 'output-test', ['url': 'file://$MODULE_DIR$/build/test-classes/debug'])
28 | } else {
29 | if(outputTestNode.attributes['url'] != 'file://$MODULE_DIR$/build/test-classes/debug') {
30 | outputTestNode.attributes = ['url': 'file://$MODULE_DIR$/build/test-classes/debug']
31 | rewrite = true
32 | }
33 | }
34 |
35 | if(rewrite) {
36 | def writer = new StringWriter()
37 | new XmlNodePrinter(new PrintWriter(writer)).print(parsedXml)
38 | file.text = writer.toString()
39 | }
40 | } catch (FileNotFoundException e) {
41 | // iml not found, common on command line only builds
42 | }
43 |
44 | }
45 | }
46 | tasks.testClasses.dependsOn(tasks.addTest)
--------------------------------------------------------------------------------
/scripts/run-circleci.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | ./gradlew :app:testDebug \
3 | :app:connectedAndroidTest \
4 | -PcircleCi -PdisablePreDex
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------