Android Studio: how to generate signed APK using Gradle? - android

I've searched on Google and SO but cannot find my answer.
This is the first time I'm working with the Gradle system and I am now at the point of generating a signed APK to upload to Google Play (project is imported from eclipse).
Now, I've read the part here that you should add signingConfigs to your build.gradle.
I've added these lines and now I saw that you need to run ./gradlew assembleRelease but running this in my CMD returns
'gradle' is not recognized as an internal or external command,
operable program or batch file.
I've also tried to right click on the build.gradle and run it, saying it was sucessful but once I look in the build/apk folder only a file called app-debug-unaligned.apk.
So, how do I generate the signed APK using the Gradle system?

There are three ways to generate your build as per the buildType. (In your case, it's release but it can be named anything you want.)
Go to Gradle Task in right panel of Android Studio and search for assembleRelease or assemble(#your_defined_buildtype) under Module Tasks
Go to Build Variant in Left Panel and select the build from drop down
Go to project root directory in File Explore and open cmd/terminal and run:
Linux: ./gradlew assembleRelease or assemble(#your_defined_buildtype)
Windows: gradlew assembleRelease or assemble(#your_defined_buildtype)
If you want to do a release build (only), you can use Build > Generate Signed apk. For other build types, only the above three options are available.
You can find the generated APK in your module/build directory having the build type name in it.

It is possible to take any existing Android Studio gradle project and build/sign it from the command line without editing any files. This makes it very nice for storing your project in version control while keeping your keys and passwords separate:
./gradlew assembleRelease -Pandroid.injected.signing.store.file=$KEYFILE -Pandroid.injected.signing.store.password=$STORE_PASSWORD -Pandroid.injected.signing.key.alias=$KEY_ALIAS -Pandroid.injected.signing.key.password=$KEY_PASSWORD

You can use this code
android {
...
signingConfigs {
release {
storeFile file("../your_key_store_file.jks")
storePassword "some_password"
keyAlias "alias_name"
keyPassword "key_password"
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
...
}
then from your terminal run
./gradlew assembleRelease
you will get the apk at
your-android-app/build/outputs/apk/your-android-app-release.apk

I think this can help you https://www.timroes.de/2013/09/22/handling-signing-configs-with-gradle/ then just select the Release from the Build Variants

If you live in certain countries, be sure to use a VPN.
step1: run this command in the command-line:
keytool -genkey -v -keystore ~/key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias key
it will ask you for some information such as password, name,... and enter them.
step2: create a file name key.properties in your android folder.
write these lines in the created file
storePassword=<password from previous step>
keyPassword=<password from previous step>
keyAlias=key
storeFile=<location of the key store file, such as ~/key.jks>
keep the key.properties file private, always keep a backup of the key.properties file and never publish publicly.
step3: Replace the following lines in app-level Gradle
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
android {
signingConfigs {
release {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile file(keystoreProperties['storeFile'])
storePassword keystoreProperties['storePassword']
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
}
step4:
keytool -list -v -keystore ~/key.jks -alias key -storepass <password> -keypass <password>
step5:
I recommend building APK, using android studio.
Build > Generate Signed Bundle/APK...

This is for Kotlin DSL (build.gradle.kts).
You could either define your properties in local.properties file in the project root directory or define them as environment variables (which is especially useful for CIs like GitHub Actions).
// See https://stackoverflow.com/q/60474010
fun getLocalProperty(key: String) = gradleLocalProperties(rootDir).getProperty(key)
fun String?.toFile() = file(this!!)
// Could also use System.getenv("VARIABLE_NAME") to get each variable individually
val environment: Map<String, String> = System.getenv()
android {
signingConfigs {
create("MyAppSigningConfig") {
keyAlias = getLocalProperty("signing.keyAlias") ?: environment["SIGNING_KEY_ALIAS"] ?: error("Error!")
storeFile = (getLocalProperty("signing.storeFile") ?: environment["SIGNING_STORE_FILE"] ?: error("Error!")).toFile()
keyPassword = getLocalProperty("signing.keyPassword") ?: environment["SIGNING_KEY_PASSWORD"] ?: error("Error!")
storePassword = getLocalProperty("signing.storePassword") ?: environment["SIGNING_STORE_PASSWORD"] ?: error("Error!")
enableV1Signing = true
enableV2Signing = true
}
}
buildTypes {
getByName("release") { // OR simply release { in newer versions of Android Gradle Plugin (AGP)
signingConfig = signingConfigs["MyAppSigningConfig"]
// ...
}
}
}
myProject/local.properties file:
signing.keyAlias=foo
signing.keyPassword=bar
# also called keystore
signing.storePassword=abcdefgh
signing.storeFile=C\:\\my-files\\my-keystore.jks
NOTE: Do NOT add your local.properties file to your version control system (like Git), as it exposes your secret information like passwords etc. to the public (if it's a public repository).
Generate your APK with either of the 3 ways that this answer mentioned.

build menu > generate signed apk

Related

Flutter application release is different than debug

I have created an app in flutter using Android studio which I want to deploy.
Flutter version is 2.10.
Dart version is 2.16.0.
When I run or debug main.dart from Android studio everything works as expected.
I have signed the application following the instructions from here:
https://docs.flutter.dev/deployment/android
I have created the keystore using the following command:
"C:\Program Files\Android\Android Studio\jre\bin\keytool" -genkey -v -keystore c:\upload-keystore.jks -keyalg RSA -keysize 2048 -validity 10000 -alias key
Created key.properties file with the following content
storePassword=password from previous step
keyPassword=password from previous step
keyAlias=key
storeFile=location of the key store file, such as /Users/<user name>/upload-keystore.jks
in [project]/android/app/build.gradle added the keystore information before the Android block as follow
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
and replaced
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now,
// so `flutter run --release` works.
signingConfig signingConfigs.debug
}
}
with
signingConfigs {
release {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
storePassword keystoreProperties['storePassword']
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
And after changing the gradle file I ran flutter clean.
After the specified steps the application can still the debugged and can be ran as expected.
I am building a bundle with the following command
flutter build appbundle
The build is successful and I get the output file in
build\app\outputs\bundle\release\app-release.aab
Using bundletool I convert the .aab file to apks and install it on my phone with the following commands:
java -jar "PATH/bundletool-all-1.8.2.jar" build-apks --bundle=PATH/app-release.aab --ks="PATH/upload-keystore.jks" --ks-key-alias=key --output=PATH/app-release.apks
java -jar "PATH/bundletool-all-1.8.2.jar" install-apks --apks=PATH/app-release.apks
where PATH is the path to the directory of the file.
After the app is being installed and launched I get the attached window
which is completely different than the app I wrote.
Can someone please tell me what am I doing wrong?
Best regards,
Stanko
Thanks to Tomas's comment I have found the solution.
Running the following command
flutter run
a different project has been started, so I had to use this instead
flutter run PATH/lib/src/main.dart
which started the correct project, similarly for the app bundle I had to run
flutter build appbundle PATH/lib/src/main.dart
Thank you for your help!
Best wishes,
Stanko

failed to release a signed APK on Android Studio

I am working on a project and when I try to release a signed APK from build.Gradle it gives me this error :
Error:(20, 0) C:\Users\sephn\Downloads\Fingerprint2Sleep-master\signing.properties (The system cannot find the file specified)
Open File
Here is my SigningConfigs:
signingConfigs {
release {
def File signingConfFile = file("../signing.properties")
def Properties signingConf = new Properties()
signingConf.load(new FileInputStream(signingConfFile))
storeFile file(signingConf['C:\\Users\\sephn\\Downloads\\APKs & JKSs\\FingerPrintQuickie.jks'])
storePassword signingConf['MyPassword']
keyAlias signingConf['MyKey']
keyPassword signingConf['MyPassword']
}
}
Try removing all uses of signingConfig and signingConfigs in your build.gradle file. And instead, consider using Android Studio -> Build -> Generate Signed APK, and enter your credentials manually.
Sometimes gradle-based signing scripts do not always work. See also: Android Studio 2.2 - Can no longer create unsigned release builds - "validateSigningReleaseLive FAILED"

Where to store Android KeyStore file for CirlceCi build?

I am trying to configure continuous integration build for my Android app.
I use CircleCi platform for it.
Now I store my apps Keystore.jks file locally, but CircleCi needs it to sign my app.
How can I achieve that without storing the file on my git repository? Or maybe I shouldn't be concerned about that while the repository is private?
My gradle signing configs:
signingConfigs {
if (System.getenv("CIRCLECI")) {
release {
keyAlias '****'
keyPassword '****'
storeFile file(System.getenv("******"))
storePassword '****'
}
}else{
release {
...
}
}
}
My circle.yml :
general:
artifacts:
- /home/ubuntu/my-app/app/build/outputs/apk/
machine:
environment:
ANDROID_HOME: /usr/local/android-sdk-linux
dependencies:
override:
- chmod +x gradlew
test:
override:
- ./gradlew assemble
I tried to save the keystore file on CircleCi as environmental variable but it isn't working, my build fails with exception:
> Execution failed for task ':app:validateSigningDemoRelease'.
> > Keystore file /home/ubuntu/my-app/app/ HERE_IS_THE_KEYSTORE not found for signing config 'release'.
Unsigned and debug builds finish with success.
I'm also open to use any different ci platform if you suggest something else.
Thanks in advance for every advice!
I struggled with this problem recently and decided that the easiest solution was to encode the keystore file to base64 and put it into an environment variable at CircleCI.
This will encode the file and you can copy and paste the value across:
openssl base64 -A -in .signing/release.jks
Then, in your config.yml file at CircleCI, decode it back:
echo $RELEASE_KEYSTORE_BASE64 | base64 -d > .signing/release.jks
if statement does not work in signingConfigs. If you want to sign apk with different keystore for different flavors, you need to create signingConfigs and put signingconfigs into buildTypes section. I did some research about where to store android keystore file in CI/CD Cycle and I come up with three approaches:
Encode keystore file as an environment variable
As #grepx's answer, convert keystore file to base-64 encoded string and save it as an environment variable in CI tools.
Store encrypted keystore file in version control system
Encrypt keystore file and store it in version control system. You can encrypt file with:
openssl aes-256-cbc -e -in keystore.jks -out keystore.jks.encrypted -k SECRET_KEY
You need to decrypt that encrypted keystore file in build step in CI tools:
openssl aes-256-cbc -d -in keystore.jks.encrypted -k $ENCRYPT_SECRET_KEY >> keystore.jks
SECRET_KEY is stored as an environment variable in CI with this key: $ENCRYPT_SECRET_KEY
Download keystore from external source like AWS S3, Google Drive
I've published an article about this topic in medium and you can reach complete example in github to understand better.
For me you have two solutions:
It's a private depot and you're the only one using it, so you can push your key.
My preferred solution would be to create another key that you call circleCI (for example) and that you push. Personally I use this solution
My build.gradle
signingConfigs {
Keys {
keyAlias 'mykey'
storeFile file('../private_key/upload_key.jks')
keyPassword ''
storePassword ''
}
Circleci {
keyAlias 'key'
storeFile file('../private_key/debug_key.jks')
keyPassword ''
storePassword ''
}
}
buildTypes {
release {
shrinkResources true
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'),
'proguard-rules.pro'
signingConfig signingConfigs.Keys
}
debug {
signingConfig signingConfigs.Keys
}
circleci{
signingConfig signingConfigs.Circleci
}
}
According to this link you have to encrypt the file like this:
openssl aes-256-cbc -a -salt -in secrets.txt -out secrets.txt.enc
and for the decryption:
openssl aes-256-cbc -a -salt -in secrets.txt.enc -out secrets.txt.new

How to sign android apk using jenkins

I have my keystore release.keystore in the path /home/ankit/keystores/release.keystore. I want to use the keypair aliased as example for signing an app that is built using Jenkins. However, I am unable to feed the address of the keystore in the Jenkins. Below is the screenshot:
As it can be seen, there is a drop down list against the key store label and it has no item. I tried to follow the official doc but I didn't get it.
I think I have to link the existing keypair somehow to Jenkins, so that it shows up in the drop down list. But I can't figure how.
Instead you could configure this all in gradle itself, which will work independent of any CI. First create a build.properties in root of your project and include following:
#Key store
keystore.release=../keys/release.keystore
keystore.debug=../keys/debug.keystore
keystore.key.alias=...
keystore.key.password=...
keystore.password=...
Now in your app modules build.gradle access those props:
final Properties props = new Properties()
props.load(new FileInputStream('build.properties'))
android {
signingConfigs {
release {
keyAlias props['keystore.key.alias']
keyPassword props['keystore.key.password']
storeFile file(props['keystore.release'])
storePassword props['keystore.password']
}
debug {
storeFile file(props['keystore.debug'])
}
}
buildTypes {
release {
...
signingConfig signingConfigs.release
}
debug {
...
signingConfig signingConfigs.debug
}
}
}
Now make sure it works in your local machine with ./gradlew clean assembleRelease (There's something else if you do in PC)
After that commit the changes and update the gradle build settings in your CI. And make sure those keystores are there.
From the Android Signing Jenkins Plugin documentation:
Before adding a Sign Android APKs build step to a job, you must configure a certificate credential using the Credentials Plugin's UI.
If you need more details about how to use the Credentials Plugin in Jenkins, here is the user guide.

What is the equivalent of Eclipse "Custom debug Keystore" in Android studio?

As I am working with Google Maps API, I have been used to work with a custom debug key in Eclipse (that is in fact my production key)
This manipulation allowed me to use the same API key for Maps and most of Google Play Services (in app billing) in my debug and release build.
This was really convenient because there was no need to change the key in the manifest.
Unfortunately, with the migration to Android Studio, I am missing this feature.
Any idea where I can find this option back?
Thank a lot.
You define a keystore in your build.gradle file. See the Signing Configurations section here: https://developer.android.com/studio/build/index.html
In your case, you want to redefine the keystore for the debug variant:
android {
signingConfigs {
debug {
storeFile file("your.keystore")
}
}
}
However, you should really be using two different keystores for debug and release configurations.
On recent Android Studio 0.8.9 you will find this at a way better place:
File->Project Structure
Add a keystore at "Signing" Tab
Select it for your debug/release "Build types".
Make sure the alias name matchs with your keystore (keytool -list -v shows your alias name)
It creates the gradle stuff, syncrhonizes automatically on "Apply" and worked immediately like a charm.
Hi If you don't want to go for hard code all of this stuff , then go for below easy steps
->Your project
->Your Module
->Right click on your module
->go to open module settings
->Go to Signing section
->Specify all the attribute here and browse your Custom debug key in Store File
Then you will find below code which will be auto-create by android studio in build.gradle
signingConfigs {
debug {
storeFile file('custom_debug_keystore')
keyAlias 'androiddebugkey'
keyPassword 'android'
storePassword 'android'
}
}
Note:
1) Please do not use .keystore in the code manually you go for manual configuration
2) Please specify correct Alias and password
Here is a complete step-by-step that I took to move both of my keys out of the gradle.build file into a file that will not be included in any builds or repository commits.
1) Create a gradle.properties (if you don't already have one).
The location for this file depends on your OS:
/home/<username>/.gradle/ (Linux)
/Users/<username>/.gradle/ (Mac)
C:\Users\<username>\.gradle (Windows)
2) Add an entry pointing to yourprojectname.properties file.
(example for Windows)
yourprojectname.properties=c:\\Users\\<username>\\signing\\yourprojectname.properties
3) Create yourprojectname.properties file in the location you specified in Step 2 with the following information:
keystore=C:\\path\\to\\keystore\\yourapps.keystore
keystore.password=your_secret_password
4) Modify your gradle.build file to point to yourprojectname.properties file to use the variables.
if(project.hasProperty("yourprojectname.properties")
&& new File(project.property("yourprojectname.properties")).exists()) {
Properties props = new Properties()
props.load(new FileInputStream(file(project.property("yourprojectname.properties"))))
android {
signingConfigs {
release {
keyAlias 'release'
keyPassword props['keystore.password']
storeFile file(props['keystore'])
storePassword props['keystore.password']
}
debug {
keyAlias 'debug'
keyPassword props['keystore.password']
storeFile file(props['keystore'])
storePassword props['keystore.password']
}
}
compileSdkVersion 19
buildToolsVersion "20.0.0"
defaultConfig {
applicationId "your.project.app"
minSdkVersion 16
targetSdkVersion 17
}
buildTypes {
release {
}
}
}
}
dependencies {
...
}
5) Enjoy! Now all of your keys will be outside of the root of the directory and yet you still have the joys of automation for each build.
If you get an error in your gradle.build file about the "props" variable it's because you are not executing the "android {}" block inside the very first if condition where the props variable gets assigned so just move the entire android{ ... } section into the condition in which the props variable is assigned then try again.
I pieced these steps together from the information found here and here.
You can specify the debug.keystore for your project independently.
Two steps with the following images: (Android Studio v0.5.2)
Step 1: Click the button of project structure.
Step 2: Add the debug.keystore as follows.
The keystore needs to be in build.gradle, example follows:
android{
signingConfigs {
release {
storeFile file('/path/platform.keystore')
storePassword 'android'
keyAlias 'androiddebugkey'
keyPassword 'android'
}
}
...
buildTypes {
release {
signingConfig signingConfigs.release
}
}
Eclipse didn't really ask for a password or alias, but gradle does. I believe Eclipse just assumed it was password:android and alias:androiddebugkey. This might not be true for your keystore but I would try it like that on gradle.
If you know the password, but you are not sure of the alias you can also run the following command to get the alias:
keytool -list -keystore /path/platform.keystore link
As pointed out, you can use the gradle file to specify it.
I also found very convenient to use the Home folder as part of the path. It makes it easier when working within a team. Here is my suggestion :
android {
signingConfigs {
debug {
storeFile file(System.properties['user.home']+"/.android/custom.debug.keystore")
}
}
}

Categories

Resources