45

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?

simbabque
  • 53,749
  • 8
  • 73
  • 136
Gie
  • 1,907
  • 2
  • 24
  • 49
  • 2
    I suspect that you do not want to be iterating over `applicationVariants`, but rather only those variants tied to `staging`. I am not sufficiently familiar with the Gradle for Android object model to tell you specifically what you would use, though. – CommonsWare Mar 02 '14 at 10:25

8 Answers8

37

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)
    }
}
Leszek
  • 6,568
  • 3
  • 42
  • 53
  • 2
    Thanks, now it works. I've only introduced small modification to the condition. Now it looks like: if(variant.buildType.name == android.buildTypes.staging.name). – Gie Mar 02 '14 at 11:22
20

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)
    }
}
Community
  • 1
  • 1
Piotr Zawadzki
  • 1,678
  • 1
  • 18
  • 24
  • Nice. Where did you find the documentation (or any hint/explication) for the new variant api (ie the outputs property)? – Julien Arzul Nov 26 '14 at 15:43
  • I googled it and came across this: http://stackoverflow.com/questions/25997866/gradle-warning-variant-getoutputfile-and-variant-setoutputfile-are-deprecat/26297636#26297636 ;) – Piotr Zawadzki Dec 01 '14 at 08:00
  • 2
    I have the latest gradle and android studio version but interestingly I get the error message "could not find property "outputs" when trying above snippet. – AgentKnopf Jan 19 '15 at 20:02
  • 2
    There was further changes in AS 1.1, you can find an updated script here: http://stackoverflow.com/questions/24649240/build-release-apk-with-customize-name-format-in-android-studio – 3c71 Mar 21 '15 at 16:05
  • ugh - can someone please tell these developers to keep their APIs consistent for more than a few months! – Bron Davies Aug 18 '15 at 19:17
4

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
Tejas Soni
  • 404
  • 3
  • 4
3

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")
Veniamin
  • 774
  • 5
  • 12
0

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

Community
  • 1
  • 1
Qamar
  • 4,959
  • 1
  • 30
  • 49
0

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"))
            }
        }
Droid Chris
  • 3,455
  • 28
  • 31
0

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
        }
}


0

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"
        }
    }
Arthur Melo
  • 454
  • 5
  • 13