diff --git a/.github/CodeStyle.md b/.github/CodeStyle.md new file mode 100644 index 0000000..bee4cde --- /dev/null +++ b/.github/CodeStyle.md @@ -0,0 +1,94 @@ +# Blink22 Android Coding Standards + +## Table of contents + +* [Code](#code) + * [Style](#style) + * [Indentation](#indentation) + * [Line length](#line-length) + * [Whitespace](#whitespace) + * [Imports](#imports) +* [XML](#xml) + * [Indentation](#indentation) + * [Structure](#structure) + * [Resources](#resource-Id-names) + * [Layout Names](#layout-names) + * [Id names](#id-names) + * [Example](#example) +* [Documentation](#documentation) + * [Javadoc](#javadoc) + * [Comments](#comments) + +## Code +#### Style +Follow the official Android code style guidelines: [http://source.android.com/source/code-style.html](http://source.android.com/source/code-style.html) + +#### Indentation +Use 4 spaces per indentation level and no tabs. + +#### Line Length +Stick within the 120 char line limit. Use line breaks to split up code according to the style guidelines. + +#### Whitespace +Code should not have any trailing whitespace to avoid creating unnecessary diff issues. Please setup your IDE to remove these as a save action. + +#### Imports +Please setup your IDE to remove all unused imports as a save action. + +## XML + +#### Indentation +Use 4 spaces per indentation level and no tabs. +Each attribute should appear on its own line. + +#### Structure +XML tags should be ordered as follows: 'xmlns' first, then id, then layout_width and layout_height then alphabetically. + +Add a space between the closing slash and the final attribute. E.g. ```android:textSize="10dp" />``` + +#### Resource Id names +String Resources -> ```if related to the app we use app__ ``` +#### Layout names +Activities layouts -> ```activity_``` +Fragments layouts -> ```fragment_ ``` +Cards/Items of lists,recyclerviews...etc -> ```item_ ``` +#### Id names +Layout resource ids should use the following naming convention where possible:
+```_```
+E.g. +``` +listview_hotels +imageview_star_rating +``` + +#### Example +Given a layout called activity_profile.xml: +``` + + + + + + +``` + + +## Documentation + +#### Javadoc +Any new classes that are committed must include a class descriptor Javadoc along with: +```@author name@address.com``` +Javadoc any public methods, variables and constants. Javadoc private methods where beneficial. + +#### Comments +Use in-line commenting to help the next developer who might be editing your code, even if it seems obvious now. Inline comments should appear on the line above the code your are commenting. +Comment XML View elements using ``````. + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5edb4ee --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +.DS_Store +/build +/captures +.externalNativeBuild diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser new file mode 100644 index 0000000..36c5ae1 Binary files /dev/null and b/.idea/caches/build_file_checksums.ser differ diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..30aa626 --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..c4e6bb9 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,19 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..c0f68ed --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 0000000..7f68460 --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/README.md b/README.md index e69de29..620fbed 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,60 @@ +# Android Boilerplate + + +## Description +Android boilerplate project to create new Android projects from. It provides basic architecture, tools and guidelines that we use when developing Android apps. + +## Getting started +First clone the boilerplate repository. Next, if you want to copy the boilerplate into your own repository follow _Clone into your own repository_. +If you just want to get started with customizing things for your own project skip onto _Make it your own_. + +### Clone into your own repository +Follow these steps if you have a repository with a branch you'd like to copy the boilerplate project into: +``` +$ cd +$ git remote add newrepo +$ git checkout --orphan copy +$ git commit -m "Copying boilerplate" +$ git push newrepo copy: +``` +This will copy the boilerplate project without history to your own branch in your repository. + +### Make it your own +Personalise the boilerplate for your own project: +1. Rename `com.blink22.blink22_boilerplate` packages to your own domain's stucture. E.g `com.mydomain.myapp`. + See [StackOverflow](http://stackoverflow.com/a/29092698) for steps to easily accomplish this in Android Studio. + +2. Open `app/build.gradle` and change the following to match your new package names: + * `applicationId "com.mydomain.myapp"` + * `testInstrumentationRunner "com.mydomain.myapp.application.ApplicationTestRunner"` + + + +## Modules +This project consists of the following modules: + +- app : contains all android related code -> activities - fragments ..etc +- core : contains almost all app logic pure java -> presenters - api client - models + +## Code Standards +[Code Style](.github/CodeStyle.md) + +## Code Structure +This project is based on Model View Presenter Structure, this project make use of Dagger 2, RxJava, RxAndroid, Retrofit. +## Used Third Parties : +* [scalable DP](https://github.com/intuit/sdp) +* [Progress/Loading](https://github.com/81813780/AVLoadingIndicatorView) +* [Toast/Alert](https://github.com/Tapadoo/Alerter) +* [Android Utility](https://github.com/mohsenoid/android_utils) +* [ButterKnife](https://github.com/JakeWharton/butterknife) +* [Image Chooser"PIX"](https://github.com/akshay2211/PixImagePicker) +* [Image Loader/Caching"Glide"](https://github.com/bumptech/glide) +* [WebVIEW](https://github.com/TheFinestArtist/FinestWebView-Android) +* [RxPermission](https://github.com/tbruyelle/RxPermissions) + +## Tools +* [Android Studio](https://developer.android.com/studio/index.html), Provides the fastest tools for building apps on every type of Android device. +* [Gradle](https://gradle.org/), An open source build automation system. + +## Testing and CI +##TODO diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..eae0504 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,93 @@ +apply plugin: 'com.android.application' + +apply plugin: 'kotlin-android' + +apply plugin: 'kotlin-android-extensions' + +apply plugin: DatePlugin + + +android { + compileSdkVersion 28 + defaultConfig { + applicationId "com.blink22.blink22_boilerplate" + minSdkVersion 17 + targetSdkVersion 28 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } +} + +dependencies { + implementation fileTree(include: ['*.jar'], dir: 'libs') + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation 'com.android.support:appcompat-v7:28.0.0' + implementation 'com.android.support.constraint:constraint-layout:1.1.3' + // Dependencies for local unit tests + testImplementation rootProject.ext.testingLibraries.junit + testImplementation rootProject.ext.testingLibraries.mockito + testImplementation rootProject.ext.testingLibraries.hamcrest + testImplementation rootProject.ext.testingLibraries.powerMockitoModule + testImplementation rootProject.ext.testingLibraries.powerMockitoApi + // Android Testing Support Library's runner and rules + androidTestImplementation rootProject.ext.testingLibraries.testSupportRunner + androidTestImplementation rootProject.ext.testingLibraries.testSupportRules + // Espresso UI Testing dependencies. + androidTestImplementation rootProject.ext.testingLibraries.espressoCore + androidTestImplementation rootProject.ext.testingLibraries.espressoContrib + implementation rootProject.ext.testingLibraries.espressoIdlingResource + + //Android Libs + implementation rootProject.ext.appLibraries.appCompatSupport + implementation rootProject.ext.appLibraries.designSupport + implementation rootProject.ext.appLibraries.cardView + implementation rootProject.ext.appLibraries.recyclerView + implementation rootProject.ext.appLibraries.scalableDP + implementation rootProject.ext.appLibraries.butterknife + implementation rootProject.ext.appLibraries.progressLib + implementation rootProject.ext.appLibraries.toastLib + implementation rootProject.ext.appLibraries.utils + implementation rootProject.ext.appLibraries.imageChooser + + + annotationProcessor rootProject.ext.aptLibraries.butterknifeCompiler + implementation rootProject.ext.libraries.rxandroid + implementation rootProject.ext.libraries.dagger + annotationProcessor rootProject.ext.aptLibraries.daggerCompiler + + + + + + + implementation project(':core') +} + +class DatePlugin implements Plugin { + void apply(Project project) { + project.task('addCurrentDatePluginTask') { + project.android.applicationVariants.all { variant -> + variant.outputs.all { output -> + def date = new Date().format("dd-MM-yyyy") + def fileName = variant.name + "_" + date + ".apk" + output.outputFileName = fileName + } + } + } + } +} + +gradle.taskGraph.whenReady { + addCurrentDatePluginTask +} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/app/src/androidTest/java/com/blink22/blink22_boilerplate/ExampleInstrumentedTest.kt b/app/src/androidTest/java/com/blink22/blink22_boilerplate/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..e4d32d8 --- /dev/null +++ b/app/src/androidTest/java/com/blink22/blink22_boilerplate/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package com.blink22.blink22_boilerplate + +import android.support.test.InstrumentationRegistry +import android.support.test.runner.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getTargetContext() + assertEquals("com.blink22.blink22_boilerplate", appContext.packageName) + } +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..743b2c1 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/blink22/blink22_boilerplate/AndroidModule.java b/app/src/main/java/com/blink22/blink22_boilerplate/AndroidModule.java new file mode 100644 index 0000000..3c89b33 --- /dev/null +++ b/app/src/main/java/com/blink22/blink22_boilerplate/AndroidModule.java @@ -0,0 +1,33 @@ +package com.blink22.blink22_boilerplate; + +import android.content.Context; +import android.content.res.Resources; + +import javax.inject.Singleton; + +import dagger.Module; +import dagger.Provides; + +@Module +public class AndroidModule { + private AppInstance application; + + public AndroidModule(AppInstance application) { + this.application = application; + } + + @Provides + @Singleton + Context provideContext() { + return application.getApplicationContext(); + } + + @Provides + @Singleton + Resources provideResources() { + return application.getResources(); + } + + + +} \ No newline at end of file diff --git a/app/src/main/java/com/blink22/blink22_boilerplate/AppInstance.java b/app/src/main/java/com/blink22/blink22_boilerplate/AppInstance.java new file mode 100644 index 0000000..c851459 --- /dev/null +++ b/app/src/main/java/com/blink22/blink22_boilerplate/AppInstance.java @@ -0,0 +1,49 @@ +package com.blink22.blink22_boilerplate; + +import android.app.Application; +import android.content.Context; + +import com.blink22.blink22_boilerplate.ExampleFeeds.ExampleFeedsSubComponent; +import com.blink22.core.modules.example.ExampleModule; +import com.blink22.core.util.LanguageProvider; + +import java.util.Locale; + +public class AppInstance extends Application { + private static ApplicationComponent component; + + @Override + public void onCreate() { + super.onCreate(); + component = createComponent(); + LanguageProvider.setCurrentLanguage(Locale.getDefault().getLanguage()); + + } + + public ApplicationComponent createComponent() { + return DaggerApplicationComponent.builder() + .androidModule(new AndroidModule(this)) + .build(); + } + + public static ApplicationComponent getComponent() { + return component; + } + + public static AppInstance get(Context context) { + return (AppInstance) context.getApplicationContext(); + } + + + private ExampleFeedsSubComponent exampleFeedsSubComponent; + public ExampleFeedsSubComponent getExampleFeedsSubComponent(){ + return exampleFeedsSubComponent != null ? exampleFeedsSubComponent: (exampleFeedsSubComponent = createExampleFeedsSubComponent()); + } + private ExampleFeedsSubComponent createExampleFeedsSubComponent(){ + return exampleFeedsSubComponent = component.plus(new ExampleModule()); + } + public void releaseHomeSubComponent(){ + exampleFeedsSubComponent = null; + } + +} diff --git a/app/src/main/java/com/blink22/blink22_boilerplate/ApplicationComponent.java b/app/src/main/java/com/blink22/blink22_boilerplate/ApplicationComponent.java new file mode 100644 index 0000000..55d6fd8 --- /dev/null +++ b/app/src/main/java/com/blink22/blink22_boilerplate/ApplicationComponent.java @@ -0,0 +1,25 @@ +package com.blink22.blink22_boilerplate; + +import com.blink22.blink22_boilerplate.ExampleFeeds.ExampleFeedsSubComponent; +import com.blink22.blink22_boilerplate.main.MainActivity; +import com.blink22.blink22_boilerplate.util.database.DataBaseModule; +import com.blink22.core.domain.ApiModule; +import com.blink22.core.domain.ClientModule; +import com.blink22.core.modules.example.ExampleModule; + +import javax.inject.Singleton; + +import dagger.Component; + +/** + * Created by m.hemdan on 4/5/18. + */ +@Singleton +@Component(modules = {AndroidModule.class, ApplicationModule.class, + ApiModule.class,ClientModule.class, + DataBaseModule.class}) +public interface ApplicationComponent { + void inject(MainActivity activity); + + ExampleFeedsSubComponent plus(ExampleModule module); +} diff --git a/app/src/main/java/com/blink22/blink22_boilerplate/ApplicationModule.java b/app/src/main/java/com/blink22/blink22_boilerplate/ApplicationModule.java new file mode 100644 index 0000000..e8f53c5 --- /dev/null +++ b/app/src/main/java/com/blink22/blink22_boilerplate/ApplicationModule.java @@ -0,0 +1,118 @@ +package com.blink22.blink22_boilerplate; + +import android.content.Context; + +import com.blink22.blink22_boilerplate.util.AppSchedulerProvider; +import com.blink22.blink22_boilerplate.util.StateManagerImpl; +import com.blink22.core.domain.URLS; +import com.blink22.core.util.Constants; +import com.blink22.core.util.LanguageProvider; +import com.blink22.core.util.SchedulerProvider; +import com.blink22.core.util.StateManager; +import com.mirhoseini.utils.Utils; + +import java.io.File; + +import javax.inject.Named; +import javax.inject.Singleton; + +import dagger.Module; +import dagger.Provides; +import okhttp3.HttpUrl; + + +/** + * Created by m.hemdan on 8/16/17. + */ +@Module +public class ApplicationModule { + @Provides + @Singleton + @Named("isDebug") + boolean provideIsDebug() { + return BuildConfig.DEBUG; + } + + @Provides + @Singleton + @Named("networkTimeoutInSeconds") + int provideNetworkTimeoutInSeconds() { + return Constants.NETWORK_CONNECTION_TIMEOUT; + } + + @Provides + @Singleton + HttpUrl provideEndpoint() { + return HttpUrl.parse(URLS.BASE_URL); + } + + @Provides + @Named("appLanguage") + LanguageProvider provideLanguage(){ + return new LanguageProvider(); + } + + @Provides + @Singleton + SchedulerProvider provideAppScheduler() { + return new AppSchedulerProvider(); + } + + @Provides + @Singleton + @Named("cacheSize") + long provideCacheSize() { + return Constants.CACHE_SIZE; + } + + @Provides + @Singleton + @Named("cacheMaxAge") + int provideCacheMaxAgeMinutes() { + return Constants.CACHE_MAX_AGE; + } + + @Provides + @Singleton + @Named("cacheMaxStale") + int provideCacheMaxStaleDays() { + return Constants.CACHE_MAX_STALE; + } + + @Provides + @Singleton + @Named("retryCount") + public int provideApiRetryCount() { + return Constants.API_RETRY_COUNT; + } + + @Provides + @Singleton + @Named("cacheDir") + File provideCacheDir(Context context) { + return context.getCacheDir(); + } + + @Provides + @Named("isConnect") + boolean provideIsConnect(Context context) { + return Utils.isConnected(context); + } + +// @Provides +// FirebaseAnalytics provideFirebaseAnalytics(Context context) { +// return FirebaseAnalytics.getInstance(context); +// } + +// @Provides +// FacebookImpl provideFacebookImpl(){ +// return FacebookImpl.getInstance(); +// } + + @Provides + @Singleton + public StateManager provideStateManager(StateManagerImpl stateManager) { + return stateManager; + } + +} diff --git a/app/src/main/java/com/blink22/blink22_boilerplate/ExampleFeeds/ExampleFeedsActivity.java b/app/src/main/java/com/blink22/blink22_boilerplate/ExampleFeeds/ExampleFeedsActivity.java new file mode 100644 index 0000000..bf0b01d --- /dev/null +++ b/app/src/main/java/com/blink22/blink22_boilerplate/ExampleFeeds/ExampleFeedsActivity.java @@ -0,0 +1,19 @@ +package com.blink22.blink22_boilerplate.ExampleFeeds; + +import com.blink22.blink22_boilerplate.AppInstance; +import com.blink22.blink22_boilerplate.ApplicationComponent; +import com.blink22.blink22_boilerplate.base.BaseActivity; +import com.blink22.core.modules.example.ExampleContract; + +import javax.inject.Inject; + +public class ExampleFeedsActivity extends BaseActivity { + + @Inject + ExampleContract.Presenter presenter; + + @Override + protected void injectDependencies(AppInstance application, ApplicationComponent component) { + application.getExampleFeedsSubComponent().inject(this); + } +} diff --git a/app/src/main/java/com/blink22/blink22_boilerplate/ExampleFeeds/ExampleFeedsSubComponent.java b/app/src/main/java/com/blink22/blink22_boilerplate/ExampleFeeds/ExampleFeedsSubComponent.java new file mode 100644 index 0000000..6c84d54 --- /dev/null +++ b/app/src/main/java/com/blink22/blink22_boilerplate/ExampleFeeds/ExampleFeedsSubComponent.java @@ -0,0 +1,12 @@ +package com.blink22.blink22_boilerplate.ExampleFeeds; + +import com.blink22.core.modules.example.Example; +import com.blink22.core.modules.example.ExampleModule; + +import dagger.Subcomponent; + +@Example +@Subcomponent(modules = {ExampleModule.class}) +public interface ExampleFeedsSubComponent { + void inject(ExampleFeedsActivity activity); +} diff --git a/app/src/main/java/com/blink22/blink22_boilerplate/base/BaseActivity.java b/app/src/main/java/com/blink22/blink22_boilerplate/base/BaseActivity.java new file mode 100644 index 0000000..138430a --- /dev/null +++ b/app/src/main/java/com/blink22/blink22_boilerplate/base/BaseActivity.java @@ -0,0 +1,78 @@ +package com.blink22.blink22_boilerplate.base; + +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v7.app.AppCompatActivity; + +import com.blink22.blink22_boilerplate.AppInstance; +import com.blink22.blink22_boilerplate.ApplicationComponent; +import com.blink22.blink22_boilerplate.R; +import com.blink22.blink22_boilerplate.base.loading.LoadingFragmentDialog; +import com.blink22.core.base.BaseView; +import com.tapadoo.alerter.Alerter; +import com.tapadoo.alerter.OnHideAlertListener; + +public abstract class BaseActivity extends AppCompatActivity implements BaseView{ + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + injectDependencies(AppInstance.get(this),AppInstance.getComponent()); + } + protected abstract void injectDependencies(AppInstance application, ApplicationComponent component); + + + @Override + public void showError(Throwable throwable) { + showMessage(throwable.getMessage()); + } + + @Override + public void showMessage(String message) { + Alerter.create(this) + .setText(message) + .setBackgroundColorRes(R.color.colorPrimaryDark) + .setDuration(2000) + .enableSwipeToDismiss() + .enableVibration(true) + .setOnHideListener(new OnHideAlertListener() { + @Override + public void onHide() { + Alerter.hide(); + } + }) + .show(); + } + + + @Override + public void showServerDownError() { +// showMessage(getResources().getString(R.string.app_server_down_error)); + + } + + @Override + public void showOfflineMessage() { +// showMessage(getResources().getString(R.string.app_connectivity_error)); + } + + @Override + public void showLoading() { + LoadingFragmentDialog fragment = (LoadingFragmentDialog) getSupportFragmentManager().findFragmentByTag(LoadingFragmentDialog.FRAGMENT_TAG); + if (fragment == null) { + fragment = new LoadingFragmentDialog(); + fragment.setCancelable(false); + getSupportFragmentManager().beginTransaction() + .add(fragment, LoadingFragmentDialog.FRAGMENT_TAG) + .commitAllowingStateLoss(); + } + } + + @Override + public void hideLoading() { + LoadingFragmentDialog fragment = (LoadingFragmentDialog) getSupportFragmentManager().findFragmentByTag(LoadingFragmentDialog.FRAGMENT_TAG); + if (fragment != null) { + getSupportFragmentManager().beginTransaction().remove(fragment).commitAllowingStateLoss(); + } + } +} diff --git a/app/src/main/java/com/blink22/blink22_boilerplate/base/fragment/BaseFragment.java b/app/src/main/java/com/blink22/blink22_boilerplate/base/fragment/BaseFragment.java new file mode 100644 index 0000000..1e4dfb6 --- /dev/null +++ b/app/src/main/java/com/blink22/blink22_boilerplate/base/fragment/BaseFragment.java @@ -0,0 +1,49 @@ +package com.blink22.blink22_boilerplate.base.fragment; + +import android.content.Context; +import android.support.v4.app.Fragment; + +import com.blink22.blink22_boilerplate.AppInstance; +import com.blink22.blink22_boilerplate.base.BaseActivity; +import com.blink22.core.base.BaseView; + +public abstract class BaseFragment extends Fragment implements BaseView{ + + @Override + public void showError(Throwable throwable) { + ((BaseActivity)getActivity()).showError(throwable); + } + + @Override + public void showMessage(String message) { + ((BaseActivity)getActivity()).showMessage(message); + } + + @Override + public void showServerDownError() { + ((BaseActivity)getActivity()).showServerDownError(); + } + + @Override + public void showOfflineMessage() { + ((BaseActivity)getActivity()).showOfflineMessage(); + } + + @Override + public void showLoading() { + ((BaseActivity)getActivity()).showLoading(); + } + + @Override + public void hideLoading() { + ((BaseActivity)getActivity()).hideLoading(); + } + + @Override + public void onAttach(Context context) { + super.onAttach(context); + + injectDependencies(AppInstance.get(getContext())); + } + protected abstract void injectDependencies(AppInstance application); +} diff --git a/app/src/main/java/com/blink22/blink22_boilerplate/base/loading/LoadingFragment.java b/app/src/main/java/com/blink22/blink22_boilerplate/base/loading/LoadingFragment.java new file mode 100644 index 0000000..2dfc47a --- /dev/null +++ b/app/src/main/java/com/blink22/blink22_boilerplate/base/loading/LoadingFragment.java @@ -0,0 +1,52 @@ +package com.blink22.blink22_boilerplate.base.loading; + +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.blink22.blink22_boilerplate.R; +import com.wang.avi.AVLoadingIndicatorView; + +import butterknife.BindView; +import butterknife.ButterKnife; + +/** + * Created by m.hemdan on 9/18/17. + */ + +public class LoadingFragment extends Fragment { + public static String FRAGMENT_TAG = "LoadingFragmentDialog"; + @BindView(R.id.loading_view) + AVLoadingIndicatorView loadingView; + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View view = View.inflate(getActivity(), R.layout.fragment_loading, null); + ButterKnife.bind(this,view); + startLoading(); + return view; + } + + public void startLoading(){ + loadingView.show(); + } + + @Override + public void onDetach() { + super.onDetach(); + if(loadingView.isShown()){ + loadingView.hide(); + } + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + if(loadingView.isShown()){ + loadingView.hide(); + } + } +} diff --git a/app/src/main/java/com/blink22/blink22_boilerplate/base/loading/LoadingFragmentDialog.java b/app/src/main/java/com/blink22/blink22_boilerplate/base/loading/LoadingFragmentDialog.java new file mode 100644 index 0000000..6a20cb9 --- /dev/null +++ b/app/src/main/java/com/blink22/blink22_boilerplate/base/loading/LoadingFragmentDialog.java @@ -0,0 +1,55 @@ +package com.blink22.blink22_boilerplate.base.loading; + +import android.app.Dialog; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.os.Bundle; +import android.support.v4.app.DialogFragment; +import android.view.View; +import android.view.ViewGroup; + +import com.blink22.blink22_boilerplate.R; +import com.wang.avi.AVLoadingIndicatorView; + +import butterknife.BindView; +import butterknife.ButterKnife; + +/** + * Created by m.hemdan on 8/30/17. + */ + +public class LoadingFragmentDialog extends DialogFragment { + public static String FRAGMENT_TAG = "LoadingFragmentDialog"; + @BindView(R.id.loading_view) + AVLoadingIndicatorView loadingView; + @Override + public void onResume() + { + super.onResume(); + getDialog().getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + setStyle(DialogFragment.STYLE_NO_FRAME, android.R.style.Theme); + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final Dialog dialog = super.onCreateDialog(savedInstanceState); + dialog.requestWindowFeature(DialogFragment.STYLE_NO_TITLE); + View view = View.inflate(getActivity(), R.layout.dialog_loading, null); + dialog.setContentView(view); + ButterKnife.bind(this,view); + startLoading(); + return dialog; + } + private void startLoading(){ + loadingView.show(); + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + if(loadingView.isShown()){ + loadingView.hide(); + } + } +} diff --git a/app/src/main/java/com/blink22/blink22_boilerplate/base/loading/TransparentLoadingFragment.java b/app/src/main/java/com/blink22/blink22_boilerplate/base/loading/TransparentLoadingFragment.java new file mode 100644 index 0000000..aecdd8f --- /dev/null +++ b/app/src/main/java/com/blink22/blink22_boilerplate/base/loading/TransparentLoadingFragment.java @@ -0,0 +1,62 @@ +package com.blink22.blink22_boilerplate.base.loading; + +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.view.InflateException; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.blink22.blink22_boilerplate.R; +import com.wang.avi.AVLoadingIndicatorView; + +import butterknife.BindView; +import butterknife.ButterKnife; + + + +/** + * Created by m.hemdan on 11/30/17. + */ + +public class TransparentLoadingFragment extends Fragment { + public static String FRAGMENT_TAG = "TransparentLoadingFragment"; + + @BindView(R.id.loading_view) + AVLoadingIndicatorView loadingView; + + private static View view; + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + + + if (view != null) { + ViewGroup parent = (ViewGroup) view.getParent(); + if (parent != null) + parent.removeView(view); + } + try { + view = inflater.inflate(R.layout.fragment_loading,container, false); + ButterKnife.bind(this, view); + startLoading(); + } catch (InflateException e) { + /* map is already there, just return view as it is */ + } + return view; + } + + + private void startLoading() { + loadingView.show(); + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + if(loadingView.isShown()){ + loadingView.hide(); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/blink22/blink22_boilerplate/main/MainActivity.java b/app/src/main/java/com/blink22/blink22_boilerplate/main/MainActivity.java new file mode 100644 index 0000000..f7c042d --- /dev/null +++ b/app/src/main/java/com/blink22/blink22_boilerplate/main/MainActivity.java @@ -0,0 +1,22 @@ +package com.blink22.blink22_boilerplate.main; + +import android.os.Bundle; +import android.support.annotation.Nullable; + +import com.blink22.blink22_boilerplate.AppInstance; +import com.blink22.blink22_boilerplate.ApplicationComponent; +import com.blink22.blink22_boilerplate.R; +import com.blink22.blink22_boilerplate.base.BaseActivity; + +public class MainActivity extends BaseActivity { + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + } + + @Override + protected void injectDependencies(AppInstance application, ApplicationComponent component) { + component.inject(this); + } +} diff --git a/app/src/main/java/com/blink22/blink22_boilerplate/util/AppSchedulerProvider.java b/app/src/main/java/com/blink22/blink22_boilerplate/util/AppSchedulerProvider.java new file mode 100644 index 0000000..f326ff6 --- /dev/null +++ b/app/src/main/java/com/blink22/blink22_boilerplate/util/AppSchedulerProvider.java @@ -0,0 +1,28 @@ +package com.blink22.blink22_boilerplate.util; + +import com.blink22.core.util.SchedulerProvider; + +import javax.inject.Inject; + +import io.reactivex.Scheduler; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.schedulers.Schedulers; + + +public class AppSchedulerProvider implements SchedulerProvider { + + @Inject + public AppSchedulerProvider() { + } + + @Override + public Scheduler mainThread() { + return AndroidSchedulers.mainThread(); + } + + @Override + public Scheduler backgroundThread() { + return Schedulers.io(); + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/blink22/blink22_boilerplate/util/StateManagerImpl.java b/app/src/main/java/com/blink22/blink22_boilerplate/util/StateManagerImpl.java new file mode 100755 index 0000000..aa05af5 --- /dev/null +++ b/app/src/main/java/com/blink22/blink22_boilerplate/util/StateManagerImpl.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2016 Karina Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and limitations under the License. + */ + +package com.blink22.blink22_boilerplate.util; + +import android.content.Context; + +import com.blink22.core.util.StateManager; +import com.mirhoseini.utils.Utils; + +import javax.inject.Inject; + + +/** + * Created by Mohsen on 06/11/2016. + */ + +public class StateManagerImpl implements StateManager { + + private Context context; + + @Inject + public StateManagerImpl(Context context) { + this.context = context; + } + + @Override + public boolean isConnect() { + return Utils.isConnected(context); + } +} diff --git a/app/src/main/java/com/blink22/blink22_boilerplate/util/database/DataBaseHelperImpl.java b/app/src/main/java/com/blink22/blink22_boilerplate/util/database/DataBaseHelperImpl.java new file mode 100644 index 0000000..1c4f236 --- /dev/null +++ b/app/src/main/java/com/blink22/blink22_boilerplate/util/database/DataBaseHelperImpl.java @@ -0,0 +1,17 @@ +package com.blink22.blink22_boilerplate.util.database; + +import com.blink22.core.util.DataBaseHelper; + +import javax.inject.Inject; + +/** + * Created by m.hemdan on 4/7/18. + */ + +public class DataBaseHelperImpl implements DataBaseHelper { + @Inject + DataBaseHelperImpl(){ + + } + +} diff --git a/app/src/main/java/com/blink22/blink22_boilerplate/util/database/DataBaseKeys.java b/app/src/main/java/com/blink22/blink22_boilerplate/util/database/DataBaseKeys.java new file mode 100644 index 0000000..1579159 --- /dev/null +++ b/app/src/main/java/com/blink22/blink22_boilerplate/util/database/DataBaseKeys.java @@ -0,0 +1,15 @@ +package com.blink22.blink22_boilerplate.util.database; + +/** + * Created by m.hemdan on 4/7/18. + */ + +public interface DataBaseKeys { + String BLOCK = "block"; + String USER = "user"; + String SOCIAL_OBJECT = "social_object"; + String USER_DEVICE_LOCATION = "USER_DEVICE_LOCATION"; + String APP_CATEGORIES_KEY = "APP_CATEGORIES_KEY"; + String NOTIFICATION_STATUS_KEY = "NOTIFICATION_STATUS_KEY"; + String PAYMENT_TOKEN_KEY = "PAYMENT_TOKEN_KEY"; +} diff --git a/app/src/main/java/com/blink22/blink22_boilerplate/util/database/DataBaseModule.java b/app/src/main/java/com/blink22/blink22_boilerplate/util/database/DataBaseModule.java new file mode 100644 index 0000000..8e1a4f3 --- /dev/null +++ b/app/src/main/java/com/blink22/blink22_boilerplate/util/database/DataBaseModule.java @@ -0,0 +1,17 @@ +package com.blink22.blink22_boilerplate.util.database; + +import com.blink22.core.util.DataBaseHelper; + +import javax.inject.Singleton; + +import dagger.Module; +import dagger.Provides; + +@Module +public class DataBaseModule { + @Provides + @Singleton + public DataBaseHelper provideDataBaseHelper(DataBaseHelperImpl dataBaseHelper){ + return dataBaseHelper; + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..c7bd21d --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..d5fccc5 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..84f1951 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,18 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_loading.xml b/app/src/main/res/layout/dialog_loading.xml new file mode 100644 index 0000000..9d7fccc --- /dev/null +++ b/app/src/main/res/layout/dialog_loading.xml @@ -0,0 +1,17 @@ + + + + + diff --git a/app/src/main/res/layout/fragment_loading.xml b/app/src/main/res/layout/fragment_loading.xml new file mode 100644 index 0000000..7ae2755 --- /dev/null +++ b/app/src/main/res/layout/fragment_loading.xml @@ -0,0 +1,16 @@ + + + + + diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..a2f5908 Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000..1b52399 Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..ff10afd Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000..115a4c7 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..dcd3cd8 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000..459ca60 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..8ca12fe Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..8e19b41 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..b824ebd Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..4c19a13 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..3ab3e9c --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,6 @@ + + + #3F51B5 + #303F9F + #FF4081 + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..fe427c8 --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + Blink22-Boilerplate + diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..5885930 --- /dev/null +++ b/app/src/main/res/values/styles.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/app/src/test/java/com/blink22/blink22_boilerplate/ExampleUnitTest.kt b/app/src/test/java/com/blink22/blink22_boilerplate/ExampleUnitTest.kt new file mode 100644 index 0000000..0dde9c4 --- /dev/null +++ b/app/src/test/java/com/blink22/blink22_boilerplate/ExampleUnitTest.kt @@ -0,0 +1,17 @@ +package com.blink22.blink22_boilerplate + +import org.junit.Test + +import org.junit.Assert.* + +/** + * Example local unit test, which will execute on the development machine (host). + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +class ExampleUnitTest { + @Test + fun addition_isCorrect() { + assertEquals(4, 2 + 2) + } +} diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..633a0d2 --- /dev/null +++ b/build.gradle @@ -0,0 +1,35 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + ext.kotlin_version = '1.2.50' + repositories { + google() + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:3.1.4' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + google() + jcenter() + mavenCentral() + maven { url "https://maven.google.com" } + maven { url "https://jitpack.io" } + maven { + url "https://plugins.gradle.org/m2/" + } + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} + +apply from: "./libraries.gradle" diff --git a/core/.gitignore b/core/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/core/.gitignore @@ -0,0 +1 @@ +/build diff --git a/core/build.gradle b/core/build.gradle new file mode 100644 index 0000000..b840b65 --- /dev/null +++ b/core/build.gradle @@ -0,0 +1,26 @@ +apply plugin: 'java-library' +configurations { + provided +} +sourceSets { + main { + compileClasspath += configurations.provided + } +} +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + api rootProject.ext.libraries.rxjava + + api rootProject.ext.libraries.dagger + provided rootProject.ext.aptLibraries.daggerCompiler + + + api rootProject.ext.libraries.retrofit + api rootProject.ext.libraries.retrofitConverter + api rootProject.ext.libraries.retrofitAdapter + api rootProject.ext.libraries.okhttp + api rootProject.ext.libraries.okhttpLogging +} + +sourceCompatibility = "1.8" +targetCompatibility = "1.8" diff --git a/core/src/main/java/com/blink22/core/base/BaseInteractor.java b/core/src/main/java/com/blink22/core/base/BaseInteractor.java new file mode 100644 index 0000000..1f83db8 --- /dev/null +++ b/core/src/main/java/com/blink22/core/base/BaseInteractor.java @@ -0,0 +1,5 @@ +package com.blink22.core.base; + +public interface BaseInteractor { + void unbind(); +} diff --git a/core/src/main/java/com/blink22/core/base/BasePresenter.java b/core/src/main/java/com/blink22/core/base/BasePresenter.java new file mode 100644 index 0000000..ca25501 --- /dev/null +++ b/core/src/main/java/com/blink22/core/base/BasePresenter.java @@ -0,0 +1,6 @@ +package com.blink22.core.base; + +public interface BasePresenter { + void bind(T view); + void unbind(); +} diff --git a/core/src/main/java/com/blink22/core/base/BaseView.java b/core/src/main/java/com/blink22/core/base/BaseView.java new file mode 100644 index 0000000..f898bd0 --- /dev/null +++ b/core/src/main/java/com/blink22/core/base/BaseView.java @@ -0,0 +1,10 @@ +package com.blink22.core.base; + +public interface BaseView { + void showError(Throwable throwable); + void showMessage(String message); + void showServerDownError(); + void showOfflineMessage(); + void showLoading(); + void hideLoading(); +} diff --git a/core/src/main/java/com/blink22/core/domain/ApiModule.java b/core/src/main/java/com/blink22/core/domain/ApiModule.java new file mode 100644 index 0000000..8f59ef7 --- /dev/null +++ b/core/src/main/java/com/blink22/core/domain/ApiModule.java @@ -0,0 +1,67 @@ +package com.blink22.core.domain; + +import com.blink22.core.domain.client.ExampleApi; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +import javax.inject.Singleton; + +import dagger.Module; +import dagger.Provides; +import okhttp3.HttpUrl; +import okhttp3.OkHttpClient; +import retrofit2.CallAdapter; +import retrofit2.Converter; +import retrofit2.Retrofit; +import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory; +import retrofit2.converter.gson.GsonConverterFactory; + +/** + * Created by m.hemdan on 4/5/18. + */ +@Module +public class ApiModule { + + +// example of adding new api to retrofit + + @Provides + @Singleton + public ExampleApi provideExampleApi(Retrofit retrofit){ + return retrofit.create(ExampleApi.class); + } + + @Provides + @Singleton + public Retrofit provideRetrofit(HttpUrl baseUrl, Converter.Factory converterFactory, + CallAdapter.Factory callAdapterFactory, OkHttpClient okHttpClient) { + return new Retrofit.Builder() + .baseUrl(baseUrl) + .addConverterFactory(converterFactory) + .addCallAdapterFactory(callAdapterFactory) + .client(okHttpClient) + .build(); + } + + @Provides + @Singleton + public Converter.Factory provideGsonConverterFactory(Gson gson) { + return GsonConverterFactory.create(gson); + } + + @Singleton + @Provides + public Gson provideGson() { + Gson gson = new GsonBuilder().disableHtmlEscaping().create(); + return gson; + } + + @Provides + @Singleton + public CallAdapter.Factory provideRxJavaCallAdapterFactory() { + return RxJavaCallAdapterFactory.create(); + } + + + +} diff --git a/core/src/main/java/com/blink22/core/domain/ClientModule.java b/core/src/main/java/com/blink22/core/domain/ClientModule.java new file mode 100755 index 0000000..07473aa --- /dev/null +++ b/core/src/main/java/com/blink22/core/domain/ClientModule.java @@ -0,0 +1,182 @@ +package com.blink22.core.domain; + + +import com.blink22.core.util.LanguageProvider; +import com.blink22.core.util.StateManager; + +import java.io.File; +import java.io.IOException; +import java.util.concurrent.TimeUnit; + +import javax.inject.Named; +import javax.inject.Singleton; + +import dagger.Module; +import dagger.Provides; +import okhttp3.Cache; +import okhttp3.CacheControl; +import okhttp3.Interceptor; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.logging.HttpLoggingInterceptor; + +/** + * Created by Mohsen on 20/10/2016. + */ + +@Module +public class ClientModule { + + private static final String HTTP_CACHE_PATH = "http-cache"; + private static final String CACHE_CONTROL = "Cache-Control"; + private static final String PRAGMA = "Pragma"; + + @Singleton + @Provides + public OkHttpClient provideOkHttpClient(HttpLoggingInterceptor loggingInterceptor, + @Named("networkTimeoutInSeconds") int networkTimeoutInSeconds, + @Named("isDebug") boolean isDebug, + @Named("cache") Cache cache, + @Named("cacheInterceptor") Interceptor cacheInterceptor, + @Named("offlineInterceptor") Interceptor offlineCacheInterceptor, + @Named("retryInterceptor") Interceptor retryInterceptor, + @Named("HeaderInterceptor") Interceptor headers) { + + OkHttpClient.Builder okHttpClient = new OkHttpClient.Builder() + .addNetworkInterceptor(cacheInterceptor) + .addInterceptor(offlineCacheInterceptor) + .addInterceptor(retryInterceptor) + .addInterceptor(headers) + .cache(cache) + .connectTimeout(networkTimeoutInSeconds, TimeUnit.SECONDS); + + //show logs if app is in Debug mode + if (isDebug) + okHttpClient.addInterceptor(loggingInterceptor); + + return okHttpClient.build(); + } + + @Singleton + @Provides + public HttpLoggingInterceptor provideHttpLoggingInterceptor() { + HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); + logging.setLevel(HttpLoggingInterceptor.Level.BODY); + return logging; + } + + @Provides + @Singleton + @Named("cache") + public Cache provideCache(@Named("cacheDir") File cacheDir, @Named("cacheSize") long cacheSize) { + Cache cache = null; + + try { + cache = new Cache(new File(cacheDir.getPath(), HTTP_CACHE_PATH), cacheSize); + } catch (Exception e) { + e.printStackTrace(); + } + return cache; + } + + @Singleton + @Provides + @Named("cacheInterceptor") + public Interceptor provideCacheInterceptor(@Named("cacheMaxAge") int maxAgeMin, @Named("cache") Cache cache) { + return chain -> { + Response response = chain.proceed(chain.request()); + + CacheControl cacheControl = new CacheControl.Builder() + .maxAge(maxAgeMin, TimeUnit.MINUTES) + .build(); + if(URLS.NO_CACHE_URLS.contains(chain.request().url().encodedPath())){ + cache.evictAll(); + } + + return response.newBuilder() + .removeHeader(PRAGMA) + .removeHeader(CACHE_CONTROL) + .header(CACHE_CONTROL, cacheControl.toString()) + .build(); + }; + } + + + @Singleton + @Provides + @Named("offlineInterceptor") + public Interceptor provideOfflineCacheInterceptor(StateManager stateManager, @Named("cacheMaxStale") int maxStaleDay) { + return chain -> { + Request request = chain.request(); + + if (!stateManager.isConnect()) { + CacheControl cacheControl = new CacheControl.Builder() + .maxStale(maxStaleDay, TimeUnit.DAYS) + .build(); + + request = request.newBuilder() + .cacheControl(cacheControl) + .build(); + }else{ + request = request.newBuilder() + .cacheControl(CacheControl.FORCE_NETWORK) + .build(); + } + + return chain.proceed(request); + }; + } + + @Singleton + @Provides + @Named("retryInterceptor") + public Interceptor provideRetryInterceptor(@Named("retryCount") int retryCount) { + return chain -> { + Request request = chain.request(); + Response response = null; + IOException exception = null; + + int tryCount = 0; + while (tryCount < retryCount && (null == response || !response.isSuccessful() )) { + // retry the request + try { + response = chain.proceed(request); + } catch (IOException e) { + exception = e; + }finally { + tryCount++; + } + } + + // throw last exception + if (null == response && null != exception) { + throw exception; + } + + + + // otherwise just pass the original response on + return response; + }; + } + + @Singleton + @Provides + @Named("HeaderInterceptor") + public Interceptor provideHeaders(@Named("appLanguage") LanguageProvider language) { + return chain -> { + Request original = chain.request(); + + Request request = original.newBuilder() + .header("X-Api-Key", URLS.API_KEY) + .header("Accept-Language",language.getCurrentLanguage()) +// .header("X-Accept-Version","1.1.0") + .method(original.method(), original.body()) + .build(); + return chain.proceed(request); + }; + } + + +} diff --git a/core/src/main/java/com/blink22/core/domain/URLS.java b/core/src/main/java/com/blink22/core/domain/URLS.java new file mode 100644 index 0000000..ddfa142 --- /dev/null +++ b/core/src/main/java/com/blink22/core/domain/URLS.java @@ -0,0 +1,16 @@ +package com.blink22.core.domain; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public interface URLS { + String API_KEY = ""; + String BASE_URL = ""; + + String REGISTER = "register"; + + List NO_CACHE_URLS = new ArrayList<>(); //= new ArrayList<>(Arrays.asList(REGISTER,LOGIN)); + + +} diff --git a/core/src/main/java/com/blink22/core/domain/client/ExampleApi.java b/core/src/main/java/com/blink22/core/domain/client/ExampleApi.java new file mode 100644 index 0000000..3c2b5df --- /dev/null +++ b/core/src/main/java/com/blink22/core/domain/client/ExampleApi.java @@ -0,0 +1,32 @@ +package com.blink22.core.domain.client; + +import com.blink22.core.domain.URLS; +import com.blink22.core.domain.model.BaseResponse; + +import io.reactivex.Single; +import retrofit2.http.Field; +import retrofit2.http.FormUrlEncoded; +import retrofit2.http.GET; +import retrofit2.http.POST; + +public interface ExampleApi { +// this is example api for retrofit interface + //Put KEYS HERE for the REQUEST +// String EMAIL = "email"; +// String PROFILE_IMAGE = "profileImage"; +// String PHONE = "phone"; +// String FIRST_NAME = "firstName"; +// String FACEBOOK_ID = "facebook"; +// +// // email=dsadas@gmail.com&phone=2001011164679&profileImage=dsadsadas&firstName=m.hemdan&facebook=31232asd +// @FormUrlEncoded +// @POST(URLS.REGISTER) +// Single execute( +// @Field(EMAIL)String email, +// @Field(PHONE) String phone, +// @Field(PROFILE_IMAGE)String profileImage, +// @Field(FIRST_NAME) String firstName, +// @Field(FACEBOOK_ID) String facebookId); + @GET + Single executeGetData(); +} diff --git a/core/src/main/java/com/blink22/core/domain/exceptions/ApiResponseCodeException.java b/core/src/main/java/com/blink22/core/domain/exceptions/ApiResponseCodeException.java new file mode 100644 index 0000000..915db84 --- /dev/null +++ b/core/src/main/java/com/blink22/core/domain/exceptions/ApiResponseCodeException.java @@ -0,0 +1,19 @@ +package com.blink22.core.domain.exceptions; + +public class ApiResponseCodeException extends Exception { + private int code; + private String status; + + public ApiResponseCodeException(int code, String status) { + this.code = code; + this.status = status; + } + + public int getCode() { + return code; + } + + public String getStatus() { + return status; + } +} diff --git a/core/src/main/java/com/blink22/core/domain/mapper/Mapper.java b/core/src/main/java/com/blink22/core/domain/mapper/Mapper.java new file mode 100644 index 0000000..2bbe08f --- /dev/null +++ b/core/src/main/java/com/blink22/core/domain/mapper/Mapper.java @@ -0,0 +1,15 @@ +package com.blink22.core.domain.mapper; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; + +public class Mapper { + //this class will be in use to parse base response data to the destination model + + //Example +// public static UserModel mapAuthResponseToUserModel(BaseResponse baseResponse){ +// return new Gson().fromJson(((JsonObject) baseResponse.getData()) +// .get("user"), UserModel.class); +// } + +} diff --git a/core/src/main/java/com/blink22/core/domain/model/BaseResponse.java b/core/src/main/java/com/blink22/core/domain/model/BaseResponse.java new file mode 100644 index 0000000..3140e59 --- /dev/null +++ b/core/src/main/java/com/blink22/core/domain/model/BaseResponse.java @@ -0,0 +1,86 @@ +package com.blink22.core.domain.model; + +import com.blink22.core.util.Constants; +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; +import com.google.gson.reflect.TypeToken; + +import java.lang.reflect.Type; +import java.util.List; + +/** + * Created by m.hemdan on 8/22/17. + */ + +public class BaseResponse { + @SerializedName("code") + @Expose + private Integer code; + @SerializedName("message") + @Expose + private String message; + @SerializedName("status") + @Expose + private String status; + @SerializedName("data") + @Expose + private JsonElement data; + + public Integer getCode() { + return code; + } + + public void setCode(Integer code) { + this.code = code; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public Object getData(String className) { + + try { + if(data.isJsonArray()){ + Type listType = new TypeToken>(){}.getType(); + return new Gson().fromJson(data, listType); + }else if(data.isJsonObject()) { + return new Gson().fromJson(data, Class.forName(className)); + } + } catch (ClassNotFoundException e) { + e.printStackTrace(); + return null; + } + + return null; + } + + public JsonElement getData() { + return data; + } + + public void setData(JsonElement data) { + this.data = data; + } + + public boolean isSuccess(){ + return !status.equals(Constants.FAILURE_STATUS); + } + + + +} diff --git a/core/src/main/java/com/blink22/core/modules/example/Example.java b/core/src/main/java/com/blink22/core/modules/example/Example.java new file mode 100644 index 0000000..a3f23be --- /dev/null +++ b/core/src/main/java/com/blink22/core/modules/example/Example.java @@ -0,0 +1,11 @@ +package com.blink22.core.modules.example; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import javax.inject.Scope; + +@Scope +@Retention(RetentionPolicy.RUNTIME) +public @interface Example { +} diff --git a/core/src/main/java/com/blink22/core/modules/example/ExampleContract.java b/core/src/main/java/com/blink22/core/modules/example/ExampleContract.java new file mode 100644 index 0000000..1c5f894 --- /dev/null +++ b/core/src/main/java/com/blink22/core/modules/example/ExampleContract.java @@ -0,0 +1,25 @@ +package com.blink22.core.modules.example; + +import com.blink22.core.base.BaseInteractor; +import com.blink22.core.base.BasePresenter; +import com.blink22.core.base.BaseView; +import com.blink22.core.domain.model.BaseResponse; + +import io.reactivex.Single; + +public interface ExampleContract { + interface View extends BaseView{ + +// void setExample(ExampleModel example); + void setExample(BaseResponse example); + } + + interface Presenter extends BasePresenter { + void getData(boolean isConnected); + } + + interface Interactor extends BaseInteractor{ + Single getData(); + } + +} diff --git a/core/src/main/java/com/blink22/core/modules/example/ExampleInteractorImpl.java b/core/src/main/java/com/blink22/core/modules/example/ExampleInteractorImpl.java new file mode 100644 index 0000000..477d9f5 --- /dev/null +++ b/core/src/main/java/com/blink22/core/modules/example/ExampleInteractorImpl.java @@ -0,0 +1,45 @@ +package com.blink22.core.modules.example; + +import com.blink22.core.domain.client.ExampleApi; +import com.blink22.core.domain.model.BaseResponse; +import com.blink22.core.util.SchedulerProvider; + +import javax.inject.Inject; + +import io.reactivex.Single; +import io.reactivex.disposables.Disposable; +import io.reactivex.subjects.SingleSubject; + +public class ExampleInteractorImpl implements ExampleContract.Interactor { + + private ExampleApi api; + private SchedulerProvider scheduler; + + private SingleSubject exampleSubject; + private Disposable exampleSubscription; + + @Inject + ExampleInteractorImpl(ExampleApi api, SchedulerProvider scheduler) { + this.api = api; + this.scheduler = scheduler; + } + + @Override + public Single getData() { + if (exampleSubscription == null || exampleSubscription.isDisposed()) { + exampleSubject = SingleSubject.create(); + + exampleSubscription = api.executeGetData() + .subscribeOn(scheduler.backgroundThread()) + .subscribe(exampleSubject::onSuccess); + } + + return exampleSubject.hide(); + } + + @Override + public void unbind() { + if (exampleSubscription != null && !exampleSubscription.isDisposed()) + exampleSubscription.dispose(); + } +} diff --git a/core/src/main/java/com/blink22/core/modules/example/ExampleModule.java b/core/src/main/java/com/blink22/core/modules/example/ExampleModule.java new file mode 100644 index 0000000..2c3490a --- /dev/null +++ b/core/src/main/java/com/blink22/core/modules/example/ExampleModule.java @@ -0,0 +1,20 @@ +package com.blink22.core.modules.example; + +import dagger.Module; +import dagger.Provides; + +@Module +public class ExampleModule { + + @Example + @Provides + public ExampleContract.Presenter providePresenter(ExamplePresenterImpl presenter){ + return presenter; + } + + @Example + @Provides + public ExampleContract.Interactor provideInteractor(ExampleInteractorImpl interactor){ + return interactor; + } +} diff --git a/core/src/main/java/com/blink22/core/modules/example/ExamplePresenterImpl.java b/core/src/main/java/com/blink22/core/modules/example/ExamplePresenterImpl.java new file mode 100644 index 0000000..e6e383e --- /dev/null +++ b/core/src/main/java/com/blink22/core/modules/example/ExamplePresenterImpl.java @@ -0,0 +1,110 @@ +package com.blink22.core.modules.example; + +import com.blink22.core.domain.exceptions.ApiResponseCodeException; +import com.blink22.core.domain.mapper.Mapper; +import com.blink22.core.util.Constants; +import com.blink22.core.util.DataBaseHelper; +import com.blink22.core.util.SchedulerProvider; + +import javax.inject.Inject; + +import io.reactivex.disposables.Disposable; +import io.reactivex.exceptions.Exceptions; + + +public class ExamplePresenterImpl implements ExampleContract.Presenter { + + + @Inject + ExampleContract.Interactor interactor; + + @Inject + DataBaseHelper databaseHelper; + + private ExampleContract.View view; + private Disposable disposable; + private SchedulerProvider scheduler; + + + @Inject + public ExamplePresenterImpl(SchedulerProvider scheduler) { + this.scheduler = scheduler; + } + + @Override + public void bind(ExampleContract.View view) { + this.view = view; + } + + @Override + public void unbind() { + if (disposable != null && !disposable.isDisposed()) + disposable.dispose(); + + interactor.unbind(); + + view = null; + } + + @Override + public void getData(boolean isConnected) { + if (null != view) { + view.showLoading(); + } + + disposable = interactor.getData() + // check if result code is OK + .map(baseResponse -> { + if (Constants.CODE_OK == baseResponse.getCode()) + return baseResponse; + else + throw Exceptions.propagate(new ApiResponseCodeException(baseResponse.getCode(), baseResponse.getStatus())); + }) + // check if is there any result + .map(baseResponse -> { +// if (baseResponse.getData() > 0) +// return baseResponse; +// else +// throw Exceptions.propagate(new NoSuchCharacterException()); + return baseResponse; + }) + // map BaseResponse to corresponding Model +// .map(Mapper::mapBaseResponseResponseToExample) + // cache data on database + .map(exampleModel -> { +// try { +// databaseHelper.addExample(example); +// } catch (SQLException e) { +// throw Exceptions.propagate(e); +// } + + return exampleModel; + }) + .observeOn(scheduler.mainThread()) + .subscribe(exampleModel -> { + if (null != view) { + view.hideLoading(); + view.setExample(exampleModel); + + if (!isConnected) + view.showOfflineMessage(); + } + }, + // handle exceptions + throwable -> { + if (null != view) { + view.hideLoading(); + + if (isConnected) { + if (throwable instanceof ApiResponseCodeException) + view.showError((ApiResponseCodeException) throwable); + else + view.showServerDownError(); + + } else { + view.showOfflineMessage(); + } + } + }); + } +} diff --git a/core/src/main/java/com/blink22/core/util/Constants.java b/core/src/main/java/com/blink22/core/util/Constants.java new file mode 100644 index 0000000..42bf8bf --- /dev/null +++ b/core/src/main/java/com/blink22/core/util/Constants.java @@ -0,0 +1,14 @@ +package com.blink22.core.util; + +public interface Constants { + String FAILURE_STATUS = "failure"; + int CODE_OK = 200; + + + int NETWORK_CONNECTION_TIMEOUT = 30; // 30 sec + long CACHE_SIZE = 10 * 1024 * 1024; // 10 MB + int CACHE_MAX_AGE = 2; // 2 min + int CACHE_MAX_STALE = 7; // 7 day + int API_RETRY_COUNT = 3; + +} diff --git a/core/src/main/java/com/blink22/core/util/DataBaseHelper.java b/core/src/main/java/com/blink22/core/util/DataBaseHelper.java new file mode 100644 index 0000000..1f1d628 --- /dev/null +++ b/core/src/main/java/com/blink22/core/util/DataBaseHelper.java @@ -0,0 +1,24 @@ +package com.blink22.core.util; + + +/** + * Created by m.hemdan on 4/5/18. + */ + +public interface DataBaseHelper { +// void setSocialObject(Object socialObject); +// Object getSocialObject(); +// void setCurrentUser(UserModel user); +// UserModel getCurrentUser(); +// void setCurrentUserDeviceLocation(Object location); +// Object getCurrentUserDeviceLocation(); +// void block(); +// boolean isBlocked(); +// void destroy(); +// void setAppCategories(ArrayList categoryModels); +// void setPaymentToken(String paymentToken); +// String getPaymentToken(); +// ArrayList getAppCategories(); +// void updateNotificationStatus(boolean isEnabled); +// boolean isNotificationEnabled(); +} diff --git a/core/src/main/java/com/blink22/core/util/LanguageProvider.java b/core/src/main/java/com/blink22/core/util/LanguageProvider.java new file mode 100644 index 0000000..34e2611 --- /dev/null +++ b/core/src/main/java/com/blink22/core/util/LanguageProvider.java @@ -0,0 +1,17 @@ +package com.blink22.core.util; + +/** + * Created by m.hemdan on 11/17/17. + */ + +public class LanguageProvider { + private static String currentLanguage = "en"; + + public String getCurrentLanguage() { + return currentLanguage; + } + + public static void setCurrentLanguage(String newLanguage) { + currentLanguage = newLanguage; + } +} diff --git a/core/src/main/java/com/blink22/core/util/SchedulerProvider.java b/core/src/main/java/com/blink22/core/util/SchedulerProvider.java new file mode 100644 index 0000000..52ae8b6 --- /dev/null +++ b/core/src/main/java/com/blink22/core/util/SchedulerProvider.java @@ -0,0 +1,16 @@ +package com.blink22.core.util; + + +import io.reactivex.Scheduler; + +/** + * Created by m.hemdan on 8/15/17. + */ + +public interface SchedulerProvider { + + Scheduler mainThread(); + + Scheduler backgroundThread(); + +} \ No newline at end of file diff --git a/core/src/main/java/com/blink22/core/util/StateManager.java b/core/src/main/java/com/blink22/core/util/StateManager.java new file mode 100755 index 0000000..926cfbc --- /dev/null +++ b/core/src/main/java/com/blink22/core/util/StateManager.java @@ -0,0 +1,11 @@ +package com.blink22.core.util; + +/** + * Created by Mohsen on 06/11/2016. + */ + +public interface StateManager { + + boolean isConnect(); + +} diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..743d692 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,13 @@ +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx1536m +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..7a3265e Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..6cd044b --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Tue Sep 25 10:19:08 EET 2018 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip diff --git a/gradlew b/gradlew new file mode 100755 index 0000000..cccdd3d --- /dev/null +++ b/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..e95643d --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/libraries.gradle b/libraries.gradle new file mode 100644 index 0000000..fac0e21 --- /dev/null +++ b/libraries.gradle @@ -0,0 +1,96 @@ +ext{ + //Versions Section + //Java + rxjavaVersion = "2.2.2" + //dagger + daggerVersion = "2.17" + + rxandroidVersion = "2.1.0" + + okhttpVersion = "3.4.1" + retrofitVersion = "2.1.0" + + //Testing + junitVersion = '4.12' + mockitoVersion = '1.10.19' + powerMockito = '1.6.2' + hamcrestVersion = '1.3' + runnerVersion = '1.0.2' + rulesVersion = '1.0.2' + espressoVersion = '3.0.2' + +// Android Lib + androidSupportVersion = "28.0.0" + butterknifeVersion = "8.8.1" + scalableDPVersion = "1.0.5" + utilsVersion = "1.0.7" + progressLibVersion = "2.1.3" + toastLibVersion = "2.0.4" + imageChooserVersion = "1.2.5" + glideVersion = "4.8.0" + rxPermissionVersion = "0.10.2" + webViewVersion = "1.2.7" + + + // Dependencies Section + + libraries = [ + + dagger : "com.google.dagger:dagger:${daggerVersion}", + rxjava : "io.reactivex.rxjava2:rxjava:${rxjavaVersion}", + rxandroid : "io.reactivex.rxjava2:rxandroid:${rxandroidVersion}", + okhttp : "com.squareup.okhttp3:okhttp:${okhttpVersion}", + okhttpLogging : "com.squareup.okhttp3:logging-interceptor:${okhttpVersion}", + retrofit : "com.squareup.retrofit2:retrofit:${retrofitVersion}", + retrofitConverter : "com.squareup.retrofit2:converter-gson:${retrofitVersion}", + retrofitAdapter : "com.squareup.retrofit2:adapter-rxjava:${retrofitVersion}", + ] + + + //android related libraries + appLibraries = [ + + appCompatSupport : "com.android.support:appcompat-v7:${androidSupportVersion}", + designSupport : "com.android.support:design:${androidSupportVersion}", + cardView : "com.android.support:cardview-v7:${androidSupportVersion}", + recyclerView : "com.android.support:recyclerview-v7:${androidSupportVersion}", + scalableDP : "com.intuit.sdp:sdp-android:${scalableDPVersion}", + butterknife : "com.jakewharton:butterknife:${butterknifeVersion}", + progressLib : "com.wang.avi:library:${progressLibVersion}", + toastLib : "com.tapadoo.android:alerter:${toastLibVersion}", + utils : "com.mirhoseini.utils:utils:${utilsVersion}", + imageChooser : "com.fxn769:pix:${imageChooserVersion}", + glide : "com.github.bumptech.glide:glide:${glideVersion}", + rxPermission : "com.github.tbruyelle:rxpermissions:${rxPermissionVersion}", + webView : "com.thefinestartist:finestwebview:${webViewVersion}", + + + ] + + testingLibraries = [ + + // Dependencies for local unit tests + junit : "junit:junit:$junitVersion", + mockito : "org.mockito:mockito-all:$mockitoVersion", + hamcrest : "org.hamcrest:hamcrest-all:$hamcrestVersion", + powerMockitoModule : "org.powermock:powermock-module-junit4:$powerMockito", + powerMockitoApi : "org.powermock:powermock-api-mockito:$powerMockito", + + // Android Testing Support Library's runner and rules + testSupportRunner : "com.android.support.test:runner:$runnerVersion", + testSupportRules : "com.android.support.test:rules:$rulesVersion", + + // Espresso UI Testing dependencies. + espressoCore : "com.android.support.test.espresso:espresso-core:$espressoVersion", + espressoContrib : "com.android.support.test.espresso:espresso-contrib:$espressoVersion", + espressoIdlingResource : "com.android.support.test.espresso:espresso-idling-resource:$espressoVersion" + + ] + + + aptLibraries = [ + butterknifeCompiler : "com.jakewharton:butterknife-compiler:${butterknifeVersion}", + daggerCompiler : "com.google.dagger:dagger-compiler:${daggerVersion}", + glideCompiler : "com.github.bumptech.glide:compiler:${glideVersion}", + ] +} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..bdf2d88 --- /dev/null +++ b/settings.gradle @@ -0,0 +1 @@ +include ':app', ':core'