How to customize the APK file name for product flavors?
Asked Answered
A

12

53

I am customizing the name of the APK file of my Android application within the build.gradle script as follows:

android {
    defaultConfig {
        project.ext.set("archivesBaseName", "MyApplication");
    }
}

Now that I am using product flavors:

android {
    productFlavors {
        green {
            applicationId "com.example.myapplication.green"
        }

        blue {
            applicationId "com.example.myapplication.blue"
        }
    }
}

Is there a way to customize the name of each APK? I experimented with archiveBaseName and baseName without success. In the end I want to come up with the following files:

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
Alamein answered 3/8, 2014 at 11:46 Comment(0)
W
28

Try to put this in your android closure of 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");
        }
    }
}

Now the outputs should be like green.apk and blue.apk.

Wyne answered 4/8, 2014 at 8:17 Comment(6)
Why do you check the product flavor name if you do the same for both "freeflavor" and "proflavor" anyways? What I really want is to change the "Modulename" as in your example - not appending something.Alamein
Still: what is the reason you have two if blocks as I asked before?Alamein
Yes. It is not serving much purpose here and can be further simplified.Wyne
The if statement rounded brackets are not complete... Although even putting them there has no impact for meBrynhild
This didn't work, missing paren and apparently incompatible with the Android plugin? I was getting an error about undefined attribute outputFile. See my answer below that shows how I fixed it.Amboina
Is there any solution for .aab file?Baden
I
27

This will help you in 2022.

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 name FreeDebug.apk

Proof enter image description here

enter image description here

Indetermination answered 3/1, 2020 at 17:46 Comment(4)
Not working for me, it does nothing. I added a "println outputFileName" and it is printing correctly, but for some reason gradle is not using the "outputFileName" value for the file name. By the way, I'm trying to use it for an app bundle, not an APK.Nadinenadir
Does not work when you use Bundles in 2021.Enschede
Works great with APK.Packard
Is there any solution for .aab file?Baden
F
10

For Android Gradle Plugin 0.13.+ you should use something like this:

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);
            }
        }
    }
}
Fosterfosterage answered 1/10, 2014 at 13:37 Comment(2)
This has stopped working in Android Gradle 3.0.0-alpha1. You can no longer access the outputFile it seems.Afoot
Really useful if you don't want to update your gradle version!Solfatara
I
10

For Android Studio 3.0 you must change from:

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

To:

android.applicationVariants.all { variant ->
        variant.outputs.all { 
            outputFileName = "whatever.apk"
    }
}
Inhume answered 26/10, 2017 at 16:50 Comment(0)
F
7

I did it like this:

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"));
                }

            }
        }
    }
Fanchette answered 5/8, 2015 at 11:35 Comment(1)
What is outputFile??Fume
Q
3

It's weird that you would need this because the apk filename is already different by default.

If you look here at line 1346, you can see that the variantData.variantConfiguration.baseName is used in the outputFile.

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

And the documentation for baseName is

/**
 * Full, unique name of the variant, including BuildType, flavors and test, dash separated.
 * (similar to full name but with dashes)
 */
private String mBaseName;

So running gradle assembleFreeDebug should get you a ProjectName-free-debug.apk file.

But if that isn't the case, or you want a different filename, you can use the following code to customize it.

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);
    }
}
Quinn answered 5/8, 2014 at 11:20 Comment(3)
Almost there. (1) For some reason the -unaligned.apk files in build/outputs/apk still carry the MyApplication prefix. (2) The variant is not capitalized.Alamein
Any idea how to complete this?Alamein
(1) According to line 1316 in the BasePlugin.groovy-link, you can change the project.archivesBaseName and variantData.variantConfiguration.baseName to adapt the unaligned-outputname. But I'm note sure if this will mess with other build-steps. Still, you shouldn't be using the unaligned-version, but rather the final apk (of which you can fully control the apk-name). (2) variant.name.capitalize()Quinn
A
3

Here's my variant (heh) of Lakshman's answer above, not sure why I needed the "variants.outputs.each" but I did.

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");
            }
        }
    }
}
Amboina answered 9/7, 2017 at 1:31 Comment(0)
B
2

This is what you need

android {
    defaultConfig {
        ……

        // custom output apk name
        applicationVariants.all { variant ->
            variant.outputs.all {
                outputFileName = "${variant.productFlavors[0].name}-${variant.buildType.name}-${variant.versionName}.apk"
            }
        }
    }
    ……
}
Burnoose answered 9/10, 2019 at 16:37 Comment(0)
M
1

This work for me:

Add the variant.productFlavors[0].name in the APK name.

Code example:

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")

            }
        }
    }
}
Minerva answered 7/3, 2017 at 10:43 Comment(0)
D
1

Every answer here is the same, and outdated. It's easy to do [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)
        }
    }
}

If your versionName is "1.2.1", running gradle assemble will produce:

Green-1.2.1-debug.apk

Green-1.2.1-release.apk

Blue-1.2.1-debug-apk

Blue-1.2.1-release.apk

Did answered 24/3, 2020 at 19:19 Comment(0)
U
0

Android Gradle Plugin 0.13.0 has deprecated the outputFile that is used in:

applicationVariants.all { variant ->
    def newApkName = variant.name + "my-custom-addition" + ".apk";
    variant.outputFile = new File("${project.buildDir}/outputs/apk/", newApkName);
}

The solution that is working for me is:

android {
... 
}

project.archivesBaseName = "AndroidAppGeneric-${_buildVersionNameForMaven}"
Urethroscope answered 19/9, 2014 at 2:54 Comment(0)
S
0

I'm using the following so the files won't override each other:

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);
    }
}
Snail answered 22/12, 2016 at 11:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.