diff --git a/app/build.gradle b/app/build.gradle index 38c9237..e94a6e1 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -9,11 +9,11 @@ def relKeyAlias = System.getenv("RELEASE_KEY_ALIAS") def keystorePath = System.getenv('PWD') + "/app/keystore.jks" def keystore = file(keystorePath).exists() ? file(keystorePath) : null android { - compileSdkVersion 31 + compileSdkVersion COMPILE_SDK_VERSION defaultConfig { applicationId "com.appttude.h_mal.farmr" - minSdkVersion 21 - targetSdkVersion 31 + minSdkVersion MIN_SDK_VERSION + targetSdkVersion TARGET_SDK_VERSION versionCode 2 versionName "2.0" testInstrumentationRunner 'com.appttude.h_mal.farmr.application.TestRunner' @@ -38,58 +38,46 @@ android { } dependencies { - implementation 'androidx.legacy:legacy-support-v4:1.0.0' - implementation 'androidx.vectordrawable:vectordrawable:1.0.0' - implementation 'androidx.core:core-ktx:1.1.0' - testImplementation 'junit:junit:4.12' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0' - implementation 'androidx.appcompat:appcompat:1.0.0' - implementation 'com.google.android.material:material:1.0.0' - implementation 'androidx.constraintlayout:constraintlayout:1.1.3' - implementation 'androidx.fragment:fragment-ktx:1.4.0' - implementation 'androidx.activity:activity-ktx:1.4.0' - implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.1' - implementation 'androidx.preference:preference:1.2.1' - implementation 'com.ajts.androidmads.SQLite2Excel:library:1.0.2' + implementation "androidx.legacy:legacy-support-v4:$LEGACY_SUPPORT_VERSION" + implementation "androidx.vectordrawable:vectordrawable:$VECTOR_DRAW_VERSION" + implementation "androidx.core:core-ktx:$CORE_KTX_VERSION" + implementation "androidx.appcompat:appcompat:$MATERIAL_VERSION" + implementation "com.google.android.material:material:$MATERIAL_VERSION" + implementation "androidx.constraintlayout:constraintlayout:$CONSTR_LAYOUT_VERSION" + implementation "androidx.fragment:fragment-ktx:$VIEW_KTX_VERSION" + implementation "androidx.activity:activity-ktx:$VIEW_KTX_VERSION" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$VIEWMODEL_VERSION" + implementation "androidx.preference:preference:$PREFERENCES_VERSION" + implementation "org.jetbrains.kotlin:kotlin-stdlib:$KOTLIN_VERSION" / * Unit testing * / - testImplementation 'junit:junit:4.13.2' - androidTestImplementation "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version" - testImplementation "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version" - implementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version" - androidTestImplementation 'androidx.test:core-ktx:1.4.0' - androidTestImplementation 'androidx.test:rules:1.4.0' + testImplementation "junit:junit:$JUNIT_VERSION" + androidTestImplementation "org.jetbrains.kotlin:kotlin-test-junit:$KOTLIN_VERSION" + testImplementation "org.jetbrains.kotlin:kotlin-test-junit:$KOTLIN_VERSION" + implementation "org.jetbrains.kotlin:kotlin-test:$KOTLIN_VERSION" + androidTestImplementation "androidx.test:core-ktx:$TEST_KTX_VERSION" + androidTestImplementation "androidx.test:rules:$TEST_KTX_VERSION" / * mockito and livedata testing * / - testImplementation 'org.mockito:mockito-inline:2.13.0' - testImplementation 'androidx.arch.core:core-testing:2.1.0' + testImplementation "org.mockito:mockito-inline:$MOKITO_INLINE_VERSION" + testImplementation "androidx.arch.core:core-testing:$CORE_TEST_VERSION" / * MockK * / - def mockk_ver = "1.10.5" - testImplementation "io.mockk:mockk:$mockk_ver" - androidTestImplementation "io.mockk:mockk-android:$mockk_ver" + testImplementation "io.mockk:mockk:$MOCKK_VERSION" + androidTestImplementation "io.mockk:mockk-android:$MOCKK_VERSION" / * Android Espresso * / - def testJunitVersion = "1.1.5" - def testRunnerVersion = "1.5.2" - def espressoVersion = "3.5.1" - androidTestImplementation "androidx.test.ext:junit:$testJunitVersion" - androidTestImplementation "androidx.test.espresso:espresso-core:$espressoVersion" - androidTestImplementation "androidx.test.espresso.idling:idling-concurrent:$espressoVersion" - implementation "androidx.test.espresso:espresso-idling-resource:$espressoVersion" - androidTestImplementation "androidx.test:runner:$testRunnerVersion" - androidTestImplementation "androidx.test.espresso:espresso-contrib:$espressoVersion" - androidTestImplementation "androidx.test.espresso:espresso-intents:$espressoVersion" - androidTestImplementation "org.hamcrest:hamcrest:2.2" + androidTestImplementation "androidx.test.ext:junit:$TEST_JUNIT_VERSION" + androidTestImplementation "androidx.test.espresso:espresso-core:$ESPRESSO_VERSION" + androidTestImplementation "androidx.test.espresso.idling:idling-concurrent:$ESPRESSO_VERSION" + implementation "androidx.test.espresso:espresso-idling-resource:$ESPRESSO_VERSION" + androidTestImplementation "androidx.test:runner:$TEST_RUNNER_VERSION" + androidTestImplementation "androidx.test.espresso:espresso-contrib:$ESPRESSO_VERSION" + androidTestImplementation "androidx.test.espresso:espresso-intents:$ESPRESSO_VERSION" + androidTestImplementation "org.hamcrest:hamcrest:$HAMCREST_VERSION" / * Room database * / - def room_version = "2.4.3" - implementation "androidx.room:room-runtime:$room_version" - kapt "androidx.room:room-compiler:$room_version" - implementation "androidx.room:room-ktx:$room_version" + implementation "androidx.room:room-runtime:$ROOM_VERSION" + kapt "androidx.room:room-compiler:$ROOM_VERSION" + implementation "androidx.room:room-ktx:$ROOM_VERSION" / *Kodein Dependency Injection * / - def kodein_version = "6.2.1" - implementation "org.kodein.di:kodein-di-generic-jvm:$kodein_version" - implementation "org.kodein.di:kodein-di-framework-android-x:$kodein_version" + implementation "org.kodein.di:kodein-di-generic-jvm:$KODEIN_VERSION" + implementation "org.kodein.di:kodein-di-framework-android-x:$KODEIN_VERSION" / * jxl * / - implementation 'net.sourceforge.jexcelapi:jxl:2.6.12' - / * Permissions dispatcher * / - def dispatcher_ver = "4.9.2" - implementation "com.github.permissions-dispatcher:permissionsdispatcher:${dispatcher_ver}" - kapt "com.github.permissions-dispatcher:permissionsdispatcher-processor:${dispatcher_ver}" + implementation "net.sourceforge.jexcelapi:jxl:$JEXCEL_VERSION" } diff --git a/app/src/androidTest/java/com/appttude/h_mal/farmr/ui/BaseTest.kt b/app/src/androidTest/java/com/appttude/h_mal/farmr/ui/BaseTest.kt index 8d4ebb8..151a2c1 100644 --- a/app/src/androidTest/java/com/appttude/h_mal/farmr/ui/BaseTest.kt +++ b/app/src/androidTest/java/com/appttude/h_mal/farmr/ui/BaseTest.kt @@ -14,7 +14,6 @@ import androidx.test.espresso.assertion.ViewAssertions import androidx.test.espresso.matcher.RootMatchers.withDecorView import androidx.test.espresso.matcher.ViewMatchers import androidx.test.platform.app.InstrumentationRegistry -import androidx.test.rule.GrantPermissionRule import com.appttude.h_mal.farmr.application.TestAppClass import com.appttude.h_mal.farmr.ui.utils.getShifts import kotlinx.coroutines.runBlocking @@ -36,9 +35,6 @@ open class BaseTest( private lateinit var testActivity: Activity private lateinit var decorView: View - @get:Rule - var permissionRule = GrantPermissionRule.grant(Manifest.permission.READ_EXTERNAL_STORAGE) - @Before open fun setUp() { val startIntent = diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 6fc2773..e984349 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -3,9 +3,6 @@ xmlns:tools="http://schemas.android.com/tools" package="com.appttude.h_mal.farmr"> - - - (R.layout.fragment_main), BackPr } productListView = view.findViewById(R.id.list_item_view) productListView.adapter = mAdapter - emptyView = view.findViewById(R.id.empty_view) + emptyView = view.findViewById(R.id.empty_view) mAdapter.registerAdapterDataObserver(object : AdapterDataObserver() { override fun onChanged() { @@ -114,16 +109,12 @@ class FragmentMain : BaseFragment(R.layout.fragment_main), BackPr } R.id.export_data -> { - if (checkStoragePermissions(activity)) { - AlertDialog.Builder(context) - .setTitle("Export?") - .setMessage("Exporting current filtered data. Continue?") - .setNegativeButton(android.R.string.cancel, null) - .setPositiveButton(android.R.string.ok) { _, _ -> exportData() } - .create().show() - } else { - displayToast("Storage permissions required") - } + AlertDialog.Builder(context) + .setTitle("Export?") + .setMessage("Exporting current filtered data. Continue?") + .setNegativeButton(android.R.string.cancel, null) + .setPositiveButton(android.R.string.ok) { _, _ -> exportData() } + .create().show() return true } @@ -175,13 +166,6 @@ class FragmentMain : BaseFragment(R.layout.fragment_main), BackPr } private fun exportData() { - val permission = - ActivityCompat.checkSelfPermission(requireActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE) - if (permission != PackageManager.PERMISSION_GRANTED) { - Toast.makeText(context, "Storage permissions not granted", Toast.LENGTH_SHORT).show() - return - } - val fileName = "shifthistory.xls" val file = File(requireContext().externalCacheDir, fileName) @@ -199,24 +183,6 @@ class FragmentMain : BaseFragment(R.layout.fragment_main), BackPr } - override fun onRequestPermissionsResult( - requestCode: Int, - permissions: Array, - grantResults: IntArray - ) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults) - println("request code$requestCode") - if (requestCode == MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE) { - if (grantResults.isNotEmpty() - && grantResults[0] == PackageManager.PERMISSION_GRANTED - ) { - exportDialog() - } else { - displayToast("Storage Permissions denied") - } - } - } - private fun exportDialog() { AlertDialog.Builder(context) .setTitle("Export?") @@ -225,22 +191,6 @@ class FragmentMain : BaseFragment(R.layout.fragment_main), BackPr .setPositiveButton(android.R.string.ok) { _, _ -> exportData() }.create().show() } - private fun checkStoragePermissions(activity: Activity?): Boolean { - var status = false - val permission = ActivityCompat.checkSelfPermission( - activity!!, - Manifest.permission.WRITE_EXTERNAL_STORAGE - ) - if (permission == PackageManager.PERMISSION_GRANTED) { - status = true - } - return status - } - - companion object { - const val MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE = 1 - } - override fun onBackPressed(): Boolean { requireContext().createDialog( title = "Leave?", diff --git a/app/src/main/java/com/appttude/h_mal/farmr/ui/MainActivity.kt b/app/src/main/java/com/appttude/h_mal/farmr/ui/MainActivity.kt index 2bb2763..0ae17b4 100644 --- a/app/src/main/java/com/appttude/h_mal/farmr/ui/MainActivity.kt +++ b/app/src/main/java/com/appttude/h_mal/farmr/ui/MainActivity.kt @@ -21,8 +21,6 @@ class MainActivity : BaseActivity() { toolbar = findViewById(R.id.toolbar) setSupportActionBar(toolbar) - verifyStoragePermissions(this) - val fragmentTransaction = supportFragmentManager.beginTransaction() fragmentTransaction.replace(R.id.container, FragmentMain()).addToBackStack("main").commit() } @@ -45,34 +43,4 @@ class MainActivity : BaseActivity() { } } } - - // Storage Permissions - private val REQUEST_EXTERNAL_STORAGE = 1 - private val PERMISSIONS_STORAGE = arrayOf( - Manifest.permission.READ_EXTERNAL_STORAGE, - Manifest.permission.WRITE_EXTERNAL_STORAGE - ) - - /** - * Checks if the app has permission to write to device storage - * - * If the app does not has permission then the user will be prompted to grant permissions - * - * @param activity - */ - fun verifyStoragePermissions(activity: Activity?) { - // Check if we have write permission - val permission = ActivityCompat.checkSelfPermission( - activity!!, - Manifest.permission.WRITE_EXTERNAL_STORAGE - ) - if (permission != PackageManager.PERMISSION_GRANTED) { - // We don't have permission so prompt the user - ActivityCompat.requestPermissions( - activity, - PERMISSIONS_STORAGE, - REQUEST_EXTERNAL_STORAGE - ) - } - } } \ No newline at end of file diff --git a/app/src/main/java/com/appttude/h_mal/farmr/viewmodel/MainViewModel.kt b/app/src/main/java/com/appttude/h_mal/farmr/viewmodel/MainViewModel.kt index 7929615..d63fca2 100644 --- a/app/src/main/java/com/appttude/h_mal/farmr/viewmodel/MainViewModel.kt +++ b/app/src/main/java/com/appttude/h_mal/farmr/viewmodel/MainViewModel.kt @@ -1,7 +1,5 @@ package com.appttude.h_mal.farmr.viewmodel -import android.Manifest.permission.WRITE_EXTERNAL_STORAGE -import androidx.annotation.RequiresPermission import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.Observer @@ -206,7 +204,6 @@ class MainViewModel( refreshLiveData() } - @RequiresPermission(WRITE_EXTERNAL_STORAGE) fun createExcelSheet(file: File): File? { val wbSettings = WorkbookSettings().apply { locale = Locale("en", "EN") diff --git a/build.gradle b/build.gradle index 4e3983e..4faecfe 100644 --- a/build.gradle +++ b/build.gradle @@ -2,16 +2,20 @@ buildscript { ext { - kotlin_version = '1.7.10' + kotlin_version = KOTLIN_VERSION } repositories { google() jcenter() + // releases + mavenCentral() + // snapshots + maven { url "https://oss.sonatype.org/content/repositories/snapshots/" } } dependencies { - classpath 'com.android.tools.build:gradle:7.4.1' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - + classpath "com.android.tools.build:gradle:$GRADLE_PLUGIN_VERSION" + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$KOTLIN_VERSION" + classpath "com.autonomousapps:dependency-analysis-gradle-plugin:$GRADLE_ANALYZE_VERSION" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } @@ -25,6 +29,8 @@ allprojects { } } +apply plugin: "com.autonomousapps.dependency-analysis" + task clean(type: Delete) { delete rootProject.buildDir } diff --git a/gradle.properties b/gradle.properties index 9e6fce1..1a2cbf3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,19 +1,37 @@ -# Project-wide Gradle settings. -# IDE (e.g. Android Studio) users: -# Gradle settings configured through the IDE *will override* -# any settings specified in this file. +# Plugin versions +LEGACY_SUPPORT_VERSION = 1.0.0 +VECTOR_DRAW_VERSION = 1.0.0 +CORE_KTX_VERSION = 1.1.0 +MATERIAL_VERSION = 1.0.0 +CONSTR_LAYOUT_VERSION = 1.1.3 +VIEW_KTX_VERSION = 1.4.0 +VIEWMODEL_VERSION = 2.4.1 +PREFERENCES_VERSION = 1.2.1 +MOKITO_INLINE_VERSION = 2.13.0 +CORE_TEST_VERSION = 2.1.0 +MOCKK_VERSION = 1.10.5 +TEST_JUNIT_VERSION = 1.1.5 +TEST_RUNNER_VERSION = 1.5.2 +ESPRESSO_VERSION = 3.5.1 +HAMCREST_VERSION = 2.2 +JEXCEL_VERSION = 2.6.12 +JUNIT_VERSION = 4.13.2 +KODEIN_VERSION = 6.2.1 +ROOM_VERSION = 2.4.3 +TEST_KTX_VERSION = 1.4.0 +GRADLE_PLUGIN_VERSION = 7.4.1 +KOTLIN_VERSION = 1.7.10 +GRADLE_ANALYZE_VERSION = 1.20.0 -# For more details on how to configure your build environment visit -# http://www.gradle.org/docs/current/userguide/build_environment.html +# Android configuration +COMPILE_SDK_VERSION = android-31 +TARGET_SDK_VERSION = 31 +MIN_SDK_VERSION = 21 -# Specifies the JVM arguments used for the daemon process. -# The setting is particularly useful for tweaking memory settings. -android.enableJetifier=true -android.useAndroidX=true -org.gradle.jvmargs=-Xmx1536m +# Gradle parameters +org.gradle.jvmargs = -Xmx1536m -# When configured, Gradle will run in incubating parallel mode. -# This option should only be used with decoupled projects. More details, visit -# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true +# AndroidX +android.useAndroidX = true +android.enableJetifier = true