diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index 1bec35e..a88ded0 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -1,8 +1,120 @@ + + + + + +
+ + + + xmlns:android + + ^$ + + + +
+
+ + + + xmlns:.* + + ^$ + + + BY_NAME + +
+
+ + + + .*:id + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:name + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + name + + ^$ + + + +
+
+ + + + style + + ^$ + + + +
+
+ + + + .* + + ^$ + + + BY_NAME + +
+
+ + + + .* + + http://schemas.android.com/apk/res/android + + + ANDROID_ATTRIBUTE_ORDER + +
+
+ + + + .* + + .* + + + BY_NAME + +
+
+
+
diff --git a/.idea/misc.xml b/.idea/misc.xml index 3484bf1..d5727af 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -8,7 +8,7 @@ - + diff --git a/app/build.gradle b/app/build.gradle index c8f3947..59c76f8 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -4,15 +4,18 @@ apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' +//kotlin kapt and navigation safeargs plugin +apply plugin: 'kotlin-kapt' + android { - compileSdkVersion 28 + compileSdkVersion 29 defaultConfig { applicationId "com.example.h_mal.myapplication" minSdkVersion 23 - targetSdkVersion 28 + targetSdkVersion 29 versionCode 1 versionName "1.0" - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildTypes { release { @@ -20,21 +23,50 @@ android { proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } + dataBinding { + enabled = true + } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" - implementation 'com.android.support:appcompat-v7:28.0.0' - implementation 'com.android.support.constraint:constraint-layout:1.1.3' + implementation 'androidx.appcompat:appcompat:1.1.0' + implementation 'androidx.core:core-ktx:1.1.0' + implementation 'androidx.constraintlayout:constraintlayout:1.1.3' + implementation 'androidx.legacy:legacy-support-v4:1.0.0' + implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.1.0' testImplementation 'junit:junit:4.12' - androidTestImplementation 'com.android.support.test:runner:1.0.2' - androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' - androidTestImplementation 'com.android.support.test:rules:1.0.2' - implementation 'com.android.support:cardview-v7:28.0.0' - implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0' - implementation 'com.squareup.retrofit2:converter-gson:2.3.0' - implementation 'com.squareup.retrofit2:retrofit:2.3.0' - implementation 'io.reactivex.rxjava2:rxjava:2.1.9' - implementation 'io.reactivex.rxjava2:rxandroid:2.0.2' + androidTestImplementation 'androidx.test:runner:1.2.0' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' + + //Retrofit and GSON + implementation 'com.squareup.retrofit2:retrofit:2.6.0' + implementation 'com.squareup.retrofit2:converter-gson:2.6.0' + + //Kotlin Coroutines + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.0" + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.0" + + // ViewModel and LiveData + implementation "androidx.lifecycle:lifecycle-extensions:2.1.0" + + //New Material Design + implementation 'com.google.android.material:material:1.1.0-alpha10' + + //Kodein Dependency Injection + implementation "org.kodein.di:kodein-di-generic-jvm:6.2.1" + implementation "org.kodein.di:kodein-di-framework-android-x:6.2.1" + + //Android Room + implementation "androidx.room:room-runtime:2.2.0-rc01" + implementation "androidx.room:room-ktx:2.2.0-rc01" + kapt "androidx.room:room-compiler:2.2.0-rc01" + + implementation 'com.xwray:groupie:2.3.0' + implementation 'com.xwray:groupie-kotlin-android-extensions:2.3.0' + implementation 'com.xwray:groupie-databinding:2.3.0' + + + } diff --git a/app/src/androidTest/java/com/example/h_mal/myapplication/ui/MainActivityTest.kt b/app/src/androidTest/java/com/example/h_mal/myapplication/ui/MainActivityTest.kt new file mode 100644 index 0000000..b361118 --- /dev/null +++ b/app/src/androidTest/java/com/example/h_mal/myapplication/ui/MainActivityTest.kt @@ -0,0 +1,14 @@ +package com.example.h_mal.myapplication.ui + + + +import androidx.test.filters.LargeTest +import androidx.test.runner.AndroidJUnit4 +import org.junit.runner.RunWith + +@LargeTest +@RunWith(AndroidJUnit4::class) +class MainActivityTest { + + +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 64c7128..5258d87 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -6,6 +6,7 @@ > + suspend fun getData() : Response> + } \ No newline at end of file diff --git a/app/src/main/java/com/example/h_mal/myapplication/Api/NetworkConnectionInterceptor.kt b/app/src/main/java/com/example/h_mal/myapplication/Api/NetworkConnectionInterceptor.kt new file mode 100644 index 0000000..e5c4e80 --- /dev/null +++ b/app/src/main/java/com/example/h_mal/myapplication/Api/NetworkConnectionInterceptor.kt @@ -0,0 +1,37 @@ +package com.example.h_mal.myapplication.Api + +import android.content.Context +import android.net.ConnectivityManager +import android.net.NetworkCapabilities +import okhttp3.Interceptor +import okhttp3.Response +import java.io.IOException + +class NetworkConnectionInterceptor( + context: Context +): Interceptor { + + private val applicationContext = context.applicationContext + + override fun intercept(chain: Interceptor.Chain): Response { + if (!isInternetAvailable()) + throw IOException("Make sure you have an active data connection") + return chain.proceed(chain.request()) + } + + private fun isInternetAvailable(): Boolean { + var result = false + val connectivityManager = + applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + connectivityManager?.let { + it.getNetworkCapabilities(connectivityManager.activeNetwork)?.apply { + result = when { + hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true + hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true + else -> false + } + } + } + return result + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/h_mal/myapplication/Api/SafeApiRequest.kt b/app/src/main/java/com/example/h_mal/myapplication/Api/SafeApiRequest.kt new file mode 100644 index 0000000..ac34ab0 --- /dev/null +++ b/app/src/main/java/com/example/h_mal/myapplication/Api/SafeApiRequest.kt @@ -0,0 +1,29 @@ +package com.example.h_mal.myapplication.Api + +import org.json.JSONException +import org.json.JSONObject +import retrofit2.Response +import java.io.IOException + +abstract class SafeApiRequest { + + suspend fun apiRequest(call: suspend () -> Response) : T{ + val response = call.invoke() + if(response.isSuccessful){ + return response.body()!! + }else{ + val error = response.errorBody()?.string() + + val message = StringBuilder() + error?.let{ + try{ + message.append(JSONObject(it).getString("message")) + }catch(e: JSONException){ } + message.append("\n") + } + message.append("Error Code: ${response.code()}") + throw IOException(message.toString()) + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/example/h_mal/myapplication/AppClass.kt b/app/src/main/java/com/example/h_mal/myapplication/AppClass.kt new file mode 100644 index 0000000..581d0bd --- /dev/null +++ b/app/src/main/java/com/example/h_mal/myapplication/AppClass.kt @@ -0,0 +1,37 @@ +package com.example.h_mal.myapplication + +import android.app.Application +import com.example.h_mal.myapplication.Api.GetData +import com.example.h_mal.myapplication.Api.NetworkConnectionInterceptor +import com.example.h_mal.myapplication.db.AppDatabase +import com.example.h_mal.myapplication.repository.Repository +import com.example.h_mal.myapplication.ui.DefaultViewFactory +import org.kodein.di.Kodein +import org.kodein.di.KodeinAware +import org.kodein.di.android.x.androidXModule +import org.kodein.di.generic.bind +import org.kodein.di.generic.instance +import org.kodein.di.generic.provider +import org.kodein.di.generic.singleton + +class AppClass : Application(), KodeinAware{ + + + override val kodein + = Kodein.lazy{ import(androidXModule(this@AppClass)) + + bind() from singleton { NetworkConnectionInterceptor(instance()) } + bind() from singleton { GetData(instance()) } + bind() from singleton { AppDatabase(instance()) } + bind() from singleton { + Repository( + instance(), + instance() + ) + } + bind() from provider { DefaultViewFactory(instance()) } + + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/example/h_mal/myapplication/db/AppDatabse.kt b/app/src/main/java/com/example/h_mal/myapplication/db/AppDatabse.kt new file mode 100644 index 0000000..02bda83 --- /dev/null +++ b/app/src/main/java/com/example/h_mal/myapplication/db/AppDatabse.kt @@ -0,0 +1,36 @@ +package com.example.h_mal.myapplication.db + +import android.content.Context +import androidx.room.Database +import androidx.room.Room +import androidx.room.RoomDatabase +import com.example.h_mal.myapplication.model.Repo + +@Database( + entities = [Repo::class], + version = 1 +) +abstract class AppDatabase : RoomDatabase() { + + abstract fun getRepoDao() : RepoDao + + companion object { + + @Volatile + private var instance: AppDatabase? = null + private val LOCK = Any() + + operator fun invoke(context: Context) = instance ?: synchronized(LOCK) { + instance ?: buildDatabase(context).also { + instance = it + } + } + + private fun buildDatabase(context: Context) = + Room.databaseBuilder( + context.applicationContext, + AppDatabase::class.java, + "MyDatabase.db" + ).build() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/h_mal/myapplication/db/RepoDao.kt b/app/src/main/java/com/example/h_mal/myapplication/db/RepoDao.kt new file mode 100644 index 0000000..c385995 --- /dev/null +++ b/app/src/main/java/com/example/h_mal/myapplication/db/RepoDao.kt @@ -0,0 +1,19 @@ +package com.example.h_mal.myapplication.db + +import androidx.lifecycle.LiveData +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import com.example.h_mal.myapplication.model.Repo + +@Dao +interface RepoDao { + + @Insert(onConflict = OnConflictStrategy.REPLACE) + fun saveAllRepos(repos : List) + + @Query("SELECT * FROM Repo") + fun getRepos() : LiveData> + +} \ No newline at end of file diff --git a/app/src/main/java/com/example/h_mal/myapplication/model/Repo.kt b/app/src/main/java/com/example/h_mal/myapplication/model/Repo.kt index bb11b0f..e7ed445 100644 --- a/app/src/main/java/com/example/h_mal/myapplication/model/Repo.kt +++ b/app/src/main/java/com/example/h_mal/myapplication/model/Repo.kt @@ -1,8 +1,13 @@ package com.example.h_mal.myapplication.model +import androidx.room.Entity +import androidx.room.PrimaryKey import com.google.gson.annotations.SerializedName +@Entity data class Repo( + @PrimaryKey + var id: Int? = null, var name: String? = null, var description : String? = null, var language : String? = null, diff --git a/app/src/main/java/com/example/h_mal/myapplication/repository/Repository.kt b/app/src/main/java/com/example/h_mal/myapplication/repository/Repository.kt new file mode 100644 index 0000000..bd6584e --- /dev/null +++ b/app/src/main/java/com/example/h_mal/myapplication/repository/Repository.kt @@ -0,0 +1,54 @@ +package com.example.h_mal.myapplication.repository + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import com.example.h_mal.myapplication.Api.GetData +import com.example.h_mal.myapplication.Api.SafeApiRequest +import com.example.h_mal.myapplication.db.AppDatabase +import com.example.h_mal.myapplication.model.Repo +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import java.lang.Exception +import java.time.LocalDateTime +import java.time.temporal.ChronoUnit + +class Repository( + private val api: GetData, + private val db: AppDatabase +):SafeApiRequest(){ + + private val repos = MutableLiveData>() + + init { + repos.observeForever { + saveRepos(it) + } + } + + suspend fun getRepos(): LiveData> { + return withContext(Dispatchers.IO) { + fetchRepos() + db.getRepoDao().getRepos() + } + } + + private suspend fun fetchRepos() { + try { + val response = apiRequest { api.getData() } + repos.postValue(response) + } catch (e: Exception) { + e.printStackTrace() + } + + } + + + + private fun saveRepos(repos: List) { + CoroutineScope(Dispatchers.IO).launch{ + db.getRepoDao().saveAllRepos(repos) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/h_mal/myapplication/ui/DefaultViewFactory.kt b/app/src/main/java/com/example/h_mal/myapplication/ui/DefaultViewFactory.kt new file mode 100644 index 0000000..f83a300 --- /dev/null +++ b/app/src/main/java/com/example/h_mal/myapplication/ui/DefaultViewFactory.kt @@ -0,0 +1,15 @@ +package com.example.h_mal.myapplication.ui + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import com.example.h_mal.myapplication.repository.Repository + +@Suppress("UNCHECKED_CAST") +class DefaultViewFactory( + private val repository: Repository +) : ViewModelProvider.NewInstanceFactory(){ + + override fun create(modelClass: Class): T { + return MainViewModel(repository) as T + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/h_mal/myapplication/ui/ListViewAdapter.kt b/app/src/main/java/com/example/h_mal/myapplication/ui/ListViewAdapter.kt index ef4a95e..959a82f 100644 --- a/app/src/main/java/com/example/h_mal/myapplication/ui/ListViewAdapter.kt +++ b/app/src/main/java/com/example/h_mal/myapplication/ui/ListViewAdapter.kt @@ -1,5 +1,6 @@ package com.example.h_mal.myapplication.ui + import android.content.Context import android.content.Intent import android.content.Intent.FLAG_ACTIVITY_NEW_TASK @@ -50,7 +51,9 @@ class ListViewAdapter(context: Context, objects: MutableList) : //language text and corresponding colour according to github is applied view.lang?.text = item.language - getColor(item.language)?.let { it1 -> view.lang_col.setCardBackgroundColor(it1) } + + + getColor(item.language)?.let { it1 -> view.lang_col.setBackgroundColor(it1) } }else{ //language was null therefore view to be hidden view.lang_layout.visibility = View.GONE diff --git a/app/src/main/java/com/example/h_mal/myapplication/ui/MainActivity.kt b/app/src/main/java/com/example/h_mal/myapplication/ui/MainActivity.kt index b62603f..7b69217 100644 --- a/app/src/main/java/com/example/h_mal/myapplication/ui/MainActivity.kt +++ b/app/src/main/java/com/example/h_mal/myapplication/ui/MainActivity.kt @@ -1,46 +1,77 @@ package com.example.h_mal.myapplication.ui -import android.support.v7.app.AppCompatActivity +import androidx.databinding.DataBindingUtil import android.os.Bundle -import android.support.v4.widget.SwipeRefreshLayout import android.view.Menu import android.view.View -import android.widget.SearchView -import com.example.h_mal.myapplication.Api.GetData +import androidx.appcompat.app.AppCompatActivity +import androidx.appcompat.widget.SearchView +import androidx.databinding.ViewDataBinding +import androidx.lifecycle.Observer +import androidx.lifecycle.ViewModelProviders +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import com.example.h_mal.myapplication.R -import com.example.h_mal.myapplication.model.Repo +import com.example.h_mal.myapplication.databinding.ActivityMainBinding import kotlinx.android.synthetic.main.activity_main.* -import io.reactivex.disposables.CompositeDisposable -import retrofit2.converter.gson.GsonConverterFactory -import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory -import retrofit2.Retrofit - -import io.reactivex.schedulers.Schedulers -import io.reactivex.android.schedulers.AndroidSchedulers -import io.reactivex.observers.DisposableObserver +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import org.kodein.di.KodeinAware +import org.kodein.di.android.kodein +import org.kodein.di.generic.instance -class MainActivity : AppCompatActivity() { +class MainActivity : AppCompatActivity(), KodeinAware { lateinit var searchView: SearchView - lateinit var myCompositeDisposable: CompositeDisposable + lateinit var adapterLV: ListViewAdapter - val urlString = "https://api.github.com/orgs/square/" + override val kodein by kodein() + + private val factory: DefaultViewFactory by instance() + + private lateinit var viewModel: MainViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) - spinner.visibility = View.VISIBLE - - myCompositeDisposable = CompositeDisposable() - - //begin populating list - loadData() + viewModel = ViewModelProviders.of(this,factory).get(MainViewModel::class.java) + bindUI() //set a listener for the swipe to refresh swipe_refresh.setOnRefreshListener(swipeRefreshListener) } + private fun bindUI() = CoroutineScope(Dispatchers.Main).launch { + spinner.visibility = View.VISIBLE + + viewModel.repos.await().observe(this@MainActivity, Observer { + spinner.visibility = View.GONE + + if (it.isEmpty()){ + empty_view.visibility = View.VISIBLE + searchView.setOnQueryTextListener(null) + }else{ + empty_view.visibility = View.GONE + + adapterLV = ListViewAdapter(baseContext, it.toMutableList()) + //apply adapter to listview + list_view.adapter = adapterLV + + list_view.setOnItemClickListener { parent, view, position, id -> + adapterLV.openLink(position) + } + + //search view has its query change listener applied + searchView.setOnQueryTextListener(queryListener) + } + + + }) + } + + + //implement search interface in the menu override fun onCreateOptionsMenu(menu: Menu?): Boolean { //inflate custom menu as our menu @@ -53,92 +84,27 @@ class MainActivity : AppCompatActivity() { return true } - override fun onDestroy() { - super.onDestroy() - - myCompositeDisposable?.clear() - } - val swipeRefreshListener = SwipeRefreshLayout.OnRefreshListener{ //populate list when pulling to refresh -// callData() - loadData() + bindUI() + } - fun loadData(){ - //clear list before populating - list_view.adapter = null + val queryListener = object : SearchView.OnQueryTextListener{ - val requestInterface = Retrofit.Builder() - .baseUrl(urlString) - .addConverterFactory(GsonConverterFactory.create()) - .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) - .build().create(GetData::class.java) + override fun onQueryTextSubmit(query: String?): Boolean { - myCompositeDisposable.add(requestInterface.getData() - .observeOn(AndroidSchedulers.mainThread()) - .subscribeOn(Schedulers.io()) - .subscribeWith(object : DisposableObserver>() { - override fun onNext(t: List) { - handleResponse(t) - } - - override fun onComplete() { - - } - - override fun onError(e: Throwable) { - handleError() - } - })) - } - - private fun handleResponse(objectList: List) { - - spinner.visibility = View.GONE - - //if swipe refresh is refreshing then stop - swipe_refresh.isRefreshing = false - - if (objectList.isNotEmpty()){ - //list is not empty - empty_view.visibility = View.GONE - //custom list view adapter created - val adapterLV = ListViewAdapter(baseContext, objectList.toMutableList()) - //apply adapter to listview - list_view.adapter = adapterLV - - list_view.setOnItemClickListener { parent, view, position, id -> - adapterLV.openLink(position) - } - - //search view has its query change listener applied - searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener{ - - override fun onQueryTextSubmit(query: String?): Boolean { - - return true - } - - //as the test is changed the list is filtered - override fun onQueryTextChange(newText: String?): Boolean { - //filter list function - adapterLV.filter.filter(newText) - - return true - } - }) + return true } + //as the test is changed the list is filtered + override fun onQueryTextChange(newText: String?): Boolean { + //filter list function + adapterLV.filter.filter(newText) + + return true + } } - fun handleError(){ - //if swipe refresh is refreshing then stop - swipe_refresh.isRefreshing = false - //list is empty - empty_view.visibility = View.VISIBLE - //progress bar hidden - spinner.visibility = View.GONE - } } diff --git a/app/src/main/java/com/example/h_mal/myapplication/ui/MainViewModel.kt b/app/src/main/java/com/example/h_mal/myapplication/ui/MainViewModel.kt new file mode 100644 index 0000000..8c9b738 --- /dev/null +++ b/app/src/main/java/com/example/h_mal/myapplication/ui/MainViewModel.kt @@ -0,0 +1,16 @@ +package com.example.h_mal.myapplication.ui + +import androidx.lifecycle.ViewModel +import com.example.h_mal.myapplication.repository.Repository +import kotlinx.coroutines.CoroutineStart +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.async + +class MainViewModel(val repository : Repository) : ViewModel(){ + + val repos by lazy{ + GlobalScope.async(start = CoroutineStart.LAZY) { + repository.getRepos() + } + } +} \ 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 c6a1ef3..a91d477 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,59 +1,70 @@ - + xmlns:app="http://schemas.android.com/apk/res-auto"> - + + + + - - + + android:layout_height="match_parent"> - + - + - + app:layout_constraintLeft_toLeftOf="parent" + app:layout_constraintRight_toRightOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent"> - + + + + + - + android:id="@+id/spinner" + app:layout_constraintLeft_toLeftOf="parent" + app:layout_constraintRight_toRightOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent"/> + - - - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/repo_list_item.xml b/app/src/main/res/layout/repo_list_item.xml index 04f1bef..8f098f7 100644 --- a/app/src/main/res/layout/repo_list_item.xml +++ b/app/src/main/res/layout/repo_list_item.xml @@ -6,7 +6,7 @@ xmlns:tools="http://schemas.android.com/tools"> - android:layout_marginTop="6dp" android:gravity="right"> - - + \ No newline at end of file diff --git a/app/src/main/res/menu/menu.xml b/app/src/main/res/menu/menu.xml index 43c4bf7..078be94 100644 --- a/app/src/main/res/menu/menu.xml +++ b/app/src/main/res/menu/menu.xml @@ -3,5 +3,6 @@ + app:showAsAction="collapseActionView|ifRoom" + app:actionViewClass="androidx.appcompat.widget.SearchView"/> \ No newline at end of file diff --git a/build.gradle b/build.gradle index bc938ee..58efbe3 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:3.4.1' + classpath 'com.android.tools.build:gradle:3.5.3' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/gradle.properties b/gradle.properties index 85be9ea..3d8ce0c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,3 +13,5 @@ org.gradle.jvmargs=-Xmx1536m # org.gradle.parallel=true # Kotlin code style for this project: "official" or "obsolete": kotlin.code.style=official +android.useAndroidX=true +android.enableJetifier=true diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index d39cfb0..b2eb118 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Tue Dec 03 01:40:10 AEDT 2019 +#Fri Jan 24 13:56:41 UTC 2020 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip