How we can set the targetProjectPath property in android test extension during configuration. W are creating a custom plugin which takes a target path property from consumer. If we dont set targetProject path, config fails as its not a property field in the Test extension rather a variable
Wondering whats the best way to handle this, afterEvaluate works but i need to set some default targetProjectPath, which i am trying to avoid setting one
Here is the sample code, that i am using
class CustomPlugin : Plugin<Project> {
override fun apply(project: Project) {
val uiTestConfigExtension =
project.extensions.create("customExtenstion", TestModuleExtension::class.java)
.apply { targetApp.convention(":sampleApp") }
with(project) {
with(pluginManager) {
apply("com.android.test")
}
}
extensions.getByType<TestExtension>().apply {
targetProjectPath = "some default"
// want to set the target path during configuration phase
afterEvaluate {
targetProjectPath = uiTestConfigExtension.targetApp.get()
}
}
}
}
Appreciate any inputs or pointers on how we can set the targetProjectPath dynamically from consumer end.
You mean it works sometimes under certain conditions. afterEvaluate is practically never a solution, but duct tape. The main effect of afterEvaluate is to introduce timing problems, ordering problems, and race conditions. It is like using SwingUtilities.invokeLater or Platform.runLater to “fix” a GUI problem. It just does symptom treatment, delaying the problem to a later, harder to reproduce, harder to debug, and harder to fix point in time.
As targetProjectPath is a primitive property and not a Property, I’d remove targetApp from the TestModuleExtension and instead add a function setTargetApp where you give the value as argument, then you can directly set the value there.
I recall reading in an earlier post about the suggested solution. I attempted to implement it, but with not much luck. As the targetProjectPath is a property, my understanding is its evaluated in the initialisation phase and android test plugin adds a project dependency based on this.
I would like to defer this dependency until the consumer project provides it. Can you elaborate on how adding a function would defer this dependency?.
I have no idea what Android Gradle Plugin does.
But if using afterEvaluate { ... } works, then a function would also work, as the function call is happening before the afterEvaluate evaluation happens.
So what is your problem with that approach?
Remove the property from the extension, add a function with targetApp parameter, in the function body set the targetProjectPath to the argument.
The consumer will then call that function instead of setitng the property.
With the above approach, default project was added to the dependency list initially and then during configuration based on condition either targetA or targetB is getting added. To speed up, i was looking for a way to skip the default project from getting set. If i dont set any, then the initialisation phase will fail as the plugin expects a value, i was wondering is there a way to overcome this problem.
Hope this clarifies the issue i was trying to solve.
You should not give the project as argument.
Just either give it to the extension when you create it, or simple let it be injected by Gradle.
I’m also not sure it is a good idea to apply the plugin in that method.
I’d keep the plugin application in your apply method, before creating the extension.