简体   繁体   中英

How to set versionName in APK filename using gradle?

I'm trying to set a specific version number in the gradle auto-generated APK filename.

Now gradle generates myapp-release.apk but I want it to look something like myapp-release-1.0.apk .

I have tried renaming options that seems messy. Is there a simple way to do this?

buildTypes {
    release {
       signingConfig signingConfigs.release
       applicationVariants.each { variant ->
       def file = variant.outputFile
       variant.outputFile = new File(file.parent, file.name.replace(".apk", "-" +    defaultConfig.versionName + ".apk"))
    }
}

I have tried the code above with no luck. Any suggestions? (using gradle 1.6)

I only have to change the version name in one place. The code is simple too.

The examples below will create apk files named named MyCompany-MyAppName-1.4.8-debug.apk or MyCompany-MyAppName-1.4.8-release.apk depending on the build variant selected.

Note that this solution works on both APK and App Bundles (.aab files) .

See Also: How to change the proguard mapping file name in gradle for Android project

#Solution for Recent Gradle Plugin

android {
    compileSdkVersion 22
    buildToolsVersion "22.0.1"
    defaultConfig {
        applicationId "com.company.app"
        minSdkVersion 13
        targetSdkVersion 21
        versionCode 14       // increment with every release
        versionName '1.4.8'   // change with every release
        setProperty("archivesBaseName", "MyCompany-MyAppName-$versionName")
    }
}

The above solution has been tested with the following Android Gradle Plugin Versions:

  • 3.6.4 (August 2020)
  • 3.5.2 (November 2019)
  • 3.3.0 (January 2019)
  • 3.1.0 (March 2018)
  • 3.0.1 (November 2017)
  • 3.0.0 (October 2017)
  • 2.3.2 (May 2017)
  • 2.3.1 (April 2017)
  • 2.3.0 (February 2017)
  • 2.2.3 (December 2016)
  • 2.2.2
  • 2.2.0 (September 2016)
  • 2.1.3 (August 2016)
  • 2.1.2
  • 2.0.0 (April 2016)
  • 1.5.0 (2015/11/12)
  • 1.4.0-beta6 (2015/10/05)
  • 1.3.1 (2015/08/11)

I'll update this post as new versions come out.

#Solution Tested Only on versions 1.1.3-1.3.0 The following solution has been tested with the following Android Gradle Plugin Versions:

  • 1.3.0 (2015/07/30) - Not Working, bug scheduled to be fixed in 1.3.1
  • 1.2.3 (2015/07/21)
  • 1.2.2 (2015/04/28)
  • 1.2.1 (2015/04/27)
  • 1.2.0 (2015/04/26)
  • 1.2.0-beta1 (2015/03/25)
  • 1.1.3 (2015/03/06)

app gradle file:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.2"
    defaultConfig {
        applicationId "com.company.app"
        minSdkVersion 13
        targetSdkVersion 21
        versionCode 14       // increment with every release
        versionName '1.4.8'   // change with every release
        archivesBaseName = "MyCompany-MyAppName-$versionName"
    }
}

This solved my problem: using applicationVariants.all instead of applicationVariants.each

buildTypes {
      release {
        signingConfig signingConfigs.release
        applicationVariants.all { variant ->
            def file = variant.outputFile
            variant.outputFile = new File(file.parent, file.name.replace(".apk", "-" + defaultConfig.versionName + ".apk")) 
        }
    }       
}

Update:

So it seems this does not work with 0.14+ versions of android studio gradle plugin.

This does the trick (Reference from this question ):

android {
    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            output.outputFile = new File(
                    output.outputFile.parent,
                    output.outputFile.name.replace(".apk", "-${variant.versionName}.apk"))
        }
    }
}

(EDITED to work with Android Studio 3.0 and Gradle 4)

I was looking for a more complex apk filename renaming option and I wrote this one in the hope it is helpfull for anyone else. It renames the apk with the following data:

  • flavor
  • build type
  • version
  • date

It took me a bit of research in gradle classes and a bit of copy/paste from other answers. I am using gradle 3.1.3 .

In the build.gradle:

android {

    ...

    buildTypes {
        release {
            minifyEnabled true
            ...
        }
        debug {
            minifyEnabled false
        }
    }

    productFlavors {
        prod {
            applicationId "com.feraguiba.myproject"
            versionCode 3
            versionName "1.2.0"
        }
        dev {
            applicationId "com.feraguiba.myproject.dev"
            versionCode 15
            versionName "1.3.6"
        }
    }

    applicationVariants.all { variant ->
        variant.outputs.all { output ->
            def project = "myProject"
            def SEP = "_"
            def flavor = variant.productFlavors[0].name
            def buildType = variant.variantData.variantConfiguration.buildType.name
            def version = variant.versionName
            def date = new Date();
            def formattedDate = date.format('ddMMyy_HHmm')

            def newApkName = project + SEP + flavor + SEP + buildType + SEP + version + SEP + formattedDate + ".apk"

            outputFileName = new File(newApkName)
        }
    }
}

If you compile today (13-10-2016) at 10:47, you get the following file names depending on the flavor and build type you have choosen:

  • dev debug : myProject_ dev_debug_1.3.6 _131016_1047.apk
  • dev release : myProject_ dev_release_1.3.6 _131016_1047.apk
  • prod debug : myProject_ prod_debug_1.2.0 _131016_1047.apk
  • prod release : myProject_ prod_release_1.2.0 _131016_1047.apk

Note: the unaligned version apk name is still the default one.

To sum up, for those don't know how to import package in build.gradle (like me), use the following buildTypes ,

buildTypes {
      release {
        signingConfig signingConfigs.release
        applicationVariants.all { variant ->
            def file = variant.outputFile
            def manifestParser = new com.android.builder.core.DefaultManifestParser()
            variant.outputFile = new File(file.parent, file.name.replace(".apk", "-" + manifestParser.getVersionName(android.sourceSets.main.manifest.srcFile) + ".apk")) 
        }
    }       
}

===== EDIT =====

If you set your versionCode and versionName in your build.gradle file like this:

defaultConfig {
    minSdkVersion 15
    targetSdkVersion 19
    versionCode 1
    versionName "1.0.0"
}

You should set it like this:

buildTypes {   
        release {
            signingConfig signingConfigs.releaseConfig
            applicationVariants.all { variant ->
                def file = variant.outputFile
                variant.outputFile = new File(file.parent, file.name.replace(".apk", "-" + defaultConfig.versionName + ".apk"))
            }
        }
}


====== EDIT with Android Studio 1.0 ======

If you are using Android Studio 1.0, you will get an error like this:

Error:(78, 0) Could not find property 'outputFile' on com.android.build.gradle.internal.api.ApplicationVariantImpl_Decorated@67e7625f.

You should change the build.Types part to this:

buildTypes {
        release {
            signingConfig signingConfigs.releaseConfig
            applicationVariants.all { variant ->
                variant.outputs.each { output ->
                    output.outputFile = new File(output.outputFile.parent, output.outputFile.name.replace(".apk", "-" + defaultConfig.versionName + ".apk"))
                }
            }
        }
    }

If you don't specify versionName in defaultConfig block then defaultConfig.versionName will result in null

to get versionName from manifest you can write following code in build.gradle:

import com.android.builder.DefaultManifestParser

def manifestParser = new DefaultManifestParser()
println manifestParser.getVersionName(android.sourceSets.main.manifest.srcFile)

Gradle 6+

I'm now using the following in Android Studio 4.0 and Gradle 6.4:

android {
    defaultConfig {
        applicationId "com.mycompany.myapplication"
        minSdkVersion 21
        targetSdkVersion 29
        versionCode 15
        versionName "2.1.1"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            applicationVariants.all { variant ->
                variant.outputs.all {
                    outputFileName = "ApplicationName-${variant.name}-${variant.versionName}.apk"
                }
            }
        }
    }
}

Gradle 4

Syntax has changed a bit in Gradle 4 (Android Studio 3+) (from output.outputFile to outputFileName , idea from this answer is now:

android {
    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            def newName = outputFileName
            newName.replace(".apk", "-${variant.versionName}.apk")
            outputFileName = new File(newName)
        }
    }
}

In my case, I just wanted to find a way to automate the generation of different apk name for release and debug variants. I managed to do this easily by putting this snippet as a child of android :

applicationVariants.all { variant ->
    variant.outputs.each { output ->
        def appName = "My_nice_name_"
        def buildType = variant.variantData.variantConfiguration.buildType.name
        def newName
        if (buildType == 'debug'){
            newName = "${appName}${defaultConfig.versionName}_dbg.apk"
        } else {
            newName = "${appName}${defaultConfig.versionName}_prd.apk"
        }
        output.outputFile = new File(output.outputFile.parent, newName)
    }
}

For the new Android gradle plugin 3.0.0 you can do something like that:

 applicationVariants.all { variant ->
    variant.outputs.all {
        def appName = "My_nice_name_"
        def buildType = variant.variantData.variantConfiguration.buildType.name
        def newName
        if (buildType == 'debug'){
            newName = "${appName}${defaultConfig.versionName}_dbg.apk"
        } else {
            newName = "${appName}${defaultConfig.versionName}_prd.apk"
        }
        outputFileName = newName
    }
}

This produce something like: My_nice_name_3.2.31_dbg.apk

Another alternative is to use the following:

String APK_NAME = "appname"
int VERSION_CODE = 1
String VERSION_NAME = "1.0.0"

project.archivesBaseName = APK_NAME + "-" + VERSION_NAME;

    android {
      compileSdkVersion 21
      buildToolsVersion "21.1.1"

      defaultConfig {
        applicationId "com.myapp"
        minSdkVersion 15
        targetSdkVersion 21
        versionCode VERSION_CODE
        versionName VERSION_NAME
      }

       .... // Rest of your config
}

This will set "appname-1.0.0" to all your apk outputs.

The right way to rename apk, as per @Jon answer

defaultConfig {
        applicationId "com.irisvision.patientapp"
        minSdkVersion 24
        targetSdkVersion 22
        versionCode 2  // increment with every release
        versionName "0.2" // change with every release
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        //add this line
        archivesBaseName = "AppName-${versionName}-${new Date().format('yyMMdd')}"
    }   

Or another way you can achieve same results with

android {
    ...

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    applicationVariants.all { variant ->
        variant.outputs.all { output ->
            def formattedDate = new Date().format('yyMMdd')
            outputFileName = "${outputFileName.replace(".apk","")}-v${defaultConfig.versionCode}-${formattedDate}.apk"
        }
    }
}

There are many answers that are correct either in full or after some modifications. But I am going to add mine anyway since I was having the problem with all of them because I was using scripts to generate VersionName and VersionCode dynamically by hooking into the preBuild task.

If you are using some similar approach this is the the code that will work:

project.android.applicationVariants.all { variant ->
    variant.preBuild.doLast {
    variant.outputs.each { output ->
        output.outputFile = new File(
                output.outputFile.parent,
                output.outputFile.name.replace(".apk", "-${variant.versionName}@${variant.versionCode}.apk"))
        }
    }
}

To explain: Since I am overriding version code and name in the first action of preBuild I have to add the file renaming to the end of this task. So what gradle will do in this case is:

Inject version code/name-> do preBuild actions -> replace name for apk

    applicationVariants.all { variant ->
        variant.outputs.all { output ->
            output.outputFileName = output.outputFileName.replace(".apk", "-${variant.versionName}.apk")
        }
    }

In my case I solve this error this way

adding a SUFFIX to the Debug version, in this case I adding the "-DEBUG" text to my Debug deploy

 buildTypes {
        release {

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


        }
        debug {

            defaultConfig {
                debuggable true

                versionNameSuffix "-DEBUG"
            }
        }
    }

For latest gradle versions you can use following snippet:

Set your application manifest location first

 sourceSets {
        main {
            manifest.srcFile 'src/main/AndroidManifest.xml'
        {
    }

And later on in build.gradle

import com.android.builder.core.DefaultManifestParser

def getVersionName(manifestFile) {
    def manifestParser = new DefaultManifestParser();
    return manifestParser.getVersionName(manifestFile);
}

def manifestFile = file(android.sourceSets.main.manifest.srcFile);
def version = getVersionName(manifestFile)

buildTypes {
    release {
       signingConfig signingConfigs.release
       applicationVariants.each { variant ->
       def file = variant.outputFile
       variant.outputFile = new File(file.parent, file.name.replace(".apk", "-" +    versionName + ".apk"))
    }
}

Adjust if you have different manifests per build type. but since I have the single one - works perfectly for me.

As of Android Studio 1.1.0, I found this combination worked in the android body of the build.gradle file. This is if you can't figure out how to import the manifest xml file data. I wish it was more supported by Android Studio, but just play around with the values until you get the desired apk name output:

defaultConfig {
        applicationId "com.package.name"
        minSdkVersion 14
        targetSdkVersion 21
        versionCode 6
        versionName "2"
    }
    signingConfigs {
        release {
            keyAlias = "your key name"
        }
    }
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

            signingConfig signingConfigs.release
            applicationVariants.all { variant ->
                variant.outputs.each { output ->
                    output.outputFile = new File(output.outputFile.parent, output.outputFile.name.replace("app-release.apk", "appName_" + versionName + ".apk"))
                }
            }
        }
    }

As I answered here If you want to append the version name and version code to the output file do it like:

applicationVariants.all { variant ->
        variant.outputs.all {
            def versionName = variant.versionName
            def versionCode = variant.versionCode
            def variantName = variant.name
            outputFileName = "${rootProject.name}" + '_' + variantName + '_' + versionName + '_' + versionCode + '.apk'
        }
    }

You can also add formatted build time to apk name as below:

setProperty("archivesBaseName", "data-$versionName " + (new Date().format("HH-mm-ss")))

Here is how you can do it in the Kotlin DSL:

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

        val apkName = outputFileName.replace(".apk", "-" + defaultConfig.versionName + ".apk")

        outputFileName = apkName
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM