gradle 如何在Kotlin中访问variant.outputFileName

to94eoyn  于 4个月前  发布在  Kotlin
关注(0)|答案(5)|浏览(81)

我们一直在使用这样的代码片段来重命名Gradle构建生成的APK文件:

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,即转换为GradleKotlinDSL。这是最后缺失的部分之一:我不知道如何访问outputFileName
根据API文档,它甚至似乎不存在:

  • BaseVariant.getOutputs()返回一个DomainObjectCollection<BaseVariantOutput>,它提供了代码片段中使用的all方法。
  • BaseVariantOutput扩展了OutputFileOutputFile扩展了VariantOutput,但这些都没有outputFileName或任何匹配名称的getter或setter。

所以,我怀疑有一些先进的Groovy魔法在工作,使这一工作-但我如何在Kotlin到达那里?

7gs2gvoe

7gs2gvoe1#

@大卫.mihola的一个小简化版本回答:

android {

    /**
    * Notes Impl: Use DomainObjectCollection#all
    */
    applicationVariants.all {
        val variant = this
        variant.outputs
            .map { it as com.android.build.gradle.internal.api.BaseVariantOutputImpl }
            .forEach { output ->
                val outputFileName = "YourAppName - ${variant.baseName} - ${variant.versionName} ${variant.versionCode}.apk"
                println("OutputFileName: $outputFileName")
                output.outputFileName = outputFileName
            }
    }

}

字符串

hivapdat

hivapdat2#

浏览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的动态类型系统允许您从代码中访问getOutputFileNamesetOutputFileName(通过缩写的outputImpl.outputFileName语法,就像Kotlin中一样),希望它们在运行时就在那里,即使您所知道的编译时接口没有它们。

hi3rlvi2

hi3rlvi23#

较短的版本,使用的是dashdas:

applicationVariants.all{
        outputs.all {
            if(name.contains("release"))
                (this as BaseVariantOutputImpl).outputFileName = "../../apk/$name-$versionName.apk"
        }
    }

字符串
这将把APK放入app/apk文件夹,文件夹名称由变体名称和版本代码组成。
您可以根据需要更改文件名的格式。
重要提示:必须仅在发布版本上执行此操作,因为路径中的“..”会导致调试构建过程出现奇怪的错误。

e1xvtsh3

e1xvtsh34#

对于libraryVariants,可以在不访问内部API的情况下更改输出文件名:

libraryVariants.all {
        outputs.all {
            packageLibraryProvider {
                archiveFileName.set("yourlibrary-${buildType.name}.aar")
            }
        }
    }

字符串

vi4fp9gy

vi4fp9gy5#

更新04/12/23:请小心进行,@Mike评论说,这样的配置可能会影响您的项目,我没有任何问题,直到知道,仍然重命名我的APK与配置以前共享。
原始答案:
为了KotlinKTS。
注意:这被认为是一个临时解决方案,直到Android团队在KTS中发布了一个正确的方法来完成它。
它可以在AGP v7.1.2中工作,也可以在较低版本的AGP中工作。
:应用程序构建器.gradle

android {

// ...

    this.buildOutputs.all {

        val variantOutputImpl = this as com.android.build.gradle.internal.api.BaseVariantOutputImpl

        val variantName: String = variantOutputImpl.name

        val outputFileName = "custom-name-${variantName}.apk"
        
        variantOutputImpl.outputFileName = outputFileName
    }
}

字符串

相关问题