Slackbot
07/05/2022, 7:05 PMSatyarth Sampath
07/06/2022, 11:02 AMadd("fooImplementation",project(":login",configuration="release"))
work.Satyarth Sampath
07/06/2022, 11:04 AMSatyarth Sampath
07/06/2022, 11:05 AM<https://developer.android.com/studio/build/build-variants#variant_aware>
That's the one...providing fallbacks could be another approach for this?Alexander Gherschon
07/06/2022, 11:06 AMadd("fooImplementation",project(":login",configuration="release")) works that's much better!
Testing right nowAlexander Gherschon
07/06/2022, 11:08 AMThe Hilt Android Gradle plugin is applied but no com.google.dagger:hilt-android dependency was found.
So weird, I don't understand how that plugin being applied is an issue when using add() or the other way of writing itSatyarth Sampath
07/06/2022, 11:10 AM--stacktrace . You could probably be hitting an issue with configuration in the other project.Satyarth Sampath
07/06/2022, 11:12 AMAlexander Gherschon
07/06/2022, 11:13 AMbuildVariantImplementation doesn't existAlexander Gherschon
07/06/2022, 11:13 AMproductFlavorImplementation exists I guessAlexander Gherschon
07/06/2022, 11:14 AMSatyarth Sampath
07/06/2022, 11:18 AMSatyarth Sampath
07/06/2022, 11:20 AMAlexander Gherschon
07/06/2022, 11:20 AMAlexander Gherschon
07/06/2022, 11:21 AMAlexander Gherschon
07/06/2022, 11:21 AMsitDebug I get the following error:
org.gradle.api.artifacts.UnknownConfigurationException: Configuration with name 'sitDebugImplementation' not found.Satyarth Sampath
07/06/2022, 11:25 AMsitDebug build variant would lead to the following configurations being created.
You can also print configurations as a part of running any gradle task.Alexander Gherschon
07/06/2022, 11:26 AMSatyarth Sampath
07/06/2022, 11:27 AMAlexander Gherschon
07/06/2022, 11:28 AMAlexander Gherschon
07/06/2022, 11:28 AMconfigurations.forEach {
println(it.name)
}Satyarth Sampath
07/06/2022, 11:30 AMAlexander Gherschon
07/06/2022, 11:31 AMAlexander Gherschon
07/06/2022, 12:21 PMXavier Ducrohet
07/06/2022, 5:11 PM<buildVariant>Implementation exist but only in afterEvaluate because that's where the variants are computed by AGP. So if you want to use this you need to wrap your dependencies {} section in afterEvaluate {}Xavier Ducrohet
07/06/2022, 5:13 PMimplementation(project("...", configuration = "...") This is Gradle's old way of targeting a specific configuration in a producer module that predates the whole variant-aware publication introduced several years ago.Xavier Ducrohet
07/06/2022, 5:14 PMAlexander Gherschon
07/08/2022, 12:45 PMlogin module, we created a special AutoLogin class (to help us when we develop) but we want to have it on the classpath and run that special code only in sitDebug and uatDebug build variants (for security reasons)
The solution:
⢠In that login module, I've created a dev and prod variants
⢠The autoLogin class is placed into the devDebug productFlavor/source folder
⢠In prodDebug and release productFlavor/source folders, there's a no-op empty AutoLogin class (copied twice for now*)
⢠matchingFallbacks += listOf(<http://Flavor.DEV|Flavor.DEV>) set in the app module, on product flavors sit and uat does the magic!
Overall I like this solution a lot, as a good infra for automating things while developping, besides having to copy twice the no-op version of the class.
* I hope to be able to use sourceSets {} to avoid the no-op class duplication but I'm not sure yet how to do that, because I need it in 3 specific build variants our of the 4. I'll look into afterEvaluate for that šAlexander Gherschon
07/08/2022, 2:18 PMafterEvaluate , I got this:
afterEvaluate {
val extra = "extra"
val extraNoop = "extra-noop"
fun newSrcDirs(sourceSetName: String, op: Boolean) = setOf(
File("./src/${sourceSetName}/java"),
File("./src/${sourceSetName}/kotlin"),
File("./src/${if (op) extra else extraNoop}/java"),
File("./src/${if (op) extra else extraNoop}/kotlin")
)
android.sourceSets.forEach { sourceSet ->
if (sourceSet.name == "devDebug") {
sourceSet.kotlin.srcDirs(newSrcDirs(sourceSet.name, true))
} else if (sourceSet.name in listOf("devRelease", "prodDebug", "prodRelease")) {
sourceSet.kotlin.srcDirs(newSrcDirs(sourceSet.name, false))
}
}
}
The IDE picks the right sourceSet correctly, but I get the following errors while building:
> Task login:compileDevReleaseKotlin FAILED
e: LoginMainFragment.kt: (12, 37): Unresolved reference: AutoLogin
e: LoginMainFragment.kt: (27, 29): Unresolved reference: AutoLogin
What am I missing?
Probably something related to the configurations... š¤Alexander Gherschon
07/08/2022, 3:37 PMsourceSets at https://developer.android.com/studio/build/extend-agp šXavier Ducrohet
07/08/2022, 3:43 PMXavier Ducrohet
07/08/2022, 3:44 PMXavier Ducrohet
07/08/2022, 3:45 PMXavier Ducrohet
07/08/2022, 3:46 PMapp-type) would consume the prod flavor in the dimension login-type, while sit/uat would consume dev in that same login-type dimension (replace with your own dimension names š )Xavier Ducrohet
07/08/2022, 3:47 PMmissingDimensionStrategy. see https://developer.android.com/studio/build/build-variantsAlexander Gherschon
07/08/2022, 6:19 PMapp module has a version dimension with 3 values (aka product flavors): sit / uat / prod
⢠The login module
⦠has a login-type dimension 2 values: automatic, manual
⦠The special code doing the automatic login sits at /login/src/automatic/java/<package>/AutoLogin.kt
⦠The no-op version, that doesn't login automatically sits at /login/src/manual/java/<package>/AutoLogin.kt
What I would need to make happen then would be the following:
⢠:app:sitDebug consumes :login:automaticDebug <- automatic login here
⢠:app:sitRelease consumes :login:manualRelease
⢠:app:uatDebug consumes :login:automaticDebug <- automatic login here
⢠:app:uatRelease consumes :login:manualRelease
⢠:app:prodDebug consumes :login:manualDebug
⢠:app:prodRelease consumes :login:manualRelease
Can I really just do that with missingDimensionStrategy ?
I feel like I miss the point of how to differentiate between debug / release š¤Alexander Gherschon
07/08/2022, 6:25 PMmissingDimensionStrategy and matchingFallbacks ?Xavier Ducrohet
07/08/2022, 6:26 PMXavier Ducrohet
07/08/2022, 6:27 PMAlexander Gherschon
07/08/2022, 6:28 PMXavier Ducrohet
07/08/2022, 6:28 PMmissingDimensionStrategy ultimately just sets up attributes on Configuration objects.Xavier Ducrohet
07/08/2022, 6:28 PMXavier Ducrohet
07/08/2022, 6:30 PMandroid {
productFlavors {
sit {
missingDimensionStrategy 'login-type', 'automatic'
}
uat {
missingDimensionStrategy 'login-type', 'automatic'
}
prod {
missingDimensionStrategy 'login-type', 'manual'
}
}
}Xavier Ducrohet
07/08/2022, 6:30 PMXavier Ducrohet
07/08/2022, 6:30 PMuatRelease and change things.Alexander Gherschon
07/08/2022, 6:31 PMXavier Ducrohet
07/08/2022, 6:32 PMConfiguration object in the variant API: https://developer.android.com/reference/tools/gradle-api/7.3/com/android/build/api/variant/ComponentXavier Ducrohet
07/08/2022, 6:33 PMuatReleaseCompileClasspath and uatReleaseRuntimeClasspathXavier Ducrohet
07/08/2022, 6:35 PMandroidComponents {
onVariant(selector().withName('uatRelease')) { v ->
v.compileConfiguration...
v.runtimeConfiguration...
}
}Xavier Ducrohet
07/08/2022, 6:36 PMselector().withName('uatRelease') is a shortcut and less future proof than something like selector().withBuildType('release').withFlavor('login-type' to 'uat')Alexander Gherschon
07/08/2022, 6:36 PMXavier Ducrohet
07/08/2022, 6:37 PMlogin-type and this is where you need low level APIs in Gradle, and some knowledge of AGP internalsXavier Ducrohet
07/08/2022, 6:37 PMmissingDimensionStrategy on variant so that you don't have to deal with thisAlexander Gherschon
07/08/2022, 6:38 PMXavier Ducrohet
07/08/2022, 6:40 PMXavier Ducrohet
07/08/2022, 6:42 PMConfiguration.getAttributes().attributes(Attribute<T>, T) is the API you want to use to set an attributesXavier Ducrohet
07/08/2022, 6:42 PMXavier Ducrohet
07/08/2022, 6:42 PMXavier Ducrohet
07/08/2022, 6:44 PMAttribute<ProductFlavorAttr> and you can get this with ProductFlavorAttr.Companion.of("name of dimension")Xavier Ducrohet
07/08/2022, 6:44 PMXavier Ducrohet
07/08/2022, 6:44 PMAlexander Gherschon
07/08/2022, 6:45 PM7.3.0-beta05 and will try those APIs right awayXavier Ducrohet
07/08/2022, 6:46 PMandroidComponents {
onVariant(selector().withName('uatRelease')) { v ->
v.compileConfiguration.getAttributes().attribute(
ProductFlavorAttr.Companion.of("login-type"),
"manual"
)
v.runtimeConfiguration.getAttributes().attribute(
ProductFlavorAttr.Companion.of("login-type"),
"manual"
)
}
}Xavier Ducrohet
07/08/2022, 6:54 PMmissingDimensionStrategy on a per-variant basis. š¤¦Xavier Ducrohet
07/08/2022, 6:54 PMAlexander Gherschon
07/08/2022, 6:55 PMXavier Ducrohet
07/08/2022, 6:55 PMandroid {
applicationVariants.all {
if (name == "uatRelease") {
missingDimensionStrategy("login-type", "manual")
}
}
}Xavier Ducrohet
07/08/2022, 6:56 PMmissingDimensionStrategy to it (filing the bug now)Xavier Ducrohet
07/08/2022, 7:00 PMAlexander Gherschon
07/08/2022, 7:06 PMAlexander Gherschon
07/08/2022, 7:07 PMXavier Ducrohet
07/08/2022, 7:08 PMXavier Ducrohet
07/08/2022, 7:08 PMXavier Ducrohet
07/08/2022, 7:09 PMXavier Ducrohet
07/08/2022, 7:09 PMAlexander Gherschon
07/08/2022, 7:10 PMAlexander Gherschon
07/08/2022, 7:32 PMXavier Ducrohet
07/08/2022, 7:32 PMAlexander Gherschon
07/14/2022, 7:18 AM2022-07-14 10:00:36.993 9097-9097/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: il.co.firstdigitalbank.uat, PID: 9097
java.lang.NoClassDefFoundError: Failed resolution of: Lil/co/firstdigitalbank/login/ui/add_email/AddEmailViewModel_HiltModules_KeyModule_ProvideFactory;
at aj.c.h(DaggerDigitalBankApp_HiltComponents_SingletonC.java:2)
at aj.c.a(DaggerDigitalBankApp_HiltComponents_SingletonC.java:4)
at wi.a.a(DefaultViewModelFactories.java:2)
at gy.b.getDefaultViewModelProviderFactory(Unknown Source:4)
at il.co.firstdigitalbank.ui.launcher.LauncherActivity$c.m(Unknown Source:2)
at androidx.lifecycle.s0.getValue(ViewModelProvider.kt:2)
at il.co.firstdigitalbank.ui.launcher.LauncherActivity.onCreate(LauncherActivity.kt:3)
Only when isMinifyEnabled = true (which was our default in release obviously), because when isMinifyEnabled = false the app runs, no issues.
Any idea why R8 is having an issue with using missingDimensionStrategy ?Alexander Gherschon
07/14/2022, 7:45 AMgoogle() aka com.android.tools:r8:3.3.28 doesn't helpXavier Ducrohet
07/14/2022, 5:30 PMAlexander Gherschon
07/15/2022, 3:47 AM