Android studio之签名配置

在上一篇教程中,我讲解了Android studio多渠道打包的相关配置,在这一篇博客中,我们将继续讲解Android studio的签名配置。如果还没有看过上一篇的朋友,或者还不了解多渠道打包的,可以先看这一篇博客

http://blog.csdn.net/caben_/article/details/52682462

Let’s go,让我们开始新的教程。
我们可以新建一个项目,然后生成一个新的签名文件。
一般来说,经过这些操作之后,我们便可以通过点击左上角的Build->Generate Signed APK->Next,然后选择对应的Build Type进行打包。

那对一些人来说,这样也太麻烦了,每次都得输入相关信息,还得进行选择,这怎么能忍!
那么有更简单快捷的方法吗?答案是有的。

我们可以在项目的app目录下的build.gradle中进行签名的配置。
首先我们找到build.gradle下的android{},默认配置如下所示

这里写图片描述

接下来呢,我们可以把项目的预览模式调成Project,不调也行,只需把刚才生成的签名文件放至到对应的目录下即可。我的做法是直接放至到项目下,如图所示

这里写图片描述

然后,回到app下的build.gradle,在里面增加这段代码

signingConfigs {
        debug {
            storeFile file('../test.jks')//签名文件路径
            storePassword "123456"
            keyAlias "test"
            keyPassword "123456"  //签名密码
            println("====== signingConfigs.debug ======")
        }
        release {
            storeFile file('../test.jks')//签名文件路径
            storePassword "123456"
            keyAlias "test"
            keyPassword "123456"  //签名密码
            println("====== signingConfigs.release ======")
        }
    }

我来解释一下,storeFile file对应的就是签名文件key的路径,我们的签名放在项目的直接子路径下,而build.gradle在test/app下,所以我们要用 .. 找到项目的根路径,再通过 / 找到对应的签名文件所在路径。当然,你也可以自己配置签名文件的地址,只要能找到即可。

这里写图片描述

此时,我们在项目路径下的app/build/outputs可以看到我们打包的apk,从名字可以看出,该APK是已经签名的。那么就是说,用代码配置,可以达到和使用图形界面一样的效果。

对了,这里有一点需要注意,就是signingConfigs代码块一定要写在buildTypes前面,否则会报下面这种错: Could not find property ‘debugConfig’ on SigningConfig container.

至此,我们的buildTypes的配置可以这样:

buildTypes {
        debug {
            println("====== buildTypes.debug ======")
            signingConfig signingConfigs.debug
        }
        release {
            //是否混淆
            minifyEnabled false
            //是否移除无用资源
            zipAlignEnabled true
            println("====== buildTypes.release ======")
            signingConfig signingConfigs.release
            //混淆的配置文件
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

大家现在便可以通过命令行进行任意操纵,或者进行多渠道打包。
不过,上述的配置虽然配置简单,但是存在不安全性,假如你的项目是开源的,你把签名文件的配置密码之类的信息用明文写在build.gradle里面,那是不是很不安全呢?

所以,我们可以这么做。在项目路径下新建一个.properties的文件,或者直接local.properties下直接添加相关信息即可。

我们可以直接在该文件下添加:(填写相关信息)

keystore.path=../test.jks              //替换成自己的签名路径
keystore.password=123456        
keystore.alias=test
keystore.alias_password=123456

那么,在build.gradle下面,为了不用明文显示,我们首先要获得key的相关配置,所以我们可以在app的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)
}

首先,便是给key赋默认值,然后根据Properties的配置文件,然后根据我们在local.properties下的配置参数keystore.password等获取签名文件的配置信息。

这里有一点需要强调,在git版本控制的项目中,我们可以看到我们项目下有一个.gitignore的文件,里面的配置大概如下所示

这里写图片描述

我们可以看到/local.properties,意思就是说local.properties默认是不添加到版本控制里面的,因为local.properties存储的是我们环境资源的一些相关信息,如sdk的路径。故我们可以在local.properties下配置签名信息而不用担心密钥外泄。对于开源项目来说,是非常好的。

那么,此时此刻,我们app/build.gradle下的signingConfigs可以改为:

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 ======")
        }
 }

相应的,buildTypes也可以配置成这样

buildTypes {
        debug {
            println("====== buildTypes.debug ======")
            signingConfig signingConfigs.debug
        }
        release {
            //是否混淆
            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')) {
                        // 输出apk名称为ruijie_v1.0_wandoujia.apk
                        def fileName = "ruijie_v${defaultConfig.versionName}_${variant.productFlavors[0].name}.apk"
                        output.outputFile = new File(outputFile.parent, fileName)
                    }
                }
            }
        }

这样的话,当我们的项目是开源的,那么我们不会上传签名文件,我们通过上述代码keyfile.exists()进行判断是否有签名,那么其他人打包出来的apk是未签名的。所以能够保证apk签名的安全性。

附加一下:build.gradle的相关配置:

有时候我们打包会显示lint报错,那么我们可以添加

    lintOptions {
        abortOnError false
    }

dx工具(android将jar包转成dex格式二进制jar包工具)
这将应用所有使用dex的task。解决65535的配置

dexOptions {
        incremental true
        javaMaxHeapSize "4g"
        //关闭预编译
        preDexLibraries = false
    }

或者指定JDK的编译版本

compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

打包忽略掉第三方jar相同的文件

 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'
    }

最后,附上build.gradle部分配置的相关代码:

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
    }
    // 这个是解决lint报错的代码
    lintOptions {
        abortOnError false
    }

    dexOptions {
        incremental true
        javaMaxHeapSize "4g"
        //关闭预编译
        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') //签名文件路径
            storePassword "with123456"
            keyAlias "with"
            keyPassword "with123456"  //签名密码
        }*/
    }

    //打包忽略掉第三方jar相同的文件
    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代码块一定要写在buildTypes前面,否则会报下面这种错:
    Could not find property 'debugConfig' on SigningConfig container.
    签名密码写在gradle中不安全,故最好在打包上线的时候将相关代码注释掉。*/
    buildTypes {
        debug {
            println("====== buildTypes.debug ======")
            signingConfig signingConfigs.debug
        }
        release {
            //是否混淆
            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')) {
                        // 输出apk名称为ruijie_v1.0_wandoujia.apk
                        def fileName = "ruijie_v${defaultConfig.versionName}_${variant.productFlavors[0].name}.apk"
                        output.outputFile = new File(outputFile.parent, fileName)
                    }
                }
            }
        }
    }

    /*  左下角打开Terminal,输入命令行
        如果我们想打包wandoujia渠道的release版本,执行如下命令就好了:
        gradlew assembleWandoujiaRelease
        如果我们想打包wandoujia渠道的debug版本,执行如下命令就好了:
        gradlew assembleWandoujiaDebug
        如果我们只打wandoujia渠道版本,则:
        gradlew assembleWandoujia
        此命令会生成wandoujia渠道的Release和Debug版本
        同理我想打全部Release版本:
        gradlew assembleRelease*/
}

至于混淆的相关配置,稍后我在下一篇博客进行详细讲解。
如果有任何疑问,欢迎留言。谢谢。

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值