How to create a release signed apk file using Gradle?

I would like to have my Gradle build to create a release signed apk file using Gradle.

I'm not sure if the code is correct or if I'm missing a parameter when doing gradle build?

This is some of the code in my gradle file:

android {
    ...
    signingConfigs {
          release {
              storeFile file("release.keystore")
              storePassword "******"
              keyAlias "******"
              keyPassword "******"
         }
     }
}

The gradle build finishes SUCCESSFUL, and in my build/apk folder I only see the ...-release-unsigned.apk and ...-debug-unaligned.apk files.

Any suggestions on how to solve this?


Solution 1:

Easier way than previous answers:

Put this into ~/.gradle/gradle.properties

RELEASE_STORE_FILE={path to your keystore}
RELEASE_STORE_PASSWORD=*****
RELEASE_KEY_ALIAS=*****
RELEASE_KEY_PASSWORD=*****

Modify your app/build.gradle, and add this inside the android { code block:

...    
signingConfigs {

   release {
       storeFile file(RELEASE_STORE_FILE)
       storePassword RELEASE_STORE_PASSWORD
       keyAlias RELEASE_KEY_ALIAS
       keyPassword RELEASE_KEY_PASSWORD

       // Optional, specify signing versions used
       v1SigningEnabled true
       v2SigningEnabled true
   }
}

buildTypes {
        release {
            signingConfig signingConfigs.release
        }
}
....

Then you can run gradle assembleRelease


Also see the reference for the signingConfigs Gradle DSL

Solution 2:

I managed to solve it adding this code, and building with gradle build:

android {
    ...
    signingConfigs {
        release {
            storeFile file("release.keystore")
            storePassword "******"
            keyAlias "******"
            keyPassword "******"
        }
    }
    buildTypes {
        release {
            signingConfig signingConfigs.release
        }
    }
}

This generates a signed release apk file.

Solution 3:

Note that @sdqali's script will (at least when using Gradle 1.6) ask for the password anytime you invoke any gradle task. Since you only need it when doing gradle assembleRelease (or similar), you could use the following trick:

android {
    ...
    signingConfigs {
        release {
            // We can leave these in environment variables
            storeFile file(System.getenv("KEYSTORE"))
            keyAlias System.getenv("KEY_ALIAS")

            // These two lines make gradle believe that the signingConfigs
            // section is complete. Without them, tasks like installRelease
            // will not be available!
            storePassword "notYourRealPassword"
            keyPassword "notYourRealPassword"
        }
    }
    ...
}

task askForPasswords << {
    // Must create String because System.readPassword() returns char[]
    // (and assigning that below fails silently)
    def storePw = new String(System.console().readPassword("Keystore password: "))
    def keyPw  = new String(System.console().readPassword("Key password: "))

    android.signingConfigs.release.storePassword = storePw
    android.signingConfigs.release.keyPassword = keyPw
}

tasks.whenTaskAdded { theTask -> 
    if (theTask.name.equals("packageRelease")) {
        theTask.dependsOn "askForPasswords"
    }
}

Note that I also had to add the following (under android) to make it work:

buildTypes {
    release {
        signingConfig signingConfigs.release
    }
}

Solution 4:

If you want to avoid hardcoding your keystore & password in build.gradle, you can use a properties file as explained here: HANDLING SIGNING CONFIGS WITH GRADLE

Basically:

1) create a myproject.properties file at /home/[username]/.signing with such contents:

keystore=[path to]\release.keystore
keystore.password=*********
keyAlias=***********
keyPassword=********

2) create a gradle.properties file (perhaps at the root of your project directory) with the contents:

MyProject.properties=/home/[username]/.signing/myproject.properties

3) refer to it in your build.gradle like this:

    if(project.hasProperty("MyProject.properties")
        && new File(project.property("MyProject.properties")).exists()) {

    Properties props = new Properties()
    props.load(new FileInputStream(file(project.property("MyProject.properties"))))

    signingConfigs {
        release {
            storeFile file(props['keystore'])
            storePassword props['keystore.password']
            keyAlias props['keyAlias']
            keyPassword props['keyPassword']
        }
    }
}