Просматривая исходный код плагина Android Gradle, я думаю, что нашел ответ - здесь мы идем:
Мы на самом деле имеем дело с объектами типа BaseVariantOutputImpl
, а этот класс делает имеют оба этих метода:
public String getOutputFileName() {
return apkData.getOutputFileName();
}
public void setOutputFileName(String outputFileName) {
if (new File(outputFileName).isAbsolute()) {
throw new GradleException("Absolute path are not supported when setting " +
"an output file name");
}
apkData.setOutputFileName(outputFileName);
}
Используя эти знания, мы можем теперь:
import com.android.build.gradle.internal.api.BaseVariantOutputImpl
и затем разыграть наши целевые объекты следующим образом:
applicationVariants.all(object : Action<ApplicationVariant> {
override fun execute(variant: ApplicationVariant) {
println("variant: ${variant}")
variant.outputs.all(object : Action<BaseVariantOutput> {
override fun execute(output: BaseVariantOutput) {
val outputImpl = output as BaseVariantOutputImpl
val fileName = output.outputFileName
.replace("-release", "-release-v${defaultConfig.versionName}-vc${defaultConfig.versionCode}-$gitHash")
.replace("-debug", "-debug-v${defaultConfig.versionName}-vc${defaultConfig.versionCode}-$gitHash")
println("output file name: ${fileName}")
outputImpl.outputFileName = fileName
}
})
}
})
Итак, я предполагаю: да, в работе есть какая-то магия Groovy, а именно то, что система динамических типов Groovy позволяет вам просто получить доступ к getOutputFileName
и setOutputFileName
(посредством сокращенного синтаксиса outputImpl.outputFileName
, как в Kotlin) из вашегокод, надеясь, что они будут там во время выполнения, даже если интерфейсы времени компиляции, о которых вы знаете, не имеют их.