Question

I have an Android project which uses Gradle for build process. Now I want to add two extra build types staging and production, so my build.gradle contains:

android {
    buildTypes {
        release {
            runProguard false
            proguardFile getDefaultProguardFile('proguard-android.txt')
        }

        staging {
            signingConfig signingConfigs.staging

            applicationVariants.all { variant ->
                appendVersionNameVersionCode(variant, defaultConfig)
            }
        }

        production {
            signingConfig signingConfigs.production
        }
    }
}

and my appndVersionNameVersionCode looks like:

def appendVersionNameVersionCode(variant, defaultConfig) {
    if(variant.zipAlign) {
        def file = variant.outputFile
        def fileName = file.name.replace(".apk", "-" + defaultConfig.versionName + "-" + defaultConfig.versionCode + ".apk")
        variant.outputFile = new File(file.parent, fileName)
    }

    def file = variant.packageApplication.outputFile
    def fileName = file.name.replace(".apk", "-" + defaultConfig.versionName + "-" + defaultConfig.versionCode + ".apk")
    variant.packageApplication.outputFile = new File(file.parent, fileName)
}

If I execute task assembleStaging then I get proper name of my apk, but when I execute assembleProduction then I get changed names of my apk (like in staging case). For example:

MyApp-defaultFlavor-production-9.9.9-999.apk
MyApp-defaultFlavor-production-9.9.9-999.apk

It looks like in production build type is executed appendVersionNameVersionCode. How can I avoid it?

Was it helpful?

Solution

As CommonsWare wrote in his comment, you should call appendVersionNameVersionCode only for staging variants. You can easily do that, just slightly modify your appendVersionNameVersionCode method, for example:

def appendVersionNameVersionCode(variant, defaultConfig) {
    //check if staging variant
    if(variant.name == android.buildTypes.staging.name){
        if(variant.zipAlign) {
            def file = variant.outputFile
            def fileName = file.name.replace(".apk", "-" + defaultConfig.versionName + "-" + defaultConfig.versionCode + ".apk")
            variant.outputFile = new File(file.parent, fileName)
        }

    def file = variant.packageApplication.outputFile
    def fileName = file.name.replace(".apk", "-" + defaultConfig.versionName + "-" + defaultConfig.versionCode + ".apk")
    variant.packageApplication.outputFile = new File(file.parent, fileName)
    }
}

OTHER TIPS

Lecho's solution doesn't work for Android Gradle Plugin 0.14.3+ because of removal of deprecated APIS: http://tools.android.com/tech-docs/new-build-system

Almost 1.0: removed deprecated properties/methods

...

  • Variant.packageApplication/zipAlign/createZipAlignTask/outputFile/processResources/processManifest (use the variant output)

The following works for me:

def appendVersionNameVersionCode(variant, defaultConfig) {
    variant.outputs.each { output ->
        if (output.zipAlign) {
            def file = output.outputFile
            def fileName = file.name.replace(".apk", "-" + defaultConfig.versionName + "-" + defaultConfig.versionCode + ".apk")
            output.outputFile = new File(file.parent, fileName)
        }

        def file = output.packageApplication.outputFile
        def fileName = file.name.replace(".apk", "-" + defaultConfig.versionName + "-" + defaultConfig.versionCode + ".apk")
        output.packageApplication.outputFile = new File(file.parent, fileName)
    }
}

For newer android studio Gradle

AppName is your app name you want so replace it
variantName will be default Selected variant or flavor
Date will Today's date, So need to do any changes just paste it

applicationVariants.all { variant ->
    variant.outputs.all {
        def variantName = variant.name
        def versionName = variant.versionName
        def formattedDate = new Date().format('dd-MM-YYYY')
        outputFileName = "AppName_${variantName}_D_${formattedDate}_V_${versionName}.apk"
    }
}

Output:

AppName_release_D_26-04-2021_V_1.2.apk

I have use little generic version of it. build and install fine. for example your projectName is "Salad" then for staging apk name will be "Salad-staging-dd-MM-YY" you can also change for debug and release apk. hope my solution will be better.
Change in projectName/app/build.gradle

buildTypes {

debug{

}

staging{
 debuggable true
 signingConfig signingConfigs.debug
 applicationVariants.all { variant ->
 variant.outputs.each { output ->
 def date = new Date();
 def formattedDate = date.format('dd-MM-yyyy')
 def appName = getProjectDir().getParentFile().name
 output.outputFile = new File(output.outputFile.parent,
                                output.outputFile.name.replace(getProjectDir().name +"-staging", "$appName-staging-" + formattedDate)
                                //for Debug use output.outputFile = new File(output.outputFile.parent,
                                //                             output.outputFile.name.replace("-debug", "-" + formattedDate)
                        )
  }
 }
}

release {
  minifyEnabled false
 proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}

to change Android app name ref

Here is what I have done:

 def appName
        if (project.hasProperty("applicationName")) {
            appName = applicationName
        } else {
            appName = parent.name
        }
        applicationVariants.all { variant ->
            variant.outputs.each { output ->
                output.outputFile = new File(output.outputFile.parent, output.outputFile.name.replace("app-release.apk", appName + "_V" + versionCode + ".apk"))
            }
        }

i successfully create apk in android studio 4.1v or above. application level gradle Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    ext.kotlin_version = '1.3.11'
    ext.play_services_version = '16.0.0'
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.6.4'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        
    }
}

allprojects {
    repositories {
        google()
        jcenter()
        maven {
            url "https://maven.google.com"
        }
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}


//..............and another module level gradle within........//
buildTypes{
release {

            def versionCode = "4.1.0"

            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
            applicationVariants.all { variant ->
                variant.outputs.all() { output ->
                    variant.productFlavors.each { flavor ->
                        def appName = "MyAPP" + versionCode + ".apk"
                        outputFileName = new File("./build/",
                                appName.replace(".apk", "_${flavor.name}.apk")
                        )
                    }
                }
            }
        }
        debug {
           // ext.enableCrashlytics = false
           // ext.alwaysUpdateBuildId = false
        }
}


If you use Kotlin DSL, then here is how you can change the APK name:

    applicationVariants.all {
        outputs.all {
            this as com.android.build.gradle.internal.api.ApkVariantOutputImpl

            val buildName = buildType.name
            val timestamp = SimpleDateFormat("yyyyMMdd").format(Date())
            val apkName = timestamp + "_AppName_" + defaultConfig.versionName + "." + defaultConfig.versionCode + "_" + buildName + ".apk"

            outputFileName = apkName
        }
    }

If you don't want to use the timestamp, remove it. Otherwise, don't forget these lines on top of the file to import java classes:

import java.util.Date
import java.text.SimpleDateFormat

You can also compare the build name in order to specify a config for different builds, like so:

name == "debug"
/* or */
name.contains("release")

Im using gradle 7.5
my version of the filename consists in :

applicationVariants.all { variant ->
        println("Generating variant: " + variant.getName())
        variant.outputs.all { output ->
            def variantName = variant.name
            def versionName = variant.versionName
            def formattedDate = new Date().format('dd_MM_YY')
            output.versionCodeOverride = defaultConfig.versionCode * 10 + variant.productFlavors.get(0).abiVersionCode
            //output.outputFileName = "${defaultConfig.applicationId}.${variantName}_v${versionName}_${defaultConfig.versionCode}.apk"
            output.outputFileName = "${variantName}_v${versionName}_${defaultConfig.versionCode}_${formattedDate}.apk"
        }
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top