How to change the generated filename for App Bundles with Gradle?

前端 未结 6 1942
隐瞒了意图╮
隐瞒了意图╮ 2020-11-30 07:47

So to change the generated APK filename inside gradle android I could do something like:

applicationVariants.output.all {
    outputFileName = \"the_file_nam         


        
相关标签:
6条回答
  • 2020-11-30 07:57

    You could use something like this:

    defaultConfig {
      applicationId "com.test.app"
      versionCode 1
      versionName "1.0"
      setProperty("archivesBaseName", applicationId + "-v" + versionCode + "(" + versionName + ")")
    }
    
    0 讨论(0)
  • 2020-11-30 07:58

    Based on Martin Zeitler's answer I did this on Windows:

    Please note that on my setup, .aab files are created in release folder and it deletes everything else in that folder as per this bug report.

    In my app's module gradle:

    apply from: "../utils.gradle"
    
    ...
    
    tasks.whenTaskAdded { task ->
        switch (task.name) {
            case 'bundleRelease':
                task.finalizedBy renameBundle
                break
        }
    }
    

    And in utils.gradle:

    task renameBundle (type: Exec) {
        def baseName = getProperty('archivesBaseName')
    
        def stdout = new ByteArrayOutputStream()
        def stderr = new ByteArrayOutputStream()
    
        commandLine "copy.bat", rootProject.getProjectDir().getAbsolutePath() + "\\release\\${baseName}-release.aab", "<MY_AAB_PATH>\\${baseName}.aab", "D:\\Android\\studio\\release"
        workingDir = rootProject.getProjectDir().getAbsolutePath()
        ignoreExitValue true
        standardOutput stdout
        errorOutput stderr
    
        doLast {
            if (execResult.getExitValue() == 0) {
                println ":${project.name}:${name} > ${stdout.toString()}"
            } else {
                println ":${project.name}:${name} > ${stderr.toString()}"
            }
        }
    }
    

    The copy.bat is created in project's folder and contains this:

    COPY %1 %2
    RMDIR /Q/S %3
    

    Be careful with 3rd argument to make sure you don't use a folder that's important to you.

    EDIT: Why a .BAT for 2 commands you might ask. If you try commandLine "copy", ... on Windows it results in "system does not recognize the command copy". Put anything, like COPY, REN, RENAME, etc, won't work.

    0 讨论(0)
  • 2020-11-30 08:07

    As a more generic way to Martin Zeitlers answer the following will listen for added tasks, then insert rename tasks for any bundle* task that gets added.

    Just add it to the bottom of your build.gradle file.

    Note: It will add more tasks than necessary, but those tasks will be skipped since they don't match any folder. e.g. > Task :app:renameBundleDevelopmentDebugResourcesAab NO-SOURCE

    tasks.whenTaskAdded { task ->
        if (task.name.startsWith("bundle")) {
            def renameTaskName = "rename${task.name.capitalize()}Aab"
            def flavor = task.name.substring("bundle".length()).uncapitalize()
            tasks.create(renameTaskName, Copy) {
                def path = "${buildDir}/outputs/bundle/${flavor}/"
                from(path)
                include "app.aab"
                destinationDir file("${buildDir}/outputs/renamedBundle/")
                rename "app.aab", "${flavor}.aab"
            }
    
            task.finalizedBy(renameTaskName)
        }
    }
    
    0 讨论(0)
  • 2020-11-30 08:14

    Now I've wrote kind of a Exec template for cross-platform CLI execution, no matter what the commandLine is. My RenameTask can detect Linux & Windows, as well as release & debug.

    Property archivesBaseName needs to be defined in defaultConfig:

    android {
        defaultConfig {
            setProperty("archivesBaseName", "SomeApp_" + "1.0.0")
        }
    }
    

    RenameTask extends Exec performs the renaming (not to be confused with type: Rename):

    import javax.inject.Inject
    
    /**
     * App Bundle RenameTask
     * @author Martin Zeitler
    **/
    class RenameTask extends Exec {
        private String buildType
        @Inject RenameTask(String value) {this.setBuildType(value)}
        @Input String getBuildType() {return this.buildType}
        void setBuildType(String value) {this.buildType = value}
        @Override
        @TaskAction
        void exec() {
            def baseName = getProject().getProperty('archivesBaseName')
            def basePath = getProject().getProjectDir().getAbsolutePath()
            def bundlePath = "${basePath}/build/outputs/bundle/${this.getBuildType()}"
            def srcFile = "${bundlePath}/${baseName}-${this.getBuildType()}.aab"
            def dstFile = "${bundlePath}/${baseName}.aab"
            def os = org.gradle.internal.os.OperatingSystem.current()
            if (os.isUnix() || os.isLinux() || os.isMacOsX()) {
                commandLine "mv -v ${srcFile} ${dstFile}".split(" ")
            } else if (os.isWindows()) {
                commandLine "ren ${srcFile} ${dstFile}".split(" ")
            } else {
                throw new GradleException("Cannot move AAB with ${os.getName()}.")
            }
            super.exec()
        }
    }
    

    And it finalizes two other tasks:

    // it defines tasks :renameBundleRelease & :renameBundleDebug
    task renameBundleRelease(type: RenameTask, constructorArgs: ['release'])
    task renameBundleDebug(type: RenameTask, constructorArgs: ['debug'])
    
    // it sets finalizedBy for :bundleRelease & :bundleDebug
    tasks.whenTaskAdded { task ->
        switch (task.name) {
            case 'bundleRelease': task.finalizedBy renameBundleRelease; break
            case   'bundleDebug': task.finalizedBy renameBundleDebug; break
        }
    }
    

    The advance is, that it leaves nothing behind and one can move the files wherever one wants.

    0 讨论(0)
  • 2020-11-30 08:19

    Solution from @SaXXuM works great! Task is not necessary for renaming artifact. You can call setProperty() directly in the android {} block. I prefer to have in the file name:

    • app id
    • module name
    • version name
    • version code
    • date
    • build type

    This is how I use it in my projects:

    build.gradle:

    apply from: "../utils.gradle"
    
    android {
        ...
        setProperty("archivesBaseName", getArtifactName(defaultConfig))
    }
    

    utils.gradle:

    ext.getArtifactName = {
        defaultConfig ->
            def date = new Date().format("yyyyMMdd")
            return defaultConfig.applicationId + "-" + project.name + "-" + defaultConfig.versionName + "-" + defaultConfig.versionCode + "-" + date
    }
    

    The result is: com.example-app-1.2.0-10200000-20191206-release.aab

    It works for both - APK and AAB.

    0 讨论(0)
  • 2020-11-30 08:22

    I've found a much better option to auto increment your app versioning and auto renaming when you generate an apk / aab. Solution as below (do remember to create "version.properties" file on your root folder:

    android {
         ...
         ...
        Properties versionProps = new Properties()
        def versionPropsFile = file("${project.rootDir}/version.properties")
        versionProps.load(new FileInputStream(versionPropsFile))
        def value = 0
        def runTasks = gradle.startParameter.taskNames
        if ('assemble' in runTasks || 'assembleRelease' in runTasks) {
            value = 1
        }
        def versionMajor = 1
        def versionPatch = versionProps['VERSION_PATCH'].toInteger() + value
        def versionBuild = versionProps['VERSION_BUILD'].toInteger() + 1
        def versionNumber = versionProps['VERSION_NUMBER'].toInteger() + value
        versionProps['VERSION_PATCH'] = versionPatch.toString()
        versionProps['VERSION_BUILD'] = versionBuild.toString()
        versionProps['VERSION_NUMBER'] = versionNumber.toString()
        versionProps.store(versionPropsFile.newWriter(), null)
    
        defaultConfig {
        applicationId "com.your.applicationname"
        versionCode versionNumber
        versionName "${versionMajor}.${versionPatch}.${versionBuild}(${versionNumber})"
        archivesBaseName = versionName
        minSdkVersion 26
        targetSdkVersion 29
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        signingConfig signingConfigs.release
        setProperty("archivesBaseName","${applicationId}-v${versionName}")
    
        ...
    }
    

    Credits to this website and this post

    0 讨论(0)
提交回复
热议问题