Как получить доступ к option.outputFileName в Котлине - PullRequest
0 голосов
/ 11 июня 2018

Мы использовали такой фрагмент кода, чтобы переименовать файл APK, сгенерированный нашей сборкой Gradle:

android.applicationVariants.all { variant ->
    variant.outputs.all {
        outputFileName = "${variant.name}-${variant.versionName}.apk"
    }
}

Источник: https://developer.android.com/studio/build/gradle-plugin-3-0-0-migration#variant_output

Я сейчас нахожусь в процессепреобразования моего build.gradle в build.gradle.kts, то есть в Gradle Kotlin DSL.Это одна из последних пропущенных частей: я не могу понять, как получить доступ к outputFileName.

В соответствии с документами API он даже не существует:

  • BaseVariant.getOutputs() возвращает DomainObjectCollection<BaseVariantOutput>, который предоставляет метод all, используемый во фрагменте.
  • BaseVariantOutput extends OutputFile, который расширяет VariantOutput, но ни один из них не имеет outputFileName или каких-либо методов полученияили сеттеры с совпадающим именем.

Итак, я подозреваю, что в работе есть какая-то продвинутая магия Groovy, чтобы заставить это работать - но как мне попасть в Kotlin?

1 Ответ

0 голосов
/ 11 июня 2018

Просматривая исходный код плагина 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) из вашегокод, надеясь, что они будут там во время выполнения, даже если интерфейсы времени компиляции, о которых вы знаете, не имеют их.

...