2

I have recently upgraded to Gradle 3.0 and now find that the feature to rename the output APK has changed. I think I can get around that, but what I am wondering is whether I can still choose the target directory for the APK. We have existing software that uses a specific APK naming convention and directory structure that I want to maintain. Is there a way to do this?

Here is my current gradle build structure (simplified and renamed to protect the innocent):

android {
    compileSdkVersion 25
    buildToolsVersion '25.0.3'
    defaultConfig {
        applicationId "com.mycompany.myapp"
        minSdkVersion 15
        targetSdkVersion 23
        versionCode 23
        versionName "23.23.23"
        compileOptions {
            sourceCompatibility JavaVersion.VERSION_1_7
            targetCompatibility JavaVersion.VERSION_1_7        }
        signingConfig signingConfigs.config
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
            signingConfig signingConfigs.config
        }
    }
    productFlavors.whenObjectAdded { flavor ->
        // Add the property 'myCustomProperty' to each product flavor and set the default value to 'customPropertyValue'
        flavor.ext.set('directoryPath', '')
        flavor.ext.set('apkName', '')
    }
    productFlavors {

        MyCompany {
            signingConfig signingConfigs.config
            directoryPath = mycompany
        }

        Copper {
            applicationId c
            signingConfig signingConfigs.config
            directoryPath = 'copper'
        }

        Steel {
            applicationId 'com.company2.steel'
            signingConfig signingConfigs.config
            directoryPath = 'steel'
        }

        Lead {
            applicationId 'com.company3.coal'
            signingConfig signingConfigs.config
            directoryPath = 'coal'
        }

    }


    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            def path = "C:/AndroidBuilds/MyBuilds/" + variant.productFlavors[0].directoryPath + "/"
            logger.error("Path = " + path)
            def SEP = "-"
            def apkName = variant.productFlavors[0].apkName
            def flavor = variant.productFlavors[0].name
            if (apkName != '')
                flavor = apkName;
            def version = variant.versionCode
            def newApkName = path + version + SEP + flavor
            logger.error("newApkName = " + newApkName)
            output.outputFile = new File(newApkName + ".apk")
        }
    }
}

I know that there is now a "Flavor Dimension" which I will just default (I removed that just to make the code a wee bit clearer). The results of running this build should be that 4 different APKs would be generated and placed in their own directory structures, prefixed with the version number (eg "64-Iron.apk").

The naming is working by replacing with "outputfile", but the directory structure does not. Is there a new way to do this under the latest Gradle?

UPDATE (FIXED)

Thanks to the info provided by selected solution, for completeness, here is the final gradle config (again, cleaned to protect the innocent):

android {
    compileSdkVersion 26
    defaultConfig {
        applicationId "com.mycompany.myapp"
        minSdkVersion 15
        targetSdkVersion 23
        versionCode 23
        versionName "23.23.23"
        compileOptions {
            sourceCompatibility JavaVersion.VERSION_1_7
            targetCompatibility JavaVersion.VERSION_1_7        }
        signingConfig signingConfigs.config
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
            signingConfig signingConfigs.config
        }
    }
    productFlavors.whenObjectAdded { flavor ->
        // Add the property 'myCustomProperty' to each product flavor and set the default value to 'customPropertyValue'
        flavor.ext.set('directoryPath', '')
        flavor.ext.set('apkName', '')
    }
    productFlavors {

        MyCompany {
            signingConfig signingConfigs.config
            directoryPath = mycompany
        }

        Copper {
            applicationId c
            signingConfig signingConfigs.config
            directoryPath = 'copper'
        }

        Steel {
            applicationId 'com.company2.steel'
            signingConfig signingConfigs.config
            directoryPath = 'steel'
        }

        Lead {
            applicationId 'com.company3.coal'
            signingConfig signingConfigs.config
            directoryPath = 'coal'
        }

    }

    applicationVariants.all { variant ->
        variant.outputs.all {
            def apkName = variant.productFlavors[0].apkName
            def flavor = variant.productFlavors[0].name
            if (apkName != '')
                flavor = apkName;
            //add here your logic to customize the name of the apk
            outputFileName = "${variant.versionCode}-${flavor}.apk"
        }
        variant.assemble.doLast { assemble ->
            //copy the apk in another directory, add here your
            //logic to customize the destination folder
            copy {
                from variant.outputs*.outputFile
                into "C:/AndroidBuilds/MyBuilds//${variant.productFlavors[0].directoryPath}"
            }
            //if you don't want to delete the file after copying it comment the line below
            delete variant.outputs*.outputFile
        }
    }
}

Thanks again MatPag!

Stephen McCormick
  • 1,706
  • 22
  • 38

1 Answers1

17

UPDATE: Starting from Gradle 3.3.0 assemble property is deprecated. This is the new way to do this:

applicationVariants.all { variant ->
    variant.outputs.all {
        //add here your logic to customize the name of the apk
        outputFileName = "${variant.name}-${variant.versionName}.apk"
    }
    variant.assembleProvider.configure { assemble ->
        assemble.doLast {
            //copy the apk in another directory, add here your
            //logic to customize the destination folder
            copy {
                from variant.outputs*.outputFile
                //for Windows
                into "C:/my_apks/${variant.dirName}"
            }
            //if you don't want to delete the file after copying it comment the line below
            delete variant.outputs*.outputFile
        }
    }
}

in macOS/Linux you can use something like this for the destination path:

into "${System.properties['user.home']}/my_apks/${variant.dirName}"

OLD ANSWER (for AGP < 3.3.0): I've played a bit with Gradle 4.2.1 and AGP 3.0.0, and a possible solution is this one

applicationVariants.all { variant ->
    variant.outputs.all {
        //add here your logic to customize the name of the apk
        outputFileName = "${variant.name}-${variant.versionName}.apk"
    }
    variant.assemble.doLast { assemble ->
        //copy the apk in another directory, add here your
        //logic to customize the destination folder
        copy {
            from variant.outputs*.outputFile
            into "C:/my_apks/${variant.dirName}"
        }
        //if you don't want to delete the file after copying it comment the line below
        delete variant.outputs*.outputFile
    }
}

I think it's a good starting point to customize the folders based on your needs :)

MatPag
  • 41,742
  • 14
  • 105
  • 114