updated template after four sprints at runtime

This commit is contained in:
Maxim Bachinsky 2020-09-29 19:35:15 +03:00
parent 7dcf10af59
commit 31ca21ea54
28 changed files with 190 additions and 156 deletions

@ -1 +1 @@
Subproject commit 7850b7f0cdd5d261e532d265b33464a9140a6d45
Subproject commit be9bbb971e0864178ebf6d2f22bcd40d7fecd24e

@ -1 +1 @@
Subproject commit 73453070050363058cd05648362723b44b30d9a6
Subproject commit 09061c1bcfd951127f1a62c25990a5c9d9cbbbce

View File

@ -2,74 +2,42 @@ plugins {
id(Plugins.ANDROID_APP_PLUGIN_WITH_DEFAULT_CONFIG)
id(Plugins.FIREBASE_CRASH)
id(Plugins.GOOGLE_SERVICES)
id(Plugins.LICENCE_PLUGIN)
}
val customEndpoint: String? = System.getenv("CUSTOM_ENDPOINT")?.takeIf(String::isNotBlank)
val customEndpoint: String? = Environment.ENDPOINT.getenv()?.takeIf(String::isNotBlank)
android {
signingConfigs {
addConfig(SigningConfig.Test)
addConfig(SigningConfig.Prod)
}
configureSigningConfig(this@Build_gradle::file)
defaultConfig {
applicationId = AndroidConfig.TEST_APP_ID
signingConfig = signingConfigs.getByName(SigningConfig.Test.name)
with(defaultConfig) {
applicationId = Environment.APP_ID.getenv() ?: AndroidConfig.TEST_APP_ID
signingConfig = signingConfigs.getByName(SigningConfig.CONFIG_NAME)
}
firebaseCrashlytics {
mappingFileUploadEnabled = true
}
buildTypes {
addBuildType(BuildType.Debug)
addBuildType(BuildType.Release)
}
addBuildType(BuildType.Debug, buildScriptDir = buildScriptDir)
addBuildType(BuildType.Release, buildScriptDir = buildScriptDir)
flavorDimensions(
ProguardFlavour.DIMENSION_NAME,
ApiFlavour.DIMENSION_NAME,
SSLPinningFlavour.DIMENSION_NAME,
TestPanelFlavour.DIMENSION_NAME
)
addFlavour(ApiFlavour.MockDev, customEndpoint)
addFlavour(ApiFlavour.TouchinTest, customEndpoint)
addFlavour(ApiFlavour.CustomerProd, customEndpoint)
addFlavour(flavour = ApiFlavour.CustomerStage, customEndpoint = customEndpoint)
addFlavour(flavour = ApiFlavour.CustomerProd, customEndpoint = customEndpoint)
addFlavour(SSLPinningFlavour.OFF)
addFlavour(SSLPinningFlavour.ON)
productFlavors {
create(ProguardFlavour.NO_OBFUSCATE) {
dimension = ProguardFlavour.DIMENSION_NAME
setProguardFiles(listOf(
getDefaultProguardFile("proguard-android.txt"),
"$rootProject.projectDir/BuildScripts/proguard/noObfuscate.pro"
))
}
create(ProguardFlavour.OBFUSCATE) {
dimension = ProguardFlavour.DIMENSION_NAME
setProguardFiles(listOf(
getDefaultProguardFile("proguard-android.txt"),
"$rootProject.projectDir/BuildScripts/proguard/obfuscate.pro"
))
}
addEmptyFlavour(TestPanelFlavour.OFF)
addEmptyFlavour(TestPanelFlavour.ON)
}
variantFilter = Action {
if (name.contentEquals(AndroidConfig.PROD_BUILD_NAME)) {
(defaultConfig as com.android.build.gradle.internal.dsl.BaseFlavor).apply {
applicationId = AndroidConfig.PROD_APP_ID
signingConfig = signingConfigs.getByName(SigningConfig.Prod.name)
}
}
}
addEmptyFlavour(TestPanelFlavour.OFF)
addEmptyFlavour(TestPanelFlavour.ON)
ignoreCustomerProdFlavourIfReleaseIsDebuggable()
}
androidExtensions {
@ -85,13 +53,22 @@ dependencies {
retrofit()
moshi()
navigation()
coreNetwork()
leakCanary()
sharedPrefs()
chucker()
implementation(Library.FIREBASE_ANAL)
implementation(Library.FIREBASE_CRASH)
implementation(Library.FIREBASE_PERF)
implementation(Library.ANDROIDX_SECURE)
coreNetwork()
coreStrings()
implementationModule(Module.Core.UI)
implementationModule(Module.Core.UTILS)
implementationModule(Module.Core.DATA)
implementationModule(Module.RoboSwag.UTILS)
}
apply(from = "${rootProject.ext["buildScriptsDir"]}/gradle/applicationFileNaming.gradle")
apply(from = "$buildScriptDir/gradle/scripts/applicationFileNaming.gradle")
val Project.buildScriptDir: String
get() = rootProject.ext["buildScriptsDir"] as String

Binary file not shown.

BIN
app/signing_key.jks Normal file

Binary file not shown.

View File

@ -1,18 +1,22 @@
package ru.touchin.template
import android.os.Bundle
import androidx.activity.OnBackPressedCallback
import com.google.firebase.analytics.FirebaseAnalytics
import com.google.firebase.analytics.ktx.analytics
import com.google.firebase.ktx.Firebase
import me.vponomarenko.injectionmanager.x.XInjectionManager
import ru.terrakok.cicerone.NavigatorHolder
import ru.terrakok.cicerone.android.support.SupportAppNavigator
import ru.touchin.roboswag.navigation_base.activities.BaseActivity
import ru.touchin.roboswag.navigation_cicerone.CiceroneTuner
import ru.touchin.template.di.ApplicationComponent
import ru.touchin.template.navigation.MainNavigation
import ru.touchin.template.navigation.StartUpNavigation
import ru.touchin.template.navigation.StartUpCoordinator
import javax.inject.Inject
// TDOD: change package name everywhere
// TODO: change google play config
class SingleActivity : BaseActivity() {
@Inject
@ -20,7 +24,7 @@ class SingleActivity : BaseActivity() {
lateinit var navigatorHolder: NavigatorHolder
@Inject
lateinit var navigation: StartUpNavigation
lateinit var coordinator: StartUpCoordinator
private lateinit var firebaseAnalytics: FirebaseAnalytics
@ -35,13 +39,18 @@ class SingleActivity : BaseActivity() {
lifecycle.addObserver(
CiceroneTuner(
activity = this,
navigatorHolder = navigatorHolder,
fragmentContainerId = R.id.fragment_container
navigator = SupportAppNavigator(this, R.id.fragment_container)
)
)
navigation.start()
coordinator.start()
onBackPressedDispatcher.addCallback(object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
coordinator.closeCurrentScreen()
}
})
}
private fun injectDependencies() {

View File

@ -3,7 +3,7 @@ package ru.touchin.template.navigation
import ru.terrakok.cicerone.Router
import javax.inject.Inject
class StartUpNavigation @Inject constructor(
class StartUpCoordinator @Inject constructor(
@MainNavigation private val router: Router
) {
@ -11,4 +11,8 @@ class StartUpNavigation @Inject constructor(
router.newRootScreen(Screens.Login())
}
fun closeCurrentScreen() {
router.exit()
}
}

View File

@ -11,12 +11,13 @@ buildscript {
classpath("com.google.gms:google-services:${Version.GOOGLE_SERVICES_PLUGIN}")
classpath("com.google.firebase:firebase-crashlytics-gradle:${Version.FIREBASE_CRASH_PLUGIN}")
classpath("com.vanniktech:gradle-dependency-graph-generator-plugin:0.5.0")
classpath("com.google.android.gms:oss-licenses-plugin:0.10.2")
}
}
plugins {
id(Plugins.DETEKT).version("1.10.0")
id(Plugins.CPD).version("3.1")
id(Plugins.DEPENDENCY_GRAPH).version("0.5.0")
id("static-analysis-android")
}
allprojects {
@ -37,5 +38,6 @@ ext["buildScriptsDir"] = buildScriptsDir
apply(plugin = Plugins.DEPENDENCY_GRAPH)
//TODO: make staticAnalysis work on kotlin DSL
//apply(from = "$buildScriptsDir/gradle/staticAnalysis.gradle")
staticAnalysis {
buildScriptDir = buildScriptsDir
}

View File

@ -1,25 +1,29 @@
import com.android.build.gradle.BaseExtension
object AndroidConfig {
const val COMPILE_SDK_VERSION = 29
const val MIN_SDK_VERSION = 23
const val TARGET_SDK_VERSION = 29
const val BUILD_TOOLS_VERSION = "29.0.2"
val VERSION_CODE: Int = System.getenv("BUILD_NUMBER")?.toIntOrNull() ?: 10000
val VERSION_NAME = "1.0.0"
val PROD_BUILD_NAME = ProguardFlavour.OBFUSCATE +
ApiFlavour.CustomerProd.flavourName +
SSLPinningFlavour.ON.flavourName +
TestPanelFlavour.OFF.flavourName +
BuildType.Release.name
val VERSION_CODE: Int = Environment.BUILD_NUMBER.getenv()?.toIntOrNull() ?: 10000
const val VERSION_NAME = "1.0.0"
// TODO: change test package name
const val TEST_APP_ID = "com.touchin.template"
const val PROD_APP_ID = "com.ask.client"
// TODO: change common file folder
const val COMMON_FOLDER = "Template-common"
const val RELEASE_DEBUGGABLE = false
}
fun BaseExtension.ignoreCustomerProdFlavourIfReleaseIsDebuggable() {
variantFilter {
ignore = name.contains(ApiFlavour.CustomerProd.name, ignoreCase = true) && AndroidConfig.RELEASE_DEBUGGABLE
}
}

View File

@ -10,7 +10,12 @@ fun DependencyHandler.fragment() {
fun DependencyHandler.materialDesign() {
implementation(Library.ANDROID_MATERIAL)
implementation(Library.SWIPE_REFRESH)
implementation(Library.SWIPE_TO_REFRESH)
}
fun DependencyHandler.permissionDispatcher() {
implementation(Library.PERMISSION_DISPATCHER)
kapt(Library.PERMISSION_DISPATCHER_ANNOTATION_PROCESSOR)
}
fun DependencyHandler.constraintLayout() {
@ -51,6 +56,10 @@ fun DependencyHandler.coreNetwork() {
implementationModule(Module.Core.NETWORK)
}
fun DependencyHandler.coreStrings() {
implementationModule(Module.Core.STRINGS)
}
fun DependencyHandler.retrofit() {
implementation(Library.RETROFIT)
implementation(Library.OKHTTP_LOGGING_INTERCEPTOR)

View File

@ -0,0 +1,13 @@
object Environment {
const val APP_ID = "BUNDLE_ID"
const val STORE_PASSWORD = "STORE_PASSWORD"
const val KEY_ALIAS = "KEY_ALIAS"
const val KEY_PASSWORD = "KEY_PASSWORD"
const val ENDPOINT = "CUSTOM_ENDPOINT"
const val BUILD_NUMBER = "BUILD_NUMBER"
}
fun String.getenv(): String? = System.getenv(this)

View File

@ -10,7 +10,10 @@ object Library {
const val ANDROIDX_FRAGMENT_KTX = "androidx.fragment:fragment-ktx:${Version.ANDROIDX_FRAGMENT}"
const val ANDROID_MATERIAL = "com.google.android.material:material:${Version.ANDROID_MATERIAL}"
const val SWIPE_REFRESH = "androidx.swiperefreshlayout:swiperefreshlayout:${Version.SWIPE_REFRESH}"
const val SWIPE_TO_REFRESH = "androidx.swiperefreshlayout:swiperefreshlayout:${Version.SWIPE_TO_REFRESH}"
const val PERMISSION_DISPATCHER = "org.permissionsdispatcher:permissionsdispatcher:${Version.PERMISSION_DISPATCHER}"
const val PERMISSION_DISPATCHER_ANNOTATION_PROCESSOR = "org.permissionsdispatcher:permissionsdispatcher-processor:${Version.PERMISSION_DISPATCHER}"
const val ANDROID_LIFECYCLE_EXTENSIONS = "androidx.lifecycle:lifecycle-extensions:${Version.ANDROID_LIFECYCLE}"
const val ANDROID_LIFECYCLE_VIEW_MODEL_EXTENSIONS = "androidx.lifecycle:lifecycle-viewmodel-ktx:${Version.ANDROID_LIFECYCLE}"
@ -50,6 +53,8 @@ object Library {
const val FIREBASE_PERF = "com.google.firebase:firebase-perf:${Version.FIREBASE_PERF}"
const val FIREBASE_CRASH = "com.google.firebase:firebase-crashlytics:${Version.FIREBASE_CRASH}"
//TODO: replace to java time
const val JODA = "net.danlew:android.joda:2.10.6"
const val ANDROIDX_SECURE = "androidx.security:security-crypto:${Version.ANDROIDX_SECURE}"
const val ANDROIDX_BIOMETRIC = "androidx.biometric:biometric:${Version.ANDROIDX_BIOMETRIC}"
const val LICENCE_LIBRARY = "com.google.android.gms:play-services-oss-licenses:${Version.LICENCE_LIBRARY}"
}

View File

@ -8,14 +8,15 @@ object Module {
const val NAVIGATION_CICERONE = "navigation-cicerone"
const val STORABLE = "storable"
const val LIFECYCLE = "lifecycle"
const val PAGINATION = "pagination"
const val VIEWS = "views"
const val RECYCLER_VIEW_ADAPTERS = "recyclerview-adapters"
const val RECYCLER_VIEW_DECORATORS = "recyclerview-decorators"
const val KOTLIN_EXTENSIONS = "kotlin-extensions"
}
object Feature {
const val LOGIN = "feature_login"
val ALL = listOf(
LOGIN
)
@ -27,6 +28,8 @@ object Module {
const val STRINGS = "core_strings"
const val UTILS = "core_utils"
const val UI = "core_ui"
const val DATA = "core_data"
const val DOMAIN = "core_domain"
}
}

View File

@ -8,6 +8,7 @@ object Plugins {
const val KOTLIN_ANDROID = "kotlin-android"
const val KOTLIN_ANDROID_EXTENSIONS = "kotlin-android-extensions"
const val KOTLIN_KAPT = "kotlin-kapt"
const val LICENCE_PLUGIN = "com.google.android.gms.oss-licenses-plugin"
const val GOOGLE_SERVICES = "com.google.gms.google-services"
const val FIREBASE_CRASH = "com.google.firebase.crashlytics"

View File

@ -1,37 +0,0 @@
import org.gradle.api.NamedDomainObjectContainer
import org.gradle.kotlin.dsl.NamedDomainObjectContainerScope
import java.io.File
sealed class SigningConfig(
val name: String,
val storeFile: File,
val storePassword: String,
val keyAlias: String,
val keyPassword: String
) {
object Test: SigningConfig(
name = "test",
storeFile = File("file/way"),
storePassword = "pass",
keyAlias = "alias",
keyPassword = "pass"
)
object Prod: SigningConfig(
name = "prod",
storeFile = File("fsdfsd"),
storePassword = "fsdf",
keyAlias = "sdfdsf",
keyPassword = "dsfsdf"
)
}
fun NamedDomainObjectContainer<com.android.build.gradle.internal.dsl.SigningConfig>.addConfig(config: SigningConfig) {
create(config.name) {
storeFile = config.storeFile
storePassword = config.storePassword
keyAlias = config.keyAlias
keyPassword = config.keyPassword
}
}

View File

@ -9,10 +9,14 @@ object Version {
const val ANDROIDX_APPCOMPAT = "1.0.2"
const val ANDROIDX_CONSTRAINT = "2.0.0-beta4"
const val ANDROIDX_FRAGMENT = "1.2.1"
const val ANDROIDX_SECURE = "1.0.0-rc02"
const val ANDROIDX_BIOMETRIC = "1.0.1"
const val ANDROID_MATERIAL = "1.1.0"
const val ANDROID_MATERIAL = "1.2.0-rc01"
const val SWIPE_TO_REFRESH = "1.0.0"
const val ANDROID_LIFECYCLE = "2.2.0"
const val SWIPE_REFRESH = "1.0.0"
const val PERMISSION_DISPATCHER = "4.8.0"
const val DAGGER = "2.27"
const val DAGGER_INJECT_ASSISTED = "0.5.2"
@ -33,10 +37,11 @@ object Version {
const val FIREBASE_CRASH = "17.1.0"
const val FIREBASE_PERF = "19.0.7"
const val GOOGLE_SERVICES_PLUGIN = "4.3.3"
const val FIREBASE_PERF_PLUGIN = "1.3.1"
const val FIREBASE_CRASH_PLUGIN = "2.2.0"
const val LEAK_CANARY = "2.4"
const val CHUCKER = "3.2.0"
const val LICENCE_LIBRARY = "17.0.0"
}

View File

@ -9,19 +9,16 @@ sealed class ApiFlavour(
const val DIMENSION_NAME = "apiEndpoint"
}
object MockDev : ApiFlavour(
name = "mockDev",
apiUrl = "url1"
)
object TouchinTest : ApiFlavour(
name = "touchinTest",
apiUrl = "url2"
// TODO: change url
object CustomerStage : ApiFlavour(
name = "customerStage",
apiUrl = "https://wallet-api.staging.mnxsc.tech"
)
// TODO: change url
object CustomerProd : ApiFlavour(
name = "customerProd",
apiUrl = "url3"
apiUrl = "https://wallet-api.prod.mnxsc.tech"
)
}

View File

@ -1,30 +1,38 @@
import org.gradle.api.NamedDomainObjectContainer
import com.android.build.gradle.BaseExtension
fun NamedDomainObjectContainer<com.android.build.gradle.internal.dsl.BuildType>.addBuildType(
type: BuildType
fun BaseExtension.addBuildType(
type: BuildType,
buildScriptDir: String
) {
getByName(type.name) {
isMinifyEnabled = type.isMinifyEnabled
isShrinkResources = type.isShrinkResources
buildTypes {
getByName(type.name) {
isMinifyEnabled = type.optimizeAndObfuscate
isShrinkResources = type.optimizeAndObfuscate
if (type.optimizeAndObfuscate) {
val proguardFile = if (AndroidConfig.RELEASE_DEBUGGABLE) "noObfuscate.pro" else "obfuscate.pro"
setProguardFiles(listOfNotNull(
getDefaultProguardFile("proguard-android-optimize.txt"),
"$buildScriptDir/proguard/$proguardFile",
"proguard/projectConfig.pro"
))
}
}
}
}
sealed class BuildType(
val name: String,
val isMinifyEnabled: Boolean,
val isShrinkResources: Boolean
val optimizeAndObfuscate: Boolean
) {
object Debug : BuildType(
name = "debug",
isMinifyEnabled = false,
isShrinkResources = false
optimizeAndObfuscate = false
)
object Release : BuildType(
name = "release",
isMinifyEnabled = true,
isShrinkResources = true
optimizeAndObfuscate = true
)
}

View File

@ -1,10 +1,11 @@
import com.android.build.gradle.internal.dsl.ProductFlavor
import org.gradle.api.NamedDomainObjectContainer
import com.android.build.gradle.BaseExtension
abstract class Flavour(val flavourName: String, val dimensionName: String)
fun NamedDomainObjectContainer<ProductFlavor>.addEmptyFlavour(flavour: Flavour) {
create(flavour.flavourName) {
dimension = flavour.dimensionName
fun BaseExtension.addEmptyFlavour(flavour: Flavour) {
productFlavors {
create(flavour.flavourName) {
dimension = flavour.dimensionName
}
}
}

View File

@ -1,6 +0,0 @@
object ProguardFlavour {
const val DIMENSION_NAME = "proguardSettings"
const val NO_OBFUSCATE = "noObfuscate"
const val OBFUSCATE = "obfuscate"
}

View File

@ -0,0 +1,23 @@
import com.android.build.gradle.BaseExtension
import java.io.File
object SigningConfig {
const val CONFIG_NAME: String = "signing_key"
const val PATH_TO_KEYSTORE_FILE: String = "signing_key.jks"
const val DEFAULT_STORE_PASSWORD: String = "iphoneandroidwp7"
const val DEFAULT_KEY_ALIAS: String = "touchin"
const val DEFAULT_KEY_PASSWORD: String = "iphoneandroidwp7"
}
fun BaseExtension.configureSigningConfig(getRelativeFile: (String) -> File) {
signingConfigs {
create(SigningConfig.CONFIG_NAME) {
storeFile = getRelativeFile(SigningConfig.PATH_TO_KEYSTORE_FILE)
storePassword = Environment.STORE_PASSWORD.getenv() ?: SigningConfig.DEFAULT_STORE_PASSWORD
keyAlias = Environment.KEY_ALIAS.getenv() ?: SigningConfig.DEFAULT_KEY_ALIAS
keyPassword = Environment.KEY_PASSWORD.getenv() ?: SigningConfig.DEFAULT_KEY_PASSWORD
}
}
}

View File

@ -1,6 +1,7 @@
package plugins
import AndroidConfig
import BuildType
import Plugins
import com.android.build.gradle.BaseExtension
import kotlinStd
@ -50,6 +51,14 @@ abstract class BaseAndroidPlugin : Plugin<Project> {
jvmTarget = "1.8"
}
}
if (AndroidConfig.RELEASE_DEBUGGABLE) {
buildTypes {
getByName(BuildType.Release.name) {
isDebuggable = true
}
}
}
}
private fun Project.configureDependencies() = dependencies {

View File

@ -0,0 +1,3 @@
plugins {
id(Plugins.ANDROID_LIB_PLUGIN_WITH_DEFAULT_CONFIG)
}

View File

@ -0,0 +1 @@
<manifest package="ru.touchin.template.core_data" />

View File

@ -0,0 +1,3 @@
plugins {
id(Plugins.ANDROID_LIB_PLUGIN_WITH_DEFAULT_CONFIG)
}

View File

@ -0,0 +1 @@
<manifest package="ru.touchin.template.core_domain" />

View File

@ -1,22 +1,20 @@
plugins {
id(Plugins.ANDROID_LIB_PLUGIN_WITH_DEFAULT_CONFIG)
// id("api-generator-android")
}
android {
defaultConfig {
rootProject.extensions.add("pathToApiSchemes", "${AndroidConfig.COMMON_FOLDER}/api")
rootProject.extensions.add("applicationId", AndroidConfig.TEST_APP_ID)
}
}
// TODO: uncomment api generator
//apiGenerator {
// pathToApiSchemes = "${AndroidConfig.COMMON_FOLDER}/api"
// outputPackageName = AndroidConfig.TEST_APP_ID
// outputLanguage = apigen.OutputLanguage.KotlinAndroid(
// methodOutputType = apigen.MethodOutputType.Coroutine
// )
//}
dependencies {
retrofit()
dagger()
moshi()
coroutines()
//TODO: fix api gen and remove joda
implementation(Library.JODA)
}
//apply(from = "${rootProject.extra["buildScriptsDir"]}/gradle/apiGenerator.gradle")

View File

@ -22,6 +22,7 @@ val roboswagModules = listOf(
"kotlin-extensions"
)
includeBuild("BuildScripts/gradle/plugins")
roboswagModules.forEach { module ->
include(":$module")
project(":$module").projectDir = file("RoboSwag/$module")