Android 如何自定义产品风格的APK文件名?

Android 如何自定义产品风格的APK文件名?,android,gradle,android-gradle-plugin,build.gradle,android-productflavors,Android,Gradle,Android Gradle Plugin,Build.gradle,Android Productflavors,我在build.gradle脚本中自定义我的Android应用程序的APK文件名,如下所示: android{ 默认配置{ project.ext.set(“archivesBaseName”、“MyApplication”); } } 现在我正在使用产品口味: android{ 产品风味{ 绿色的{ applicationId“com.example.myapplication.green” } 蓝色的{ applicationId“com.example.myapplication.blu

我在
build.gradle
脚本中自定义我的Android应用程序的APK文件名,如下所示:

android{
默认配置{
project.ext.set(“archivesBaseName”、“MyApplication”);
}
}
现在我正在使用产品口味:

android{
产品风味{
绿色的{
applicationId“com.example.myapplication.green”
}
蓝色的{
applicationId“com.example.myapplication.blue”
}
}
}
有没有办法自定义每个APK的名称?我尝试了
archiveBaseName
baseName
,但没有成功。最后,我想提出以下文件:

build/outputs/apk/Blue-debug-1.2.1.apk
build/outputs/apk/Blue-debug-unaligned.apk
build/outputs/apk/Blue-release-1.2.1.apk
build/outputs/apk/Blue-release-unaligned.apk
build/outputs/apk/Green-debug-1.2.1.apk
build/outputs/apk/Green-debug-unaligned.apk
build/outputs/apk/Green-release-1.2.1.apk
build/outputs/apk/Green-release-unaligned.apk

试着把这个放在你的android build.gradle闭包中

buildTypes {
    debug {
        // debug buildType specific stuff
    }
    release {
        // release buildType specific stuff
    }
    applicationVariants.all { variant ->
        if (variant.buildType.name.equals("release") &&
            variant.productFlavors[0].name.equals("green") &&
            variant.zipAlign) {
                def apk = variant.outputFile;
                variant.outputFile = new File(apk.parentFile, "green.apk");
        } else if(variant.buildType.name.equals("release") &&
            variant.productFlavors[0].name.equals("blue") &&
            variant.zipAlign) {
                def apk = variant.outputFile;
                variant.outputFile = new File(apk.parentFile, "blue.apk");
        }
    }
}

现在输出应该像
green.apk
blue.apk

因为默认情况下apk文件名已经不同了,所以需要这样做很奇怪

如果查看第1346行,可以看到outputFile中使用了variantData.variantConfiguration.baseName

variantData.outputFile = project.file("$project.buildDir/apk/${project.archivesBaseName}-${variantData.variantConfiguration.baseName}.apk")
baseName
的文档是

/**
 * Full, unique name of the variant, including BuildType, flavors and test, dash separated.
 * (similar to full name but with dashes)
 */
private String mBaseName;
因此,运行
gradleassemblefreedebug
应该会得到一个
ProjectName-free-debug.apk
文件

但如果情况并非如此,或者您需要不同的文件名,则可以使用以下代码对其进行自定义

android {
    buildTypes {
        debug {}
        alpha {}
        release {}
    }
    productFlavors {
        free{}
        paid{}
    }
    applicationVariants.all { variant ->
        def newApkName = variant.name + "my-custom-addition" + ".apk";
        variant.outputFile = new File("${project.buildDir}/outputs/apk/", newApkName);
    }
}

Android Gradle插件0.13.0不推荐在以下应用程序中使用的输出文件:

applicationVariants.all { variant ->
    def newApkName = variant.name + "my-custom-addition" + ".apk";
    variant.outputFile = new File("${project.buildDir}/outputs/apk/", newApkName);
}
对我有效的解决方案是:

android {
... 
}

project.archivesBaseName = "AndroidAppGeneric-${_buildVersionNameForMaven}"

对于Android Gradle插件0.13.+您应该使用以下内容:

android{
    buildTypes {
        applicationVariants.all { variant ->
            variant.outputs.each { output ->
                def apk = output.outputFile;
                def newName = "mysms-" + variant.baseName.replace("-release", "") + "-" + defaultConfig.versionName + ".apk";
                output.outputFile = new File(apk.parentFile, newName);
            }
        }
    }
}
productFlavors {
        production {
            applicationId "com.example.production"
        }

        staging {
            applicationId "com.example.production.staging"

        }

        applicationVariants.all { variant ->
            variant.outputs.each { output ->
                if(variant.productFlavors[0].name.equals("staging")){
                    output.outputFile = new File(output.outputFile.parent,
                            output.outputFile.name.replace("app-staging-release",  "test"));

                }else{
                    output.outputFile = new File(output.outputFile.parent,
                            output.outputFile.name.replace("app-production-release",  "production"));
                }

            }
        }
    }
我是这样做的:

android{
    buildTypes {
        applicationVariants.all { variant ->
            variant.outputs.each { output ->
                def apk = output.outputFile;
                def newName = "mysms-" + variant.baseName.replace("-release", "") + "-" + defaultConfig.versionName + ".apk";
                output.outputFile = new File(apk.parentFile, newName);
            }
        }
    }
}
productFlavors {
        production {
            applicationId "com.example.production"
        }

        staging {
            applicationId "com.example.production.staging"

        }

        applicationVariants.all { variant ->
            variant.outputs.each { output ->
                if(variant.productFlavors[0].name.equals("staging")){
                    output.outputFile = new File(output.outputFile.parent,
                            output.outputFile.name.replace("app-staging-release",  "test"));

                }else{
                    output.outputFile = new File(output.outputFile.parent,
                            output.outputFile.name.replace("app-production-release",  "production"));
                }

            }
        }
    }

我正在使用以下命令,以便文件不会相互覆盖:

applicationVariants.all { variant ->
    variant.outputs.each { output ->
        def newApkName = variant.name + "-" + variant.versionName + "(" + variant.versionCode +")" + ".apk";
        output.outputFile = new File("${project.projectDir}/outputs/apk/" + variant.name, newApkName);
    }
}
这是我的工作:

在APK名称中添加
变量.productFlavors[0].name

代码示例:

buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        applicationVariants.all { variant ->
            variant.outputs.each { output ->
                output.outputFile = new File(output.outputFile.parent, "APPNAME_" + variant.productFlavors[0].name + "_" + variant.versionName + ".apk")

            }
        }
    }
}
这是我对上面Lakshman答案的变体(呵呵),我不知道为什么我需要“variants.outputs.each”,但我确实需要

defaultConfig {
    applicationId "my.company.com"
    minSdkVersion 16
    targetSdkVersion 25
    applicationVariants.all { variant ->
        if (variant.productFlavors[0].name.equals("VariantA")) {
            variant.outputs.each { output ->
                def apk = output.outputFile;
                output.outputFile = new File(apk.parentFile, "Blue.apk");
            }
        } else { // Only two variants
            variant.outputs.each { output ->
                def apk = output.outputFile;
                output.outputFile = new File(apk.parentFile, "Green.apk");
            }
        }
    }
}

对于Android Studio 3.0,您必须更改为:

applicationVariants.all { variant ->
    variant.outputs.each { output ->
        output.outputFile = new File(output.outputFile.parent, "whatever" + ".apk")
    }
}
致:

这就是你需要的

android {
    defaultConfig {
        ……

        // custom output apk name
        applicationVariants.all { variant ->
            variant.outputs.all {
                outputFileName = "${variant.productFlavors[0].name}-${variant.buildType.name}-${variant.versionName}.apk"
            }
        }
    }
    ……
}

这将在2021年对你有所帮助

android {
    
//........
flavorDimensions "version"
productFlavors {
    Free {
        dimension "version"
        applicationId "com.exampleFree.app"
    }
    Paid {
        dimension "version"
        applicationId "com.examplePaid.app"
    }
}

applicationVariants.all { variant ->
    variant.outputs.all { output ->
        def appId = variant.applicationId// com.exampleFree.app OR com.examplePaid.app
        def versionName = variant.versionName
        def versionCode = variant.versionCode // e.g 1.0
        def flavorName = variant.flavorName // e. g. Free
        def buildType = variant.buildType.name // e. g. debug
        def variantName = variant.name // e. g. FreeDebug

        //customize your app name by using variables
        outputFileName = "${variantName}.apk"
    }
}}
Apk名称FreeDebug.Apk

证明


这里的每个答案都是一样的,而且过时了。很容易做到[flavor]-[version]-[build type]:

android {
    productFlavors {
        green {
            applicationId "com.example.myapplication.green"
            setProperty("archivesBaseName", "Green-" + defaultConfig.versionName)
        }

        blue {
            applicationId "com.example.myapplication.blue"
            setProperty("archivesBaseName", "Blue-" + defaultConfig.versionName)
        }
    }
}
如果您的版本名为“1.2.1”,则运行gradle Assembly将生成:

绿色-1.2.1-debug.apk

绿色-1.2.1-release.apk

Blue-1.2.1-debug-apk


Blue-1.2.1-release.apk

如果对“freeflavor”和“proflavor”都做同样的检查,为什么还要检查产品的风味名称?我真正想要的是改变“Modulename”,就像在你的例子中一样,而不是附加一些东西。不过:你为什么像我之前问的那样有两个
if
块?是的。它在这里没有多大作用,可以进一步简化。如果四舍五入括号中的语句不完整。。。虽然即使把它们放在那里也不会对meThis产生影响,但它并没有起作用,缺少了paren,而且显然与Android插件不兼容?我得到一个关于未定义属性outputFile的错误。请看下面我的答案,它显示了我是如何修复它的。(1) 由于某种原因,
build/outputs/apk
中的
-unaligned.apk
文件仍然带有
MyApplication
前缀。(2) 变量没有大写。知道如何完成吗?(1)根据BasePlugin.groovy-link中的第1316行,您可以更改
项目.archivesBaseName
variantData.variantConfiguration.baseName
以适应未对齐的outputname。但我确信这会干扰其他构建步骤。不过,您不应该使用未对齐的版本,而应该使用最终的apk(您可以完全控制apk名称)。(2) variant.name.capitalize()这在Android Gradle 3.0.0-alpha1中已停止工作。你似乎不能再访问输出文件了。如果你不想更新你的gradle版本,这真的很有用!什么是outputFile?对我不起作用,它什么都不起作用。我添加了一个“println outputFileName”,并且打印正确,但出于某种原因,gradle没有使用“outputFileName”值作为文件名。顺便说一下,我正在尝试将其用于应用程序包,而不是APK。