Signature Configuration of Android studio

Posted by immot on Sat, 22 Jun 2019 20:00:32 +0200

We can create a new project and then generate a new signature file.  
Generally speaking, after these operations, we can package by clicking Build - > Generate Signed APK - > Next in the upper left corner, and then selecting the corresponding Build Type.

That's too much trouble for some people. They have to input relevant information and make choices every time. How can they bear it?  
So is there a simpler and faster way? The answer is yes.

We can configure signatures in build.gradle under the app directory of the project.  
First, we find android {} under build.gradle. The default configuration is as follows

Next, we can change the preview mode of the project to Project, or unchanged, just put the signature file we just generated into the corresponding directory. My approach is to put it directly under the project, as shown in the figure.

Then, go back to build.gradle under app and add this code to it.

signingConfigs {
        debug {
            storeFile file('../test.jks')//Signature file path
            storePassword "123456"
            keyAlias "test"
            keyPassword "123456"  //Signature password
            println("====== signingConfigs.debug ======")
        }
        release {
            storeFile file('../test.jks')//Signature file path
            storePassword "123456"
            keyAlias "test"
            keyPassword "123456"  //Signature password
            println("====== signingConfigs.release ======")
        }
    }
  •  

Let me explain that storeFile file corresponds to the path of the signature file key. Our signature is placed under the direct subpath of the project, while build.gradle is under test/app, so we need to find the root path of the project with... and then through / find the path of the corresponding signature file. Of course, you can also configure the address of the signature file, as long as you can find it.

At this point, we can see our packaged APK in app/build/outputs under the project path, and the name shows that the APK has been signed. That is to say, using code configuration can achieve the same effect as using graphical interfaces.

By the way, one thing to note here is that the signing Configs code block must be written in front of buildTypes, otherwise the following error will be reported: Can not find property'debug Config'on Signing Config Container.

So far, our buildTypes configuration can be as follows:

buildTypes {
        debug {
            println("====== buildTypes.debug ======")
            signingConfig signingConfigs.debug
        }
        release {
            //Is there any confusion?
            minifyEnabled false
            //Whether to remove useless resources
            zipAlignEnabled true
            println("====== buildTypes.release ======")
            signingConfig signingConfigs.release
            //Confused configuration files
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
  •  

You can now manipulate it arbitrarily from the command line, or pack it in multiple channels.  
However, the above configuration is simple, but there is insecurity. If your project is open source, you write the configuration password of the signature file and other information in clear text in build.gradle, is that not safe?

So we can do that. Create a new. properties file under the project path, or add relevant information directly under local.properties.

We can add directly under this document: (fill in the relevant information)

keystore.path=../test.jks              //Replace with your signature path
keystore.password=123456        
keystore.alias=test
keystore.alias_password=123456
  •  

So, under build.gradle, in order not to display in plaintext, we first need to get the key configuration, so we can add the code under app's build.gradle.

def keystoreFilepath = ''
def keystorePSW = ''
def keystoreAlias = ''
def keystoreAliasPSW = ''
// default keystore file, PLZ config file path in local.properties
def keyfile = file('s.keystore.temp')

Properties properties = new Properties()
// local.properties file in the root director
properties.load(project.rootProject.file('local.properties').newDataInputStream())
keystoreFilepath = properties.getProperty("keystore.path")

if (keystoreFilepath) {
    keystorePSW = properties.getProperty("keystore.password")
    keystoreAlias = properties.getProperty("keystore.alias")
    keystoreAliasPSW = properties.getProperty("keystore.alias_password")
    keyfile = file(keystoreFilepath)
}
  •  

First, we assign default values to keys, then we get the configuration information of signature files according to the configuration file of Properties, and then we get the configuration information of signature files according to our configuration parameter keystore.password under local.properties.

Here's a point to emphasize. Gitversion control In the project, we can see a. gitignore file under our project. The configuration is as follows.

We can see / local.properties, which means that local.properties are not added to version control by default, because local.properties store some information about our environment resources, such as the path of sdk. So we can configure signature information under local.properties without worrying about key leakage. It's very good for open source projects.

So, at this point in time, we can change signing Configs under app/build.gradle to:

signingConfigs {
        debug {
            storeFile keyfile
            storePassword keystorePSW
            keyAlias keystoreAlias
            keyPassword keystoreAliasPSW
            println("====== signingConfigs.debug ======")
        }
        myConfig {
            storeFile keyfile
            storePassword keystorePSW
            keyAlias keystoreAlias
            keyPassword keystoreAliasPSW
            println("====== signingConfigs.release ======")
        }
 }
  •  

Correspondingly, buildTypes can also be configured like this

buildTypes {
        debug {
            println("====== buildTypes.debug ======")
            signingConfig signingConfigs.debug
        }
        release {
            //Is there any confusion?
            minifyEnabled false
            //Whether to remove useless resources
            zipAlignEnabled true
            //Confusion Configuration
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            //If a signature file exists, it will sign
            if (keyfile.exists()) {
                println("WITH -> buildTypes -> release: using jks key")
                signingConfig signingConfigs.myConfig
            }else {
                println("WITH -> buildTypes -> release: using default key")
            }
            applicationVariants.all { variant ->
                variant.outputs.each { output ->
                    def outputFile = output.outputFile
                    if (outputFile != null && outputFile.name.endsWith('.apk')) {
                        // The output APK name is ruijie_v1.0_wandoujia.apk
                        def fileName = "ruijie_v${defaultConfig.versionName}_${variant.productFlavors[0].name}.apk"
                        output.outputFile = new File(outputFile.parent, fileName)
                    }
                }
            }
        }
  •  

In this way, when our project is open source, then we will not upload signature files. We use the code keyfile.exists() to determine whether there is a signature, then the APK packaged by others is unsigned. So it can guarantee the security of apk signature.

Add a note: build.gradle configuration:

Sometimes when we package, we display lint errors, so we can add

    lintOptions {
        abortOnError false
    }
  •  

dx tool (android converts jar package to dex format binary jar package tool)
This will apply all task s that use dex. Resolve configuration of 65535

dexOptions {
        incremental true
        javaMaxHeapSize "4g"
        //Turn off precompilation
        preDexLibraries = false
    }
  •  

Or specify a compiled version of JDK

compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
  •  

Packing ignores the same files as third-party jar s

 packagingOptions {
        exclude 'META-INF/DEPENDENCIES.txt'
        exclude 'META-INF/LICENSE.txt'
        exclude 'META-INF/NOTICE.txt'
        exclude 'META-INF/NOTICE'
        exclude 'META-INF/LICENSE'
        exclude 'META-INF/DEPENDENCIES'
        exclude 'META-INF/notice.txt'
        exclude 'META-INF/license.txt'
        exclude 'META-INF/dependencies.txt'
        exclude 'META-INF/LGPL2.1'
    }
  •  

Finally, attach the relevant code of the build.gradle configuration:

apply plugin: 'com.android.application'
apply plugin: 'me.tatarka.retrolambda'
apply plugin: 'android-apt'

def keystoreFilepath = ''
def keystorePSW = ''
def keystoreAlias = ''
def keystoreAliasPSW = ''
// default keystore file, PLZ config file path in local.properties
def keyfile = file('s.keystore.temp')

Properties properties = new Properties()
// local.properties file in the root director
properties.load(project.rootProject.file('local.properties').newDataInputStream())
keystoreFilepath = properties.getProperty("keystore.path")

if (keystoreFilepath) {
    keystorePSW = properties.getProperty("keystore.password")
    keystoreAlias = properties.getProperty("keystore.alias")
    keystoreAliasPSW = properties.getProperty("keystore.alias_password")
    keyfile = file(keystoreFilepath)
}

android {
    compileSdkVersion 24
    buildToolsVersion "24.0.2"
    defaultConfig {
        applicationId "com.example.vizax.with"
        minSdkVersion 15
        targetSdkVersion 24
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        multiDexEnabled true
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    // This is the code to resolve the lint error.
    lintOptions {
        abortOnError false
    }

    dexOptions {
        incremental true
        javaMaxHeapSize "4g"
        //Turn off precompilation
        preDexLibraries = false
    }
    /*android {
        productFlavors {
            kuan {
                manifestPlaceholders = [UMENG_CHANNEL_VALUE: "kuan"]
            }
            xiaomi {
                manifestPlaceholders = [UMENG_CHANNEL_VALUE: "xiaomi"]
            }
            qh360 {
                manifestPlaceholders = [UMENG_CHANNEL_VALUE: "qh360"]
            }
            baidu {
                manifestPlaceholders = [UMENG_CHANNEL_VALUE: "baidu"]
            }
            wandoujia {
                manifestPlaceholders = [UMENG_CHANNEL_VALUE: "wandoujia"]
            }
        }
    }*/
    android {
        productFlavors {
            kuan {}
            xiaomi {}
            qh360 {}
            baidu {}
            wandoujia {}
            yingyongbao {}
        }

        productFlavors.all {
            flavor -> flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name]
        }
    }

    signingConfigs {
        debug {
            storeFile keyfile
            storePassword keystorePSW
            keyAlias keystoreAlias
            keyPassword keystoreAliasPSW
            println("====== signingConfigs.debug ======")
        }
        myConfig {
            storeFile keyfile
            storePassword keystorePSW
            keyAlias keystoreAlias
            keyPassword keystoreAliasPSW
            println("====== signingConfigs.release ======")
        }
        /*release {
            storeFile file('../with.jks') //Signature file path
            storePassword "with123456"
            keyAlias "with"
            keyPassword "with123456"  //Signature password
        }*/
    }

    //Packing ignores the same files as third-party jar s
    packagingOptions {
        exclude 'META-INF/DEPENDENCIES.txt'
        exclude 'META-INF/LICENSE.txt'
        exclude 'META-INF/NOTICE.txt'
        exclude 'META-INF/NOTICE'
        exclude 'META-INF/LICENSE'
        exclude 'META-INF/DEPENDENCIES'
        exclude 'META-INF/notice.txt'
        exclude 'META-INF/license.txt'
        exclude 'META-INF/dependencies.txt'
        exclude 'META-INF/LGPL2.1'
    }

    /*signingConfigs The code block must be written in front of buildTypes, otherwise the following error will be reported:
    Could not find property 'debugConfig' on SigningConfig container.
    Signature passwords are not safe to write in gradle, so it's better to comment out the relevant code when it's packaged online.*/
    buildTypes {
        debug {
            println("====== buildTypes.debug ======")
            signingConfig signingConfigs.debug
        }
        release {
            //Is there any confusion?
            minifyEnabled false
            zipAlignEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            if (keyfile.exists()) {
                println("WITH -> buildTypes -> release: using jks key")
                signingConfig signingConfigs.myConfig
            }else {
                println("WITH -> buildTypes -> release: using default key")
            }
            applicationVariants.all { variant ->
                variant.outputs.each { output ->
                    def outputFile = output.outputFile
                    if (outputFile != null && outputFile.name.endsWith('.apk')) {
                        // The output APK name is ruijie_v1.0_wandoujia.apk
                        def fileName = "ruijie_v${defaultConfig.versionName}_${variant.productFlavors[0].name}.apk"
                        output.outputFile = new File(outputFile.parent, fileName)
                    }
                }
            }
        }
    }

    /*  Open Terminal in the lower left corner and enter the command line
        If we want to pack the release version of wandoujia channel, just execute the following command:
        gradlew assembleWandoujiaRelease
        If we want to pack the debug version of wandoujia channel, just execute the following command:
        gradlew assembleWandoujiaDebug
        If we only play the wandoujia channel version, then:
        gradlew assembleWandoujia
        This command generates Release and Debug versions of the wandoujia channel
        Similarly, I would like to call all Release versions:
        gradlew assembleRelease*/
}
  •  

As for confusing configuration, I'll explain it in detail in my next blog.  
If you have any questions, please leave a message. Thank you.

Topics: Gradle Android SDK JDK