diff --git a/.gitignore b/.gitignore index 6994a8f..258b027 100644 --- a/.gitignore +++ b/.gitignore @@ -74,6 +74,7 @@ obj/ .idea/copyright/profiles_settings.xml .idea/encodings.xml .idea/misc.xml +.idea/gradle.xml .idea/modules.xml .idea/scopes/scope_settings.xml .idea/dictionaries @@ -132,4 +133,5 @@ fabric.properties !/gradle/wrapper/gradle-wrapper.jar -# End of https://www.gitignore.io/api/androidstudio \ No newline at end of file +# End of https://www.gitignore.io/api/androidstudio +src/main/java/com/egdroid/movieapp/di/ diff --git a/.idea/misc.xml b/.idea/misc.xml index af0bbdd..703e5d4 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -5,7 +5,7 @@ - + diff --git a/app/build.gradle b/app/build.gradle index 6521609..77a46ad 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,96 +1,36 @@ apply plugin: 'com.android.application' apply from: "$project.rootDir/tools/gradle/script/quality.gradle" +apply from: "$project.rootDir/tools/gradle/base.gradle" android { - compileSdkVersion deps.build.compileSdkVersion defaultConfig { applicationId "com.egdroid.movieapp" - minSdkVersion deps.build.minSdkVersion - targetSdkVersion deps.build.targetSdkVersion - versionCode deps.build.versionCode - versionName deps.build.versionName - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + externalNativeBuild { + ndkBuild { + path 'src/main/jni/Android.mk' + } } buildTypes { release { - minifyEnabled false + minifyEnabled true + shrinkResources true proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } debug { - minifyEnabled false + minifyEnabled true + shrinkResources true proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } } -dependencies { - //UI - implementation deps.support.design - implementation deps.support.recyclerview - implementation deps.support.constraintLayout - - // Arch Component - implementation deps.architecturecomponents.lifecycles - implementation deps.architecturecomponents.room - annotationProcessor deps.architecturecomponents.room_compiler - - // Rx - implementation deps.rx.java - implementation deps.rx.relay - implementation deps.rx.android - implementation deps.rx.binding - implementation deps.rx.retrofitAdapter - - // Dependency Injection - implementation deps.dependencyInjection.dagger - implementation deps.dependencyInjection.daggerSupportAndroid - annotationProcessor deps.dependencyInjection.daggerCompiler - annotationProcessor deps.dependencyInjection.daggerAndroidCompiler - - // View Binding - implementation deps.viewBinding.butterknife - annotationProcessor deps.viewBinding.butterknifeCompiler - - // Images - implementation deps.image.glide - annotationProcessor deps.image.glideCompiler - - // Network - implementation deps.network.retrofit - implementation deps.network.retrofitGsonConverter +configurations { + compile.exclude group: 'androidx.annotation', module: 'annotation' +} - // Log - implementation deps.log.timber - debugImplementation deps.log.leakCanaryDebug - releaseImplementation deps.log.leakCanaryRelease +dependencies{ - // Testing - testImplementation deps.test.junit - androidTestImplementation deps.test.runner - androidTestImplementation deps.test.robolectric - androidTestImplementation deps.test.espresso - androidTestImplementation deps.test.mockito - androidTestImplementation deps.test.powermock_mockito - androidTestImplementation deps.test.powermock_easymock - androidTestImplementation deps.test.powermock_reflect - androidTestImplementation deps.test.powermock_junit4 - androidTestImplementation deps.test.powermock_junit4_rule - androidTestImplementation deps.test.powermock_classloading + implementation project(":presentation:popularmoviespresentation") - implementation fileTree(dir: 'libs', include: ['*.jar']) - configurations.all { - resolutionStrategy { - force deps.support.annotations - } - resolutionStrategy.eachDependency { details -> - if (details.requested.group == 'com.android.support' - && !details.requested.name.contains('multidex')) { - details.useVersion deps.versions.support - } - } - } -} +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c533410..285e4a2 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,10 +2,13 @@ + + diff --git a/app/src/main/java/com/egdroid/movieapp/EgdoidApp.kt b/app/src/main/java/com/egdroid/movieapp/EgdoidApp.kt new file mode 100644 index 0000000..87107b1 --- /dev/null +++ b/app/src/main/java/com/egdroid/movieapp/EgdoidApp.kt @@ -0,0 +1,15 @@ +package com.egdroid.movieapp + +import android.app.Application +import timber.log.Timber + +class EgdoidApp : Application() { + + override fun onCreate() { + super.onCreate() + + if (BuildConfig.DEBUG) { + Timber.plant(Timber.DebugTree()) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/egdroid/movieapp/MainActivity.java b/app/src/main/java/com/egdroid/movieapp/MainActivity.java deleted file mode 100644 index c6c4f6c..0000000 --- a/app/src/main/java/com/egdroid/movieapp/MainActivity.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.egdroid.movieapp; - -import androidx.appcompat.app.AppCompatActivity; - -import android.os.Bundle; - -public class MainActivity extends AppCompatActivity { - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); - } -} diff --git a/app/src/main/java/com/egdroid/movieapp/MainActivity.kt b/app/src/main/java/com/egdroid/movieapp/MainActivity.kt new file mode 100644 index 0000000..5f66df3 --- /dev/null +++ b/app/src/main/java/com/egdroid/movieapp/MainActivity.kt @@ -0,0 +1,23 @@ +package com.egdroid.movieapp + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.egdroid.presentation.popularmoviespresentation.PopularMoviesFragment + + +class MainActivity : AppCompatActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + +// val key1 = String(Base64.decode(getNativeKey1(), Base64.DEFAULT)) +// Timber.w(key1) + + + val manager = supportFragmentManager + val transaction = manager.beginTransaction() + transaction.replace(R.id.container, PopularMoviesFragment()) + transaction.commit() + } +} diff --git a/app/src/main/java/com/egdroid/movieapp/popularmovies/PopularMovieAdapter.kt b/app/src/main/java/com/egdroid/movieapp/popularmovies/PopularMovieAdapter.kt new file mode 100644 index 0000000..6ee35e0 --- /dev/null +++ b/app/src/main/java/com/egdroid/movieapp/popularmovies/PopularMovieAdapter.kt @@ -0,0 +1,42 @@ +package com.egdroid.presentation.popularmoviespresentation + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import com.bumptech.glide.Glide +import com.egdroid.models.popularmovies.MovieUi +import com.egdroid.movieapp.R +import kotlinx.android.synthetic.main.popular_movie_row.view.* + +class PopularMovieAdapter : RecyclerView.Adapter() { + + private val moviesList: MutableList = arrayListOf() + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MovieViewHolder { + val inflater = LayoutInflater.from(parent.context) + return MovieViewHolder(inflater, parent) + } + + override fun onBindViewHolder(holder: MovieViewHolder, position: Int) { + val movie: MovieUi = moviesList[position] + holder.bind(movie) + } + + override fun getItemCount(): Int = moviesList.size + + fun addPopularMovies(movies: List) { + moviesList.addAll(movies) + notifyDataSetChanged() + } + + class MovieViewHolder(inflater: LayoutInflater, parent: ViewGroup) : + RecyclerView.ViewHolder(inflater.inflate(R.layout.popular_movie_row, parent, false)) { + + fun bind(movie: MovieUi) { + Glide.with(itemView).load("https://image.tmdb.org/t/p/w600_and_h900_bestv2/" + movie.posterPath).into(itemView.movieImageView) + itemView.titleTextView.text = movie.title + itemView.overviewTextView.text = movie.overview + } + + } +} diff --git a/app/src/main/java/com/egdroid/movieapp/popularmovies/PopularMoviesFragment.kt b/app/src/main/java/com/egdroid/movieapp/popularmovies/PopularMoviesFragment.kt new file mode 100644 index 0000000..6b83607 --- /dev/null +++ b/app/src/main/java/com/egdroid/movieapp/popularmovies/PopularMoviesFragment.kt @@ -0,0 +1,42 @@ +package com.egdroid.presentation.popularmoviespresentation + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import androidx.lifecycle.Observer +import androidx.recyclerview.widget.LinearLayoutManager +import com.egdroid.movieapp.R +import com.egdroid.presentation.popularmoviespresentation.PopularMoviePresentationFactory.providePopularMoviesViewModel +import kotlinx.android.synthetic.main.fragment_popular_movies.view.* + +/** + * A simple [Fragment] subclass. + */ +class PopularMoviesFragment : Fragment() { + + private lateinit var popularMovieAdapter: PopularMovieAdapter + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle?): View? { + val view = inflater.inflate(R.layout.fragment_popular_movies, container, false) + + val popularMoviesViewModel = providePopularMoviesViewModel(activity!!) + + setupRecyclerView(view) + + popularMoviesViewModel.getMovies().observe(this, Observer { + if (it != null) { + popularMovieAdapter.addPopularMovies(it) + } + }) + return view + } + + private fun setupRecyclerView(view: View) { + popularMovieAdapter = PopularMovieAdapter() + view.popularMoviesRecyclerView.setLayoutManager(LinearLayoutManager(activity)) + view.popularMoviesRecyclerView.adapter = popularMovieAdapter + } +} \ No newline at end of file diff --git a/app/src/main/jni/Android.mk b/app/src/main/jni/Android.mk new file mode 100644 index 0000000..f42f188 --- /dev/null +++ b/app/src/main/jni/Android.mk @@ -0,0 +1,8 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := keys +LOCAL_SRC_FILES := keys.c + +include $(BUILD_SHARED_LIBRARY) \ No newline at end of file diff --git a/app/src/main/jni/Application.mk b/app/src/main/jni/Application.mk new file mode 100644 index 0000000..a252a72 --- /dev/null +++ b/app/src/main/jni/Application.mk @@ -0,0 +1 @@ +APP_ABI := all diff --git a/app/src/main/jni/keys.c b/app/src/main/jni/keys.c new file mode 100644 index 0000000..c9a9d40 --- /dev/null +++ b/app/src/main/jni/keys.c @@ -0,0 +1,14 @@ +#include + +//JNIEXPORT jstring JNICALL +//Java_com_egdroid_movieapp_MainActivity_getNativeKey1(JNIEnv *env, jobject instance) { +// +// return (*env)-> NewStringUTF(env, "ODI4MTU3MDk1YTU0ZWQ4ZjY4Yjg4ODI2MjRlZDc2NjA="); +//} + +JNIEXPORT jstring JNICALL +Java_com_egdroid_datasource_remote_movie_MoviesServiceFactory_getNativeKey(JNIEnv *env, + jobject instance) { + + return (*env)->NewStringUTF(env, "ODI4MTU3MDk1YTU0ZWQ4ZjY4Yjg4ODI2MjRlZDc2NjA="); +} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 4fc2444..06dbc4c 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -6,13 +6,15 @@ android:layout_height="match_parent" tools:context=".MainActivity"> - + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent"> + + \ No newline at end of file diff --git a/app/src/main/res/layout/emptyview.xml b/app/src/main/res/layout/emptyview.xml new file mode 100644 index 0000000..ea1ca05 --- /dev/null +++ b/app/src/main/res/layout/emptyview.xml @@ -0,0 +1,14 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_popular_movies.xml b/app/src/main/res/layout/fragment_popular_movies.xml new file mode 100644 index 0000000..bfae834 --- /dev/null +++ b/app/src/main/res/layout/fragment_popular_movies.xml @@ -0,0 +1,23 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/popular_movie_row.xml b/app/src/main/res/layout/popular_movie_row.xml new file mode 100644 index 0000000..eded7d4 --- /dev/null +++ b/app/src/main/res/layout/popular_movie_row.xml @@ -0,0 +1,39 @@ + + + + + + + + + \ No newline at end of file diff --git a/build.gradle b/build.gradle index 22f601a..1894440 100644 --- a/build.gradle +++ b/build.gradle @@ -1,13 +1,15 @@ apply from: "$project.rootDir/tools/gradle/dependencies.gradle" buildscript { + ext.kotlin_version = '1.3.50' repositories { google() jcenter() - + mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:3.5.0' + classpath 'com.android.tools.build:gradle:3.5.1' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } @@ -15,6 +17,7 @@ allprojects { repositories { google() jcenter() + mavenCentral() } } diff --git a/common/.gitignore b/common/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/common/.gitignore @@ -0,0 +1 @@ +/build diff --git a/common/build.gradle b/common/build.gradle new file mode 100644 index 0000000..6fcf49c --- /dev/null +++ b/common/build.gradle @@ -0,0 +1,14 @@ +apply plugin: 'com.android.library' +apply from: "$project.rootDir/tools/gradle/script/quality.gradle" +apply from: "$project.rootDir/tools/gradle/base.gradle" + +android { + + buildTypes { + release { + minifyEnabled true + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + +} diff --git a/common/consumer-rules.pro b/common/consumer-rules.pro new file mode 100644 index 0000000..e69de29 diff --git a/common/proguard-rules.pro b/common/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/common/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/common/src/androidTest/java/com/egdroid/common/ExampleInstrumentedTest.java b/common/src/androidTest/java/com/egdroid/common/ExampleInstrumentedTest.java new file mode 100644 index 0000000..22ced8c --- /dev/null +++ b/common/src/androidTest/java/com/egdroid/common/ExampleInstrumentedTest.java @@ -0,0 +1,27 @@ +package com.egdroid.common; + +import android.content.Context; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import androidx.test.InstrumentationRegistry; +import androidx.test.runner.AndroidJUnit4; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + + assertEquals("com.egdroid.common.test", appContext.getPackageName()); + } +} diff --git a/common/src/main/AndroidManifest.xml b/common/src/main/AndroidManifest.xml new file mode 100644 index 0000000..9eab0b6 --- /dev/null +++ b/common/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + diff --git a/common/src/main/res/values/strings.xml b/common/src/main/res/values/strings.xml new file mode 100644 index 0000000..9e44af5 --- /dev/null +++ b/common/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + common + diff --git a/common/src/test/java/com/egdroid/common/ExampleUnitTest.java b/common/src/test/java/com/egdroid/common/ExampleUnitTest.java new file mode 100644 index 0000000..3061f3c --- /dev/null +++ b/common/src/test/java/com/egdroid/common/ExampleUnitTest.java @@ -0,0 +1,17 @@ +package com.egdroid.common; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see Testing documentation + */ +public class ExampleUnitTest { + @Test + public void addition_isCorrect() { + assertEquals(4, 2 + 2); + } +} \ No newline at end of file diff --git a/datasource/local/.gitignore b/datasource/local/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/datasource/local/.gitignore @@ -0,0 +1 @@ +/build diff --git a/datasource/local/build.gradle b/datasource/local/build.gradle new file mode 100644 index 0000000..99ab598 --- /dev/null +++ b/datasource/local/build.gradle @@ -0,0 +1,17 @@ +apply plugin: 'com.android.library' +apply from: "$project.rootDir/tools/gradle/script/quality.gradle" +apply from: "$project.rootDir/tools/gradle/base.gradle" + +android { + + buildTypes { + release { + minifyEnabled true + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } +} + +dependencies{ + api project(":models:localmodel") +} diff --git a/datasource/local/consumer-rules.pro b/datasource/local/consumer-rules.pro new file mode 100644 index 0000000..e69de29 diff --git a/datasource/local/proguard-rules.pro b/datasource/local/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/datasource/local/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/datasource/local/src/androidTest/java/com/egdroid/datasource/local/ExampleInstrumentedTest.java b/datasource/local/src/androidTest/java/com/egdroid/datasource/local/ExampleInstrumentedTest.java new file mode 100644 index 0000000..751eb9e --- /dev/null +++ b/datasource/local/src/androidTest/java/com/egdroid/datasource/local/ExampleInstrumentedTest.java @@ -0,0 +1,27 @@ +package com.egdroid.datasource.local; + +import android.content.Context; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import androidx.test.InstrumentationRegistry; +import androidx.test.runner.AndroidJUnit4; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + + assertEquals("com.egdroid.datasource.local.test", appContext.getPackageName()); + } +} diff --git a/datasource/local/src/main/AndroidManifest.xml b/datasource/local/src/main/AndroidManifest.xml new file mode 100644 index 0000000..aee27b6 --- /dev/null +++ b/datasource/local/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + diff --git a/datasource/local/src/main/java/com/egdroid/datasource/local/movie/DataConverter.kt b/datasource/local/src/main/java/com/egdroid/datasource/local/movie/DataConverter.kt new file mode 100644 index 0000000..1be2963 --- /dev/null +++ b/datasource/local/src/main/java/com/egdroid/datasource/local/movie/DataConverter.kt @@ -0,0 +1,27 @@ +package com.egdroid.datasource.local.movie + +import androidx.room.TypeConverter +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +object DataConverter { + @TypeConverter + @JvmStatic + fun fromIntList(list: List?): String? { + if (list == null) { + return null + } + val type = object : TypeToken>() {}.type + return Gson().toJson(list, type) + } + + @TypeConverter + @JvmStatic + fun toIntList(listString: String?): List? { + if (listString == null) { + return null + } + val type = object : TypeToken>() {}.type + return Gson().fromJson>(listString, type) + } +} diff --git a/datasource/local/src/main/java/com/egdroid/datasource/local/movie/LocalMovieFactory.kt b/datasource/local/src/main/java/com/egdroid/datasource/local/movie/LocalMovieFactory.kt new file mode 100644 index 0000000..635eb23 --- /dev/null +++ b/datasource/local/src/main/java/com/egdroid/datasource/local/movie/LocalMovieFactory.kt @@ -0,0 +1,10 @@ +package com.egdroid.datasource.local.movie + +import android.content.Context + +object LocalMovieFactory { + + fun provideDatabase(context: Context): MovieLocalDatabase { + return MovieLocalDatabase.getDatabase(context) + } +} diff --git a/datasource/local/src/main/java/com/egdroid/datasource/local/movie/MovieDao.kt b/datasource/local/src/main/java/com/egdroid/datasource/local/movie/MovieDao.kt new file mode 100644 index 0000000..5ac1bbc --- /dev/null +++ b/datasource/local/src/main/java/com/egdroid/datasource/local/movie/MovieDao.kt @@ -0,0 +1,22 @@ +package com.egdroid.datasource.local.movie + +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import com.egdroid.models.local.movie.MovieLocal +import io.reactivex.Completable +import io.reactivex.Maybe + +@Dao +interface MovieDao { + + @Query("SELECT * FROM movies") + fun getAllMovies(): Maybe> + + @Insert(onConflict = OnConflictStrategy.REPLACE) + fun insertAllMovies(movies: List) + + @Query("DELETE FROM movies") + fun deleteAllMovies(): Completable +} \ No newline at end of file diff --git a/datasource/local/src/main/java/com/egdroid/datasource/local/movie/MovieLocalDatabase.kt b/datasource/local/src/main/java/com/egdroid/datasource/local/movie/MovieLocalDatabase.kt new file mode 100644 index 0000000..2689e54 --- /dev/null +++ b/datasource/local/src/main/java/com/egdroid/datasource/local/movie/MovieLocalDatabase.kt @@ -0,0 +1,37 @@ +package com.egdroid.datasource.local.movie + +import android.content.Context +import androidx.room.Database +import androidx.room.Room +import androidx.room.RoomDatabase +import androidx.room.TypeConverters +import com.egdroid.models.local.movie.MovieLocal + +@Database(entities = [MovieLocal::class], version = 1, exportSchema = false) +@TypeConverters(DataConverter::class) +abstract class MovieLocalDatabase : RoomDatabase() { + abstract fun movieDao(): MovieDao + + companion object { + // Singleton prevents multiple instances of database opening at the + // same time. + @Volatile + private var INSTANCE: MovieLocalDatabase? = null + + fun getDatabase(context: Context): MovieLocalDatabase { + val tempInstance = INSTANCE + if (tempInstance != null) { + return tempInstance + } + synchronized(this) { + val instance = Room.databaseBuilder( + context.applicationContext, + MovieLocalDatabase::class.java, + "movies_database" + ).build() + INSTANCE = instance + return instance + } + } + } +} diff --git a/datasource/local/src/main/res/values/strings.xml b/datasource/local/src/main/res/values/strings.xml new file mode 100644 index 0000000..b74fbf3 --- /dev/null +++ b/datasource/local/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + local + diff --git a/datasource/local/src/test/java/com/egdroid/datasource/local/ExampleUnitTest.java b/datasource/local/src/test/java/com/egdroid/datasource/local/ExampleUnitTest.java new file mode 100644 index 0000000..d2bdc22 --- /dev/null +++ b/datasource/local/src/test/java/com/egdroid/datasource/local/ExampleUnitTest.java @@ -0,0 +1,17 @@ +package com.egdroid.datasource.local; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see Testing documentation + */ +public class ExampleUnitTest { + @Test + public void addition_isCorrect() { + assertEquals(4, 2 + 2); + } +} \ No newline at end of file diff --git a/datasource/remote/.gitignore b/datasource/remote/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/datasource/remote/.gitignore @@ -0,0 +1 @@ +/build diff --git a/datasource/remote/build.gradle b/datasource/remote/build.gradle new file mode 100644 index 0000000..fca0bfd --- /dev/null +++ b/datasource/remote/build.gradle @@ -0,0 +1,25 @@ +apply plugin: 'com.android.library' +apply from: "$project.rootDir/tools/gradle/script/quality.gradle" +apply from: "$project.rootDir/tools/gradle/base.gradle" + +android { + + buildTypes { + release { + minifyEnabled true + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + buildConfigField 'String', "ApiKey", AnotherMovieApp_ApiKey + resValue 'string', "api_key", AnotherMovieApp_ApiKey + } + debug { + minifyEnabled true + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + buildConfigField 'String', "ApiKey", AnotherMovieApp_ApiKey + resValue 'string', "api_key", AnotherMovieApp_ApiKey + } + } +} + +dependencies{ + api project(":models:remotemodel") +} diff --git a/datasource/remote/consumer-rules.pro b/datasource/remote/consumer-rules.pro new file mode 100644 index 0000000..e69de29 diff --git a/datasource/remote/proguard-rules.pro b/datasource/remote/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/datasource/remote/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/datasource/remote/src/androidTest/java/com/egdroid/datasource/remote/ExampleInstrumentedTest.java b/datasource/remote/src/androidTest/java/com/egdroid/datasource/remote/ExampleInstrumentedTest.java new file mode 100644 index 0000000..b4c2eea --- /dev/null +++ b/datasource/remote/src/androidTest/java/com/egdroid/datasource/remote/ExampleInstrumentedTest.java @@ -0,0 +1,27 @@ +package com.egdroid.datasource.remote; + +import android.content.Context; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import androidx.test.InstrumentationRegistry; +import androidx.test.runner.AndroidJUnit4; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + + assertEquals("com.egdroid.datasource.remote.test", appContext.getPackageName()); + } +} diff --git a/datasource/remote/src/main/AndroidManifest.xml b/datasource/remote/src/main/AndroidManifest.xml new file mode 100644 index 0000000..960d295 --- /dev/null +++ b/datasource/remote/src/main/AndroidManifest.xml @@ -0,0 +1,5 @@ + + + + diff --git a/datasource/remote/src/main/java/com/egdroid/datasource/remote/movie/Extensions.kt b/datasource/remote/src/main/java/com/egdroid/datasource/remote/movie/Extensions.kt new file mode 100644 index 0000000..42e8ffb --- /dev/null +++ b/datasource/remote/src/main/java/com/egdroid/datasource/remote/movie/Extensions.kt @@ -0,0 +1,13 @@ +package com.egdroid.datasource.remote.movie + +import android.content.Context +import android.net.ConnectivityManager +import android.net.NetworkInfo + +fun isNetworkConnected(context: Context): Boolean { + val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) + return if (connectivityManager is ConnectivityManager) { + val networkInfo: NetworkInfo? = connectivityManager.activeNetworkInfo + networkInfo?.isConnected ?: false + } else false +} \ No newline at end of file diff --git a/datasource/remote/src/main/java/com/egdroid/datasource/remote/movie/MovieRemote.kt b/datasource/remote/src/main/java/com/egdroid/datasource/remote/movie/MovieRemote.kt new file mode 100644 index 0000000..1f1440a --- /dev/null +++ b/datasource/remote/src/main/java/com/egdroid/datasource/remote/movie/MovieRemote.kt @@ -0,0 +1,3 @@ +package com.egdroid.datasource.remote.movie + +class MovieRemote diff --git a/datasource/remote/src/main/java/com/egdroid/datasource/remote/movie/MoviesServiceFactory.kt b/datasource/remote/src/main/java/com/egdroid/datasource/remote/movie/MoviesServiceFactory.kt new file mode 100644 index 0000000..e14550c --- /dev/null +++ b/datasource/remote/src/main/java/com/egdroid/datasource/remote/movie/MoviesServiceFactory.kt @@ -0,0 +1,123 @@ +package com.egdroid.datasource.remote.movie + +import android.content.Context +import android.util.Base64 +import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory +import okhttp3.Cache +import okhttp3.CacheControl +import okhttp3.Interceptor +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import timber.log.Timber +import java.io.File +import java.util.concurrent.TimeUnit + +object MoviesServiceFactory { + + external fun getNativeKey(): String + + init { + System.loadLibrary("keys") + } + + fun provideRetrofitService(context: Context): PopularMovieService { + return provideRetrofit(context).create(PopularMovieService::class.java) + + } + + fun provideRetrofit(context: Context): Retrofit { + return Retrofit.Builder() + .baseUrl("https://api.themoviedb.org/3/movie/") + .addConverterFactory(GsonConverterFactory.create()) + .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) + .client(provideOkHttpClient(context)) + .build() + } + + private fun provideOkHttpClient(context: Context): OkHttpClient { + return OkHttpClient.Builder() + .addInterceptor(provideLoggingInterceptor()) + .addInterceptor(provideQueryParamsInterceptor()) + .addInterceptor(provideCashingInterceptor()) + .addNetworkInterceptor(provideOfflineCashingInterceptor(context)) + .cache(provideCache(context)) + .build() + } + + private fun provideLoggingInterceptor(): Interceptor { + val logging = HttpLoggingInterceptor() + logging.level = HttpLoggingInterceptor.Level.BODY + return logging + } + + private fun provideAuthInterceptor(): Interceptor { + return Interceptor { chain -> + val request = chain.request().newBuilder() + .addHeader("api_key", getNativeKey()) + .addHeader("page", "1") + .addHeader("language", "en-US") + .build() + chain.proceed(request) + } + } + + private fun provideQueryParamsInterceptor(): Interceptor { + val apiKey = String(Base64.decode(getNativeKey(), Base64.DEFAULT)) + return Interceptor { chain -> + var request = chain.request() + val url = request.url().newBuilder() + .addQueryParameter("api_key", apiKey) + .addQueryParameter("page", "1") + .addQueryParameter("language", "en-US") + .build() + request = request.newBuilder().url(url).build() + chain.proceed(request) + } + } + + private fun provideCache(context: Context): Cache? { + var cache: Cache? = null + try { + // 10 MB for cache + val file = File(context.cacheDir, "okhttp_cache") + cache = Cache(file, 10 * 1024 * 1024) + } catch (e: Exception) { + Timber.w("Failed to create cache. Error: $e") + } + return cache + } + + private fun provideCashingInterceptor(): Interceptor { + return Interceptor { chain -> + val response = chain.proceed(chain.request()) + val cashControl = CacheControl.Builder() + .maxAge(3, TimeUnit.MINUTES) + .build() + response.newBuilder() + .header("Cache-Control", cashControl.toString()) + .build() + } + } + + // even if cashing time passed and user don't have network fetch data from cache + private fun provideOfflineCashingInterceptor(context: Context): Interceptor { + return Interceptor { chain -> + val request = chain.request() + + if (!isNetworkConnected(context)) { + val cacheControl = CacheControl.Builder() + .maxStale(7, TimeUnit.DAYS) + .build() + + request.newBuilder() + .cacheControl(cacheControl) + .build() + } + chain.proceed(request) + } + } + + +} diff --git a/datasource/remote/src/main/java/com/egdroid/datasource/remote/movie/PopularMovieService.kt b/datasource/remote/src/main/java/com/egdroid/datasource/remote/movie/PopularMovieService.kt new file mode 100644 index 0000000..a1967af --- /dev/null +++ b/datasource/remote/src/main/java/com/egdroid/datasource/remote/movie/PopularMovieService.kt @@ -0,0 +1,12 @@ +package com.egdroid.datasource.remote.movie + +import com.egdroid.models.remote.movie.popularmovie.MovieResponse +import io.reactivex.Single +import retrofit2.http.GET + + +interface PopularMovieService { + + @GET("popular") + fun getMovies(): Single +} \ No newline at end of file diff --git a/datasource/remote/src/main/res/values/strings.xml b/datasource/remote/src/main/res/values/strings.xml new file mode 100644 index 0000000..16f98ce --- /dev/null +++ b/datasource/remote/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + remote + diff --git a/datasource/remote/src/test/java/com/egdroid/datasource/remote/ExampleUnitTest.java b/datasource/remote/src/test/java/com/egdroid/datasource/remote/ExampleUnitTest.java new file mode 100644 index 0000000..e158e77 --- /dev/null +++ b/datasource/remote/src/test/java/com/egdroid/datasource/remote/ExampleUnitTest.java @@ -0,0 +1,17 @@ +package com.egdroid.datasource.remote; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see Testing documentation + */ +public class ExampleUnitTest { + @Test + public void addition_isCorrect() { + assertEquals(4, 2 + 2); + } +} \ No newline at end of file diff --git a/features/popularmovies/.gitignore b/features/popularmovies/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/features/popularmovies/.gitignore @@ -0,0 +1 @@ +/build diff --git a/features/popularmovies/build.gradle b/features/popularmovies/build.gradle new file mode 100644 index 0000000..86e8807 --- /dev/null +++ b/features/popularmovies/build.gradle @@ -0,0 +1,18 @@ +apply plugin: 'com.android.library' +apply from: "$project.rootDir/tools/gradle/script/quality.gradle" +apply from: "$project.rootDir/tools/gradle/base.gradle" + +android { + buildTypes { + release { + minifyEnabled true + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } +} + +dependencies{ + api project(":datasource:local") + api project(":datasource:remote") + api project(":models:mapper") +} diff --git a/features/popularmovies/consumer-rules.pro b/features/popularmovies/consumer-rules.pro new file mode 100644 index 0000000..e69de29 diff --git a/features/popularmovies/proguard-rules.pro b/features/popularmovies/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/features/popularmovies/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/features/popularmovies/src/androidTest/java/com/egdroid/features/popularmovies/ExampleInstrumentedTest.kt b/features/popularmovies/src/androidTest/java/com/egdroid/features/popularmovies/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..2073145 --- /dev/null +++ b/features/popularmovies/src/androidTest/java/com/egdroid/features/popularmovies/ExampleInstrumentedTest.kt @@ -0,0 +1,22 @@ +package com.egdroid.features.popularmovies + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.platform.app.InstrumentationRegistry +import org.junit.Assert.assertEquals +import org.junit.Test +import org.junit.runner.RunWith + +/** + * 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.getInstrumentation().targetContext + assertEquals("com.egdroid.features.popularmovies.test", appContext.packageName) + } +} diff --git a/features/popularmovies/src/main/AndroidManifest.xml b/features/popularmovies/src/main/AndroidManifest.xml new file mode 100644 index 0000000..13bb866 --- /dev/null +++ b/features/popularmovies/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + diff --git a/features/popularmovies/src/main/java/com/egdroid/features/popularmovies/repository/PopularMovieRepo.kt b/features/popularmovies/src/main/java/com/egdroid/features/popularmovies/repository/PopularMovieRepo.kt new file mode 100644 index 0000000..1c270cd --- /dev/null +++ b/features/popularmovies/src/main/java/com/egdroid/features/popularmovies/repository/PopularMovieRepo.kt @@ -0,0 +1,39 @@ +package com.egdroid.features.popularmovies.repository + +import com.egdroid.datasource.local.movie.MovieLocalDatabase +import com.egdroid.datasource.remote.movie.PopularMovieService +import com.egdroid.mapper.MovieMapper +import com.egdroid.model.datasource.MovieDataSource +import io.reactivex.Flowable +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.schedulers.Schedulers + + +class PopularMovieRepo(private val database: MovieLocalDatabase, + private val popularMovieService: PopularMovieService, + private val mapper: MovieMapper) { + + fun getMovies(): Flowable> { + return Flowable.merge(getLocalMovies(), getRemoteMovies()) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + } + + private fun getLocalMovies(): Flowable> { + return database.movieDao().getAllMovies().map { + mapper.mapMovieLocalToDataSource(it) + }.toFlowable() + } + + private fun getRemoteMovies(): Flowable> { + return popularMovieService.getMovies().doOnSuccess { + database.movieDao().deleteAllMovies() + .doOnComplete { + database.movieDao() + .insertAllMovies(mapper.mapMovieResponseToLocalMovie(it.results!!)) + } + }.map { + mapper.mapMovieResponseToDataSource(it.results!!) + }.toFlowable() + } +} \ No newline at end of file diff --git a/features/popularmovies/src/main/java/com/egdroid/features/popularmovies/repository/PopularMoviesRepoFactory.kt b/features/popularmovies/src/main/java/com/egdroid/features/popularmovies/repository/PopularMoviesRepoFactory.kt new file mode 100644 index 0000000..94d9888 --- /dev/null +++ b/features/popularmovies/src/main/java/com/egdroid/features/popularmovies/repository/PopularMoviesRepoFactory.kt @@ -0,0 +1,13 @@ +package com.egdroid.features.popularmovies.repository + +import android.content.Context +import com.egdroid.datasource.local.movie.LocalMovieFactory.provideDatabase +import com.egdroid.datasource.remote.movie.MoviesServiceFactory.provideRetrofitService +import com.egdroid.mapper.MapperFactory.providePopularMovieMapper + +object PopularMoviesRepoFactory { + + fun providePopularMoviesRepo(context: Context): PopularMovieRepo { + return PopularMovieRepo(provideDatabase(context), provideRetrofitService(context), providePopularMovieMapper()) + } +} \ No newline at end of file diff --git a/features/popularmovies/src/main/java/com/egdroid/features/popularmovies/usecase/PopularMovieUseCase.kt b/features/popularmovies/src/main/java/com/egdroid/features/popularmovies/usecase/PopularMovieUseCase.kt new file mode 100644 index 0000000..5f047d5 --- /dev/null +++ b/features/popularmovies/src/main/java/com/egdroid/features/popularmovies/usecase/PopularMovieUseCase.kt @@ -0,0 +1,12 @@ +package com.egdroid.features.popularmovies.usecase + +import com.egdroid.features.popularmovies.repository.PopularMovieRepo +import com.egdroid.mapper.MovieMapper + +class PopularMovieUseCase(repo: PopularMovieRepo, providePopularMovieMapper: MovieMapper) { + + val popularmovies = repo.getMovies().map { + providePopularMovieMapper.mapMovieDataSourceToMovieEntity(it) + } + +} \ No newline at end of file diff --git a/features/popularmovies/src/main/java/com/egdroid/features/popularmovies/usecase/PopularMoviesUseCaseFactory.kt b/features/popularmovies/src/main/java/com/egdroid/features/popularmovies/usecase/PopularMoviesUseCaseFactory.kt new file mode 100644 index 0000000..5a09c2e --- /dev/null +++ b/features/popularmovies/src/main/java/com/egdroid/features/popularmovies/usecase/PopularMoviesUseCaseFactory.kt @@ -0,0 +1,13 @@ +package com.egdroid.features.popularmovies.usecase + +import android.content.Context +import com.egdroid.features.popularmovies.repository.PopularMoviesRepoFactory +import com.egdroid.mapper.MapperFactory + +object PopularMoviesUseCaseFactory { + + fun providePopularMoviesUseCase(context: Context): PopularMovieUseCase { + return PopularMovieUseCase(PopularMoviesRepoFactory.providePopularMoviesRepo(context), + MapperFactory.providePopularMovieMapper()) + } +} \ No newline at end of file diff --git a/features/popularmovies/src/main/res/values/strings.xml b/features/popularmovies/src/main/res/values/strings.xml new file mode 100644 index 0000000..e3bd89a --- /dev/null +++ b/features/popularmovies/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + popularmovies + diff --git a/features/popularmovies/src/test/java/com/egdroid/features/popularmovies/ExampleUnitTest.kt b/features/popularmovies/src/test/java/com/egdroid/features/popularmovies/ExampleUnitTest.kt new file mode 100644 index 0000000..34ef6b5 --- /dev/null +++ b/features/popularmovies/src/test/java/com/egdroid/features/popularmovies/ExampleUnitTest.kt @@ -0,0 +1,16 @@ +package com.egdroid.features.popularmovies + +import org.junit.Assert.assertEquals +import org.junit.Test + +/** + * 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/features/upcomingmovies/.gitignore b/features/upcomingmovies/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/features/upcomingmovies/.gitignore @@ -0,0 +1 @@ +/build diff --git a/features/upcomingmovies/build.gradle b/features/upcomingmovies/build.gradle new file mode 100644 index 0000000..b40f635 --- /dev/null +++ b/features/upcomingmovies/build.gradle @@ -0,0 +1,21 @@ +apply plugin: 'com.android.library' +apply from: "$project.rootDir/tools/gradle/script/quality.gradle" +apply from: "$project.rootDir/tools/gradle/base.gradle" + +android { + buildTypes { + release { + minifyEnabled true + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + +} + +dependencies { + api project(":datasource:local") + api project(":datasource:remote") + api project(":models:mapper") + api project(":models:datasourcemodel") + +} diff --git a/features/upcomingmovies/consumer-rules.pro b/features/upcomingmovies/consumer-rules.pro new file mode 100644 index 0000000..e69de29 diff --git a/features/upcomingmovies/proguard-rules.pro b/features/upcomingmovies/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/features/upcomingmovies/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/features/upcomingmovies/src/androidTest/java/com/egdroid/feature/upcomingmovies/ExampleInstrumentedTest.java b/features/upcomingmovies/src/androidTest/java/com/egdroid/feature/upcomingmovies/ExampleInstrumentedTest.java new file mode 100644 index 0000000..30b2cf2 --- /dev/null +++ b/features/upcomingmovies/src/androidTest/java/com/egdroid/feature/upcomingmovies/ExampleInstrumentedTest.java @@ -0,0 +1,27 @@ +package com.egdroid.feature.upcomingmovies; + +import android.content.Context; + +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + + assertEquals("com.egdroid.feature.upcomingmovies.test", appContext.getPackageName()); + } +} diff --git a/features/upcomingmovies/src/main/AndroidManifest.xml b/features/upcomingmovies/src/main/AndroidManifest.xml new file mode 100644 index 0000000..898d25d --- /dev/null +++ b/features/upcomingmovies/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + diff --git a/features/upcomingmovies/src/main/java/com/egdroid/feature/upcomingmovies/rep/MovieRepo.java b/features/upcomingmovies/src/main/java/com/egdroid/feature/upcomingmovies/rep/MovieRepo.java new file mode 100644 index 0000000..36c2a2d --- /dev/null +++ b/features/upcomingmovies/src/main/java/com/egdroid/feature/upcomingmovies/rep/MovieRepo.java @@ -0,0 +1,23 @@ +package com.egdroid.feature.upcomingmovies.rep; + +public class MovieRepo { + +// public MovieDataSource getMovies() { +// +// MovieMapper movieMapper = new MovieMapper(); +// +// // Room integration +// MovieLocal movieLocalDatabase = new MovieLocalDatabase().getMovie(); +// +// // Retrofit integration +// MovieResponse movieRemote = new MovieRemote().getMovie(); +// +// if (movieLocalDatabase != null) { +// return movieMapper.mapToDataSource(movieLocalDatabase); +// } else { +// return movieMapper.mapToDataSource(movieRemote); +// } +// +// } + +} diff --git a/features/upcomingmovies/src/main/res/values/strings.xml b/features/upcomingmovies/src/main/res/values/strings.xml new file mode 100644 index 0000000..ef66922 --- /dev/null +++ b/features/upcomingmovies/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + upcomingmovies + diff --git a/features/upcomingmovies/src/test/java/com/egdroid/feature/upcomingmovies/ExampleUnitTest.java b/features/upcomingmovies/src/test/java/com/egdroid/feature/upcomingmovies/ExampleUnitTest.java new file mode 100644 index 0000000..de997df --- /dev/null +++ b/features/upcomingmovies/src/test/java/com/egdroid/feature/upcomingmovies/ExampleUnitTest.java @@ -0,0 +1,17 @@ +package com.egdroid.feature.upcomingmovies; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see Testing documentation + */ +public class ExampleUnitTest { + @Test + public void addition_isCorrect() { + assertEquals(4, 2 + 2); + } +} \ No newline at end of file diff --git a/models/datasourcemodel/.gitignore b/models/datasourcemodel/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/models/datasourcemodel/.gitignore @@ -0,0 +1 @@ +/build diff --git a/models/datasourcemodel/build.gradle b/models/datasourcemodel/build.gradle new file mode 100644 index 0000000..8713285 --- /dev/null +++ b/models/datasourcemodel/build.gradle @@ -0,0 +1,14 @@ +apply plugin: 'com.android.library' +apply from: "$project.rootDir/tools/gradle/script/quality.gradle" +apply from: "$project.rootDir/tools/gradle/base.gradle" + +android { + + buildTypes { + release { + minifyEnabled true + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + +} \ No newline at end of file diff --git a/models/datasourcemodel/consumer-rules.pro b/models/datasourcemodel/consumer-rules.pro new file mode 100644 index 0000000..e69de29 diff --git a/models/datasourcemodel/proguard-rules.pro b/models/datasourcemodel/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/models/datasourcemodel/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/models/datasourcemodel/src/androidTest/java/com/egdroid/model/datasource/ExampleInstrumentedTest.java b/models/datasourcemodel/src/androidTest/java/com/egdroid/model/datasource/ExampleInstrumentedTest.java new file mode 100644 index 0000000..dd3b67b --- /dev/null +++ b/models/datasourcemodel/src/androidTest/java/com/egdroid/model/datasource/ExampleInstrumentedTest.java @@ -0,0 +1,27 @@ +package com.egdroid.model.datasource; + +import android.content.Context; + +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + + assertEquals("com.egdroid.model.datasource.test", appContext.getPackageName()); + } +} diff --git a/models/datasourcemodel/src/main/AndroidManifest.xml b/models/datasourcemodel/src/main/AndroidManifest.xml new file mode 100644 index 0000000..ae633c3 --- /dev/null +++ b/models/datasourcemodel/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + diff --git a/models/datasourcemodel/src/main/java/com/egdroid/model/datasource/MovieDataSource.kt b/models/datasourcemodel/src/main/java/com/egdroid/model/datasource/MovieDataSource.kt new file mode 100644 index 0000000..6f09a29 --- /dev/null +++ b/models/datasourcemodel/src/main/java/com/egdroid/model/datasource/MovieDataSource.kt @@ -0,0 +1,8 @@ +package com.egdroid.model.datasource + +data class MovieDataSource( + val id: Int? = null, + val title: String? = null, + val overview: String? = null, + val posterPath: String? = null +) \ No newline at end of file diff --git a/models/datasourcemodel/src/main/res/values/strings.xml b/models/datasourcemodel/src/main/res/values/strings.xml new file mode 100644 index 0000000..7c4da98 --- /dev/null +++ b/models/datasourcemodel/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + datasourcemodel + diff --git a/models/datasourcemodel/src/test/java/com/egdroid/model/datasource/ExampleUnitTest.java b/models/datasourcemodel/src/test/java/com/egdroid/model/datasource/ExampleUnitTest.java new file mode 100644 index 0000000..415c734 --- /dev/null +++ b/models/datasourcemodel/src/test/java/com/egdroid/model/datasource/ExampleUnitTest.java @@ -0,0 +1,17 @@ +package com.egdroid.model.datasource; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see Testing documentation + */ +public class ExampleUnitTest { + @Test + public void addition_isCorrect() { + assertEquals(4, 2 + 2); + } +} \ No newline at end of file diff --git a/models/entitymodel/.gitignore b/models/entitymodel/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/models/entitymodel/.gitignore @@ -0,0 +1 @@ +/build diff --git a/models/entitymodel/build.gradle b/models/entitymodel/build.gradle new file mode 100644 index 0000000..4db41c0 --- /dev/null +++ b/models/entitymodel/build.gradle @@ -0,0 +1,13 @@ +apply plugin: 'com.android.library' +apply from: "$project.rootDir/tools/gradle/script/quality.gradle" +apply from: "$project.rootDir/tools/gradle/base.gradle" + +android { + buildTypes { + release { + minifyEnabled true + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + +} diff --git a/models/entitymodel/consumer-rules.pro b/models/entitymodel/consumer-rules.pro new file mode 100644 index 0000000..e69de29 diff --git a/models/entitymodel/proguard-rules.pro b/models/entitymodel/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/models/entitymodel/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/models/entitymodel/src/androidTest/java/com/egdroid/models/ExampleInstrumentedTest.kt b/models/entitymodel/src/androidTest/java/com/egdroid/models/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..ed7fd2c --- /dev/null +++ b/models/entitymodel/src/androidTest/java/com/egdroid/models/ExampleInstrumentedTest.kt @@ -0,0 +1,22 @@ +package com.egdroid.models + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.platform.app.InstrumentationRegistry +import org.junit.Assert.assertEquals +import org.junit.Test +import org.junit.runner.RunWith + +/** + * 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.getInstrumentation().targetContext + assertEquals("com.egdroid.models.test", appContext.packageName) + } +} diff --git a/models/entitymodel/src/main/AndroidManifest.xml b/models/entitymodel/src/main/AndroidManifest.xml new file mode 100644 index 0000000..6d8a19d --- /dev/null +++ b/models/entitymodel/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + diff --git a/models/entitymodel/src/main/java/com/egdroid/models/entity/popularmovies/MovieEntity.kt b/models/entitymodel/src/main/java/com/egdroid/models/entity/popularmovies/MovieEntity.kt new file mode 100644 index 0000000..92dbde8 --- /dev/null +++ b/models/entitymodel/src/main/java/com/egdroid/models/entity/popularmovies/MovieEntity.kt @@ -0,0 +1,9 @@ +package com.egdroid.models.popularmovies + +data class MovieEntity( + val id: Int, + val title: String? = null, + val overview: String? = null, + val posterPath: String? = null + +) diff --git a/models/entitymodel/src/main/res/values/strings.xml b/models/entitymodel/src/main/res/values/strings.xml new file mode 100644 index 0000000..edbd4f8 --- /dev/null +++ b/models/entitymodel/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + uimodel + diff --git a/models/entitymodel/src/test/java/com/egdroid/models/ExampleUnitTest.kt b/models/entitymodel/src/test/java/com/egdroid/models/ExampleUnitTest.kt new file mode 100644 index 0000000..c1df2ae --- /dev/null +++ b/models/entitymodel/src/test/java/com/egdroid/models/ExampleUnitTest.kt @@ -0,0 +1,16 @@ +package com.egdroid.models + +import org.junit.Assert.assertEquals +import org.junit.Test + +/** + * 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/models/localmodel/.gitignore b/models/localmodel/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/models/localmodel/.gitignore @@ -0,0 +1 @@ +/build diff --git a/models/localmodel/build.gradle b/models/localmodel/build.gradle new file mode 100644 index 0000000..8713285 --- /dev/null +++ b/models/localmodel/build.gradle @@ -0,0 +1,14 @@ +apply plugin: 'com.android.library' +apply from: "$project.rootDir/tools/gradle/script/quality.gradle" +apply from: "$project.rootDir/tools/gradle/base.gradle" + +android { + + buildTypes { + release { + minifyEnabled true + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + +} \ No newline at end of file diff --git a/models/localmodel/consumer-rules.pro b/models/localmodel/consumer-rules.pro new file mode 100644 index 0000000..e69de29 diff --git a/models/localmodel/proguard-rules.pro b/models/localmodel/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/models/localmodel/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/models/localmodel/src/androidTest/java/com/egdroid/models/local/ExampleInstrumentedTest.java b/models/localmodel/src/androidTest/java/com/egdroid/models/local/ExampleInstrumentedTest.java new file mode 100644 index 0000000..8bde83b --- /dev/null +++ b/models/localmodel/src/androidTest/java/com/egdroid/models/local/ExampleInstrumentedTest.java @@ -0,0 +1,27 @@ +package com.egdroid.models.local; + +import android.content.Context; + +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + + assertEquals("com.egdroid.models.local.test", appContext.getPackageName()); + } +} diff --git a/models/localmodel/src/main/AndroidManifest.xml b/models/localmodel/src/main/AndroidManifest.xml new file mode 100644 index 0000000..229fad5 --- /dev/null +++ b/models/localmodel/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + diff --git a/models/localmodel/src/main/java/com/egdroid/models/local/movie/MovieLocal.kt b/models/localmodel/src/main/java/com/egdroid/models/local/movie/MovieLocal.kt new file mode 100644 index 0000000..6627ca1 --- /dev/null +++ b/models/localmodel/src/main/java/com/egdroid/models/local/movie/MovieLocal.kt @@ -0,0 +1,14 @@ +package com.egdroid.models.local.movie + +import androidx.room.Entity +import androidx.room.PrimaryKey + +@Entity(tableName = "movies") +data class MovieLocal( + @PrimaryKey(autoGenerate = false) + val id: Int, + val title: String? = null, + val overview: String? = null, + val posterPath: String? = null + +) diff --git a/models/localmodel/src/main/res/values/strings.xml b/models/localmodel/src/main/res/values/strings.xml new file mode 100644 index 0000000..3888986 --- /dev/null +++ b/models/localmodel/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + localmodel + diff --git a/models/localmodel/src/test/java/com/egdroid/models/local/ExampleUnitTest.java b/models/localmodel/src/test/java/com/egdroid/models/local/ExampleUnitTest.java new file mode 100644 index 0000000..5799b7e --- /dev/null +++ b/models/localmodel/src/test/java/com/egdroid/models/local/ExampleUnitTest.java @@ -0,0 +1,17 @@ +package com.egdroid.models.local; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see Testing documentation + */ +public class ExampleUnitTest { + @Test + public void addition_isCorrect() { + assertEquals(4, 2 + 2); + } +} \ No newline at end of file diff --git a/models/mapper/.gitignore b/models/mapper/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/models/mapper/.gitignore @@ -0,0 +1 @@ +/build diff --git a/models/mapper/build.gradle b/models/mapper/build.gradle new file mode 100644 index 0000000..03847d3 --- /dev/null +++ b/models/mapper/build.gradle @@ -0,0 +1,20 @@ +apply plugin: 'com.android.library' +apply from: "$project.rootDir/tools/gradle/script/quality.gradle" +apply from: "$project.rootDir/tools/gradle/base.gradle" + +android { + buildTypes { + release { + minifyEnabled true + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + api project(":models:remotemodel") + api project(":models:localmodel") + api project(":models:datasourcemodel") + api project(":models:uimodel") + api project(":models:entitymodel") +} diff --git a/models/mapper/consumer-rules.pro b/models/mapper/consumer-rules.pro new file mode 100644 index 0000000..e69de29 diff --git a/models/mapper/proguard-rules.pro b/models/mapper/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/models/mapper/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/models/mapper/src/androidTest/java/com/egdroid/mapper/ExampleInstrumentedTest.java b/models/mapper/src/androidTest/java/com/egdroid/mapper/ExampleInstrumentedTest.java new file mode 100644 index 0000000..14046e6 --- /dev/null +++ b/models/mapper/src/androidTest/java/com/egdroid/mapper/ExampleInstrumentedTest.java @@ -0,0 +1,27 @@ +package com.egdroid.mapper; + +import android.content.Context; + +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + + assertEquals("com.egdroid.mapper.test", appContext.getPackageName()); + } +} diff --git a/models/mapper/src/main/AndroidManifest.xml b/models/mapper/src/main/AndroidManifest.xml new file mode 100644 index 0000000..a1e6b54 --- /dev/null +++ b/models/mapper/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + diff --git a/models/mapper/src/main/java/com/egdroid/mapper/MapperFactory.kt b/models/mapper/src/main/java/com/egdroid/mapper/MapperFactory.kt new file mode 100644 index 0000000..c8d356a --- /dev/null +++ b/models/mapper/src/main/java/com/egdroid/mapper/MapperFactory.kt @@ -0,0 +1,8 @@ +package com.egdroid.mapper + +object MapperFactory { + + fun providePopularMovieMapper(): MovieMapper { + return MovieMapper() + } +} \ No newline at end of file diff --git a/models/mapper/src/main/java/com/egdroid/mapper/MovieMapper.kt b/models/mapper/src/main/java/com/egdroid/mapper/MovieMapper.kt new file mode 100644 index 0000000..a96bb25 --- /dev/null +++ b/models/mapper/src/main/java/com/egdroid/mapper/MovieMapper.kt @@ -0,0 +1,93 @@ +package com.egdroid.mapper + +import com.egdroid.model.datasource.MovieDataSource +import com.egdroid.models.local.movie.MovieLocal +import com.egdroid.models.popularmovies.MovieEntity +import com.egdroid.models.popularmovies.MovieUi +import com.egdroid.models.remote.movie.popularmovie.MovieRemote + +class MovieMapper { + + fun mapDataSourceToMovieLocal(movieDataSource: MovieDataSource): MovieLocal { + return MovieLocal( + movieDataSource.id!!, + movieDataSource.title, + movieDataSource.overview, + movieDataSource.posterPath + ) + } + + fun mapMovieLocalToDataSource(movieLocal: List): List { + val moviesDataSource = mutableListOf() + for (movie in movieLocal) { + moviesDataSource.add(MovieDataSource( + movie.id, + movie.title, + movie.overview, + movie.posterPath + )) + } + return moviesDataSource + } + + fun mapMovieDataSourceToMovieEntity(movieDataSources: List): List { + val movieEntities = mutableListOf() + for (movie in movieDataSources) { + movieEntities.add(MovieEntity( + movie.id!!, + movie.title, + movie.overview, + movie.posterPath + )) + } + return movieEntities + } + + fun mapMovieEntityToMovieUi(movieEntities: List): List { + val movies = mutableListOf() + for (movie in movieEntities) { + movies.add(MovieUi( + movie.id, + movie.title, + movie.overview, + movie.posterPath + )) + } + return movies + } + + fun mapMovieResponseToDataSource(moviesResponse: List): List { + val moviesDataSource = mutableListOf() + for (movie in moviesResponse) { + moviesDataSource.add(MovieDataSource( + movie.id, + movie.title, + movie.overview, + movie.poster_path + )) + } + return moviesDataSource + } + + fun mapMovieResponseToLocalMovie(moviesResponse: List): List { + val moviesDataSource = mutableListOf() + for (movie in moviesResponse) { + moviesDataSource.add(MovieLocal( + movie.id, + movie.title, + movie.overview, + movie.poster_path + )) + } + return moviesDataSource + } + + fun mapMovieDataSourceToMovieLocal(movieDataSource: MovieDataSource): MovieLocal { + return MovieLocal( + movieDataSource.id!!, + movieDataSource.title, + movieDataSource.overview, + movieDataSource.posterPath + ) + } +} diff --git a/models/mapper/src/main/res/values/strings.xml b/models/mapper/src/main/res/values/strings.xml new file mode 100644 index 0000000..22d889b --- /dev/null +++ b/models/mapper/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + mapper + diff --git a/models/mapper/src/test/java/com/egdroid/mapper/ExampleUnitTest.java b/models/mapper/src/test/java/com/egdroid/mapper/ExampleUnitTest.java new file mode 100644 index 0000000..8c5a8b8 --- /dev/null +++ b/models/mapper/src/test/java/com/egdroid/mapper/ExampleUnitTest.java @@ -0,0 +1,17 @@ +package com.egdroid.mapper; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see Testing documentation + */ +public class ExampleUnitTest { + @Test + public void addition_isCorrect() { + assertEquals(4, 2 + 2); + } +} \ No newline at end of file diff --git a/models/remotemodel/.gitignore b/models/remotemodel/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/models/remotemodel/.gitignore @@ -0,0 +1 @@ +/build diff --git a/models/remotemodel/build.gradle b/models/remotemodel/build.gradle new file mode 100644 index 0000000..6fcf49c --- /dev/null +++ b/models/remotemodel/build.gradle @@ -0,0 +1,14 @@ +apply plugin: 'com.android.library' +apply from: "$project.rootDir/tools/gradle/script/quality.gradle" +apply from: "$project.rootDir/tools/gradle/base.gradle" + +android { + + buildTypes { + release { + minifyEnabled true + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + +} diff --git a/models/remotemodel/consumer-rules.pro b/models/remotemodel/consumer-rules.pro new file mode 100644 index 0000000..e69de29 diff --git a/models/remotemodel/proguard-rules.pro b/models/remotemodel/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/models/remotemodel/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/models/remotemodel/src/androidTest/java/com/egdroid/models/remote/ExampleInstrumentedTest.java b/models/remotemodel/src/androidTest/java/com/egdroid/models/remote/ExampleInstrumentedTest.java new file mode 100644 index 0000000..1a97ba2 --- /dev/null +++ b/models/remotemodel/src/androidTest/java/com/egdroid/models/remote/ExampleInstrumentedTest.java @@ -0,0 +1,27 @@ +package com.egdroid.models.remote; + +import android.content.Context; + +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + + assertEquals("com.egdroid.models.remote.test", appContext.getPackageName()); + } +} diff --git a/models/remotemodel/src/main/AndroidManifest.xml b/models/remotemodel/src/main/AndroidManifest.xml new file mode 100644 index 0000000..8edf1c8 --- /dev/null +++ b/models/remotemodel/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + diff --git a/models/remotemodel/src/main/java/com/egdroid/models/remote/movie/popularmovie/MovieRemote.kt b/models/remotemodel/src/main/java/com/egdroid/models/remote/movie/popularmovie/MovieRemote.kt new file mode 100644 index 0000000..b36a60a --- /dev/null +++ b/models/remotemodel/src/main/java/com/egdroid/models/remote/movie/popularmovie/MovieRemote.kt @@ -0,0 +1,33 @@ +package com.egdroid.models.remote.movie.popularmovie + +import com.google.gson.annotations.SerializedName + +data class MovieRemote( + @SerializedName("popularity") + val popularity: Double, + @SerializedName("vote_count") + val vote_count: Int, + @SerializedName("video") + val video: Boolean, + @SerializedName("poster_path") + val poster_path: String, + @SerializedName("id") + val id: Int, + @SerializedName("adult") + val adult: Boolean, + @SerializedName("backdrop_path") + val backdrop_path: String, + @SerializedName("original_language") + val original_language: String, + @SerializedName("original_title") + val original_title: String, + @SerializedName("genre_ids") + val genre_ids: List, + @SerializedName("title") + val title: String, + @SerializedName("vote_average") + val vote_average: Double, + @SerializedName("overview") + val overview: String, + @SerializedName("release_date") + val release_date: String) diff --git a/models/remotemodel/src/main/java/com/egdroid/models/remote/movie/popularmovie/MovieResponse.kt b/models/remotemodel/src/main/java/com/egdroid/models/remote/movie/popularmovie/MovieResponse.kt new file mode 100644 index 0000000..5027a28 --- /dev/null +++ b/models/remotemodel/src/main/java/com/egdroid/models/remote/movie/popularmovie/MovieResponse.kt @@ -0,0 +1,8 @@ +package com.egdroid.models.remote.movie.popularmovie + +data class MovieResponse( + val page: Int? = null, + val totalPages: Int? = null, + val results: List? = null, + val totalResults: Int? = null +) diff --git a/models/remotemodel/src/main/res/values/strings.xml b/models/remotemodel/src/main/res/values/strings.xml new file mode 100644 index 0000000..85af1b3 --- /dev/null +++ b/models/remotemodel/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + remotemodel + diff --git a/models/remotemodel/src/test/java/com/egdroid/models/remote/ExampleUnitTest.java b/models/remotemodel/src/test/java/com/egdroid/models/remote/ExampleUnitTest.java new file mode 100644 index 0000000..329b3b7 --- /dev/null +++ b/models/remotemodel/src/test/java/com/egdroid/models/remote/ExampleUnitTest.java @@ -0,0 +1,17 @@ +package com.egdroid.models.remote; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see Testing documentation + */ +public class ExampleUnitTest { + @Test + public void addition_isCorrect() { + assertEquals(4, 2 + 2); + } +} \ No newline at end of file diff --git a/models/uimodel/.gitignore b/models/uimodel/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/models/uimodel/.gitignore @@ -0,0 +1 @@ +/build diff --git a/models/uimodel/build.gradle b/models/uimodel/build.gradle new file mode 100644 index 0000000..4db41c0 --- /dev/null +++ b/models/uimodel/build.gradle @@ -0,0 +1,13 @@ +apply plugin: 'com.android.library' +apply from: "$project.rootDir/tools/gradle/script/quality.gradle" +apply from: "$project.rootDir/tools/gradle/base.gradle" + +android { + buildTypes { + release { + minifyEnabled true + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + +} diff --git a/models/uimodel/consumer-rules.pro b/models/uimodel/consumer-rules.pro new file mode 100644 index 0000000..e69de29 diff --git a/models/uimodel/proguard-rules.pro b/models/uimodel/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/models/uimodel/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/models/uimodel/src/androidTest/java/com/egdroid/models/ExampleInstrumentedTest.kt b/models/uimodel/src/androidTest/java/com/egdroid/models/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..ed7fd2c --- /dev/null +++ b/models/uimodel/src/androidTest/java/com/egdroid/models/ExampleInstrumentedTest.kt @@ -0,0 +1,22 @@ +package com.egdroid.models + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.platform.app.InstrumentationRegistry +import org.junit.Assert.assertEquals +import org.junit.Test +import org.junit.runner.RunWith + +/** + * 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.getInstrumentation().targetContext + assertEquals("com.egdroid.models.test", appContext.packageName) + } +} diff --git a/models/uimodel/src/main/AndroidManifest.xml b/models/uimodel/src/main/AndroidManifest.xml new file mode 100644 index 0000000..549152b --- /dev/null +++ b/models/uimodel/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + diff --git a/models/uimodel/src/main/res/values/strings.xml b/models/uimodel/src/main/res/values/strings.xml new file mode 100644 index 0000000..edbd4f8 --- /dev/null +++ b/models/uimodel/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + uimodel + diff --git a/models/uimodel/src/test/java/com/egdroid/models/ExampleUnitTest.kt b/models/uimodel/src/test/java/com/egdroid/models/ExampleUnitTest.kt new file mode 100644 index 0000000..c1df2ae --- /dev/null +++ b/models/uimodel/src/test/java/com/egdroid/models/ExampleUnitTest.kt @@ -0,0 +1,16 @@ +package com.egdroid.models + +import org.junit.Assert.assertEquals +import org.junit.Test + +/** + * 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/presentation/popularmoviespresentation/.gitignore b/presentation/popularmoviespresentation/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/presentation/popularmoviespresentation/.gitignore @@ -0,0 +1 @@ +/build diff --git a/presentation/popularmoviespresentation/build.gradle b/presentation/popularmoviespresentation/build.gradle new file mode 100644 index 0000000..a00aa70 --- /dev/null +++ b/presentation/popularmoviespresentation/build.gradle @@ -0,0 +1,16 @@ +apply plugin: 'com.android.library' +apply from: "$project.rootDir/tools/gradle/script/quality.gradle" +apply from: "$project.rootDir/tools/gradle/base.gradle" + +android { + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + api project(":features:popularmovies") +} diff --git a/presentation/popularmoviespresentation/consumer-rules.pro b/presentation/popularmoviespresentation/consumer-rules.pro new file mode 100644 index 0000000..e69de29 diff --git a/presentation/popularmoviespresentation/proguard-rules.pro b/presentation/popularmoviespresentation/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/presentation/popularmoviespresentation/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/presentation/popularmoviespresentation/src/androidTest/java/com/egdroid/presentation/popularmoviespresentation/ExampleInstrumentedTest.kt b/presentation/popularmoviespresentation/src/androidTest/java/com/egdroid/presentation/popularmoviespresentation/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..b0ff535 --- /dev/null +++ b/presentation/popularmoviespresentation/src/androidTest/java/com/egdroid/presentation/popularmoviespresentation/ExampleInstrumentedTest.kt @@ -0,0 +1,22 @@ +package com.egdroid.presentation.popularmoviespresentation + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.platform.app.InstrumentationRegistry +import org.junit.Assert.assertEquals +import org.junit.Test +import org.junit.runner.RunWith + +/** + * 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.getInstrumentation().targetContext + assertEquals("com.egdroid.presentation.popularmoviespresentation.test", appContext.packageName) + } +} diff --git a/presentation/popularmoviespresentation/src/main/AndroidManifest.xml b/presentation/popularmoviespresentation/src/main/AndroidManifest.xml new file mode 100644 index 0000000..50c7d0c --- /dev/null +++ b/presentation/popularmoviespresentation/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + diff --git a/presentation/popularmoviespresentation/src/main/java/com/egdroid/presentation/popularmoviespresentation/PopularMoviePresentationFactory.kt b/presentation/popularmoviespresentation/src/main/java/com/egdroid/presentation/popularmoviespresentation/PopularMoviePresentationFactory.kt new file mode 100644 index 0000000..ca7d0dd --- /dev/null +++ b/presentation/popularmoviespresentation/src/main/java/com/egdroid/presentation/popularmoviespresentation/PopularMoviePresentationFactory.kt @@ -0,0 +1,15 @@ +package com.egdroid.presentation.popularmoviespresentation + +import android.content.Context +import com.egdroid.features.popularmovies.usecase.PopularMoviesUseCaseFactory +import com.egdroid.mapper.MapperFactory +import com.egdroid.presentation.popularmoviespresentation.popularmovies.PopularMoviesViewModel + +object PopularMoviePresentationFactory { + + fun providePopularMoviesViewModel(context: Context): PopularMoviesViewModel { + return PopularMoviesViewModel( + PopularMoviesUseCaseFactory.providePopularMoviesUseCase(context), + MapperFactory.providePopularMovieMapper()) + } +} \ No newline at end of file diff --git a/presentation/popularmoviespresentation/src/main/java/com/egdroid/presentation/popularmoviespresentation/popularmovies/PopularMoviesViewModel.kt b/presentation/popularmoviespresentation/src/main/java/com/egdroid/presentation/popularmoviespresentation/popularmovies/PopularMoviesViewModel.kt new file mode 100644 index 0000000..340a79e --- /dev/null +++ b/presentation/popularmoviespresentation/src/main/java/com/egdroid/presentation/popularmoviespresentation/popularmovies/PopularMoviesViewModel.kt @@ -0,0 +1,33 @@ +package com.egdroid.presentation.popularmoviespresentation.popularmovies + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.egdroid.features.popularmovies.usecase.PopularMovieUseCase +import com.egdroid.mapper.MovieMapper +import com.egdroid.models.popularmovies.MovieUi +import io.reactivex.disposables.CompositeDisposable + +class PopularMoviesViewModel(private val popularMovieUseCase: PopularMovieUseCase, + private val mapper: MovieMapper) : ViewModel() { + + private var disposable: CompositeDisposable = CompositeDisposable() + + fun getMovies(): LiveData> { + val movies = MutableLiveData>() + disposable.add(popularMovieUseCase.popularmovies + .subscribe( + { movies.value = mapper.mapMovieEntityToMovieUi(it) }, + { movies.value = null }, + {} + )) + + return movies + } + + override fun onCleared() { + super.onCleared() + disposable.clear() + } + +} \ No newline at end of file diff --git a/presentation/popularmoviespresentation/src/main/res/values/strings.xml b/presentation/popularmoviespresentation/src/main/res/values/strings.xml new file mode 100644 index 0000000..cca7901 --- /dev/null +++ b/presentation/popularmoviespresentation/src/main/res/values/strings.xml @@ -0,0 +1,8 @@ + + popularmoviespresentation + + + Hello blank fragment + popular movie image + Empty movies list + diff --git a/presentation/popularmoviespresentation/src/test/java/com/egdroid/presentation/popularmoviespresentation/ExampleUnitTest.kt b/presentation/popularmoviespresentation/src/test/java/com/egdroid/presentation/popularmoviespresentation/ExampleUnitTest.kt new file mode 100644 index 0000000..9b3ba98 --- /dev/null +++ b/presentation/popularmoviespresentation/src/test/java/com/egdroid/presentation/popularmoviespresentation/ExampleUnitTest.kt @@ -0,0 +1,16 @@ +package com.egdroid.presentation.popularmoviespresentation + +import org.junit.Assert.assertEquals +import org.junit.Test + +/** + * 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/settings.gradle b/settings.gradle index 9d78681..e379f23 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,2 +1,5 @@ -include ':app' -rootProject.name='AnotherMovieApp' +include ':app', ':common', ':models:remotemodel', ':models:localmodel', ':models:datasourcemodel', + 'models:uimodel','models:entitymodel', + ':features:popularmovies', ':presentation:popularmoviespresentation', + ':features:upcomingmovies', ':datasource:local', ':datasource:remote', ':models:mapper' +rootProject.name = 'AnotherMovieApp' diff --git a/tools/gradle/base.gradle b/tools/gradle/base.gradle new file mode 100644 index 0000000..dd104a9 --- /dev/null +++ b/tools/gradle/base.gradle @@ -0,0 +1,99 @@ +apply plugin: 'kotlin-android-extensions' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-kapt' + +android { + + compileSdkVersion deps.build.compileSdkVersion + + defaultConfig { + + minSdkVersion deps.build.minSdkVersion + targetSdkVersion deps.build.targetSdkVersion + versionCode deps.build.versionCode + versionName deps.build.versionName + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + consumerProguardFiles 'consumer-rules.pro' + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } +} + +dependencies { + //UI + implementation deps.support.design + implementation deps.support.recyclerview + implementation deps.support.superRecyclerView + implementation deps.support.constraintLayout + + // Arch Component + implementation deps.architecturecomponents.lifecycles + implementation deps.architecturecomponents.room + implementation deps.architecturecomponents.room_kotlin + kapt deps.architecturecomponents.room_compiler + + // Rx + api deps.rx.java + api deps.rx.relay + api deps.rx.android + api deps.rx.binding + api deps.rx.retrofitAdapter + api deps.rx.roomRxJava + + // Dependency Injection + api deps.dependencyInjection.dagger + api deps.dependencyInjection.daggerSupportAndroid + kapt deps.dependencyInjection.daggerCompiler + kapt deps.dependencyInjection.daggerAndroidCompiler + + // View Binding + api deps.viewBinding.butterknife + kapt deps.viewBinding.butterknifeCompiler + + // Images + api deps.image.glide + kapt deps.image.glideCompiler + + // Network + implementation deps.network.retrofit + implementation deps.network.retrofitGsonConverter + implementation deps.network.okhttpLogging + + // Log + implementation deps.log.timber + debugImplementation deps.log.leakCanaryDebug + releaseImplementation deps.log.leakCanaryRelease + + api deps.kotlin.kotlin + api deps.kotlin.kotlinCore + + // Testing + testImplementation deps.test.junit + androidTestImplementation deps.test.runner + androidTestImplementation deps.test.espresso + androidTestImplementation deps.test.robolectric + androidTestImplementation deps.test.mockito + androidTestImplementation deps.test.powermock_mockito + androidTestImplementation deps.test.powermock_easymock + androidTestImplementation deps.test.powermock_reflect + androidTestImplementation deps.test.powermock_junit4 + androidTestImplementation deps.test.powermock_junit4_rule + androidTestImplementation deps.test.powermock_classloading + + implementation fileTree(dir: 'libs', include: ['*.jar']) + configurations.all { + resolutionStrategy { + force deps.support.annotations + } + resolutionStrategy.eachDependency { details -> + if (details.requested.group == 'com.android.support' + && !details.requested.name.contains('multidex')) { + details.useVersion deps.versions.support + } + } + } +} \ No newline at end of file diff --git a/tools/gradle/dependencies.gradle b/tools/gradle/dependencies.gradle index 0ac530c..c5c6a65 100644 --- a/tools/gradle/dependencies.gradle +++ b/tools/gradle/dependencies.gradle @@ -22,6 +22,10 @@ def versions = [ powermock : '1.6.6', mockito : '1.9.5', robolectric: '3.8', + kotlinCore : '1.1.0', + kotlin : '1.3.50', + okhttpLogging : '3.12.0', + superRecyclerView : '1.1.4' ] def support = [ @@ -29,6 +33,7 @@ def support = [ design : "com.android.support:design:${versions.support}", recyclerview : "com.android.support:recyclerview-v7:${versions.support}", constraintLayout: 'com.android.support.constraint:constraint-layout:1.0.2', + superRecyclerView: "com.malinskiy:superrecyclerview:${versions.superRecyclerView}" ] def rx = [ @@ -37,11 +42,13 @@ def rx = [ android : "io.reactivex.rxjava2:rxandroid:2.0.1", relay : "com.jakewharton.rxrelay2:rxrelay:2.0.0", retrofitAdapter: "com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0", + roomRxJava: "android.arch.persistence.room:rxjava2:1.1.1", ] def network = [ retrofit : "com.squareup.retrofit2:retrofit:${versions.retrofit}", - retrofitGsonConverter: "com.squareup.retrofit2:converter-gson:${versions.retrofit}" + retrofitGsonConverter: "com.squareup.retrofit2:converter-gson:${versions.retrofit}", + okhttpLogging: "com.squareup.okhttp3:logging-interceptor:${versions.okhttpLogging}" ] def dependencyInjection = [ @@ -63,6 +70,11 @@ def image = [ glideCompiler: "com.github.bumptech.glide:compiler:${versions.glide}" ] +def kotlin = [ + kotlinCore: "androidx.core:core-ktx:${versions.kotlinCore}", + kotlin : "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${versions.kotlin}" +] + def test = [ junit : "junit:junit:${versions.junit}", runner : "com.android.support.test:runner:${versions.testrunner}", @@ -80,6 +92,7 @@ def test = [ def architecturecomponents = [ lifecycles : "android.arch.lifecycle:common-java8:1.1.0", room : "androidx.room:room-runtime:${versions.room}", + room_kotlin : "androidx.room:room-ktx:${versions.room}", room_compiler: "androidx.room:room-compiler:${versions.room}", ] @@ -101,4 +114,5 @@ ext.deps = [ rx : rx, network : network, architecturecomponents: architecturecomponents, + kotlin: kotlin, ] \ No newline at end of file