通上前两篇博文由浅入深的学习Gradle的基础和Gradle的Java插件相关知识后,现在终于到了高潮部分了,让我们来进一步正式学习Android Gradle插件。前面提到,Android Gradle插件是一个基于内置的Java插件来实现的第三方插件,它是由google的Android团队开发的。
分类
Android Gradle插件根据我们Android工程的属性分为三类:
插件名称 |
id |
描述 |
App |
com.android.application |
App应用工程,它可生成一个运行的apk应用 |
Library |
com.android.library |
Library库工程,它可生成AAR包 |
Test |
com.android.test |
Test测试工程,用于对App工程或者Library库工程进行单元测试 |
应该很好理解,像我们之前提到的工程中,有app和mylibrary两个子工程的情况下,除了Root Project的build.gradle外,其它两个Child Project的build.gradle的第一行便能看到应用android插件的代码:
\app\build.gradle
apply plugin: 'com.android.application'
mylibrary\build.gradle
apply plugin: 'com.android.library'
配置依赖
前面提到,要应用第三方插件前,必须先对其进行配置,因为Android Gradle插件是托管在jcenter库上,所以在Root Project的build.gradle里有这样的代码:
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
}
}
build.gradle的结构
经过前面的知识学习,现在我们应该可以很容易地看懂在Android Studio新建工程后的Root Project的build.gradle和Child Project的build.gradle的大概意思,我们先列出它们的大至结构:
Root Projec的build.gradle
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
说明:
- buildscript的配置就是上面所说的配置依赖关系
- allprojects的配置我们在《Gradle使用详解(二) 之 项目结构和初识Java Gradle插件》中有提过,一般地在Root Project的build.gradle中使用allprojects或subprojects是对Child Project进行统一的抽离公共配置,这样所有的Child Project的build.gradle就不用重复配置。这里是配置仓库。告诉Gradle是要去google库和jcenter库搜寻第三方库。
- task clean是Java插件内置的Task,同样也在《Gradle使用详解(二) 之 项目结构和初识Java Gradle插件》介绍过,它用于清理构建生成的目录文件。
App的build.gradle
apply plugin: 'com.android.application'
android {
compileSdkVersion 26
defaultConfig {
……
}
buildTypes {
……
}
}
dependencies {
……
}
说明:
- 第一行我们在上面介绍过了,apply plugine就是应用Android Gradle中的App类型插件
- android{}是Android Gradle工程唯一的一个入口,通过它可以进行自定配置工程参数,我们在下面再对其详细介绍
- dependencies就是配置依赖关系了,同样也在《Gradle使用详解(二) 之 项目结构和初识Java Gradle插件》介绍过,可以配置依赖第三方库或者依赖另一个Gradle项目(例如mylibrary)
mylibrary的build.gradle
apply plugin: 'com.android.library'
android {
……
}
dependencies {
……
}
说明:
总体上跟App的build.gradle文件大同小异,区别在于第一行中应用的是Android Gradle中的Library类型插件
android{}
Android Gradle工程的配置,都是在android{}中,这是唯一的一个入口。通过它可以对Android Gradle工程进行自定义的配置。示例如下:
android {
compileSdkVersion 26
buildToolVersion "26.0.1"
defaultConfig {
applicationId "com.zyx.myapplication"
minSdkVersion 19
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
compileSdkVersion
compileSdkVersio是配置Android工程的SDK,或者说是告诉 Gradle 用哪个 Android SDK 版本编译你的应用。还可以这样写成:
android {
compileSdkVersion "android-26"
}
或者
android. compileSdkVersion "android-26"
buildToolVersion
buildToolsVerion表示使用的Android构建工具的版本
defaultConfig{}
defaultConfig是Android对象中的一个配置块,负责定义所有的默认配置。其里面可以配置很多字段,一般基本的defaultConfig配置字段有:
applicationId
用于指写生成的APP的包名,默认情况下是null,若为null,则会在构建的时候从AndroidManifest.xml文件中配置的manifest标签的package属性读取。
minSdkVerion
用于指写APP最低支持的Android 系统版本,其对应的值是Android SKD 的API Level。
targetSdkVersion
是 Android 提供向前兼容的主要依据,表明是基于哪个Android 版本开发的。也就是说,只要targetSdkVersion 不变,即使APK 安装在新 Android 系统上,其行为还是保持老的系统上的行为,这样就保证了系统对老应用的前向兼容性。
versionCode
表明APP应用内部版本号,它是一个整数,一般用于APP升级。
verionName
表明APP应用内部版本名称。
testInstrumentationRunner
用于配置单元测试时使用的Runner,一般情况下使用默认的是android.test.InstrumentationTestRunner即可。
testApplicationId
用于配置测试APP的包名,默认情况下是applicationId + “.test”。一般情况下默认即可。
等
buildTypes{}
buildTypes是一个域对象。它是对构建类型:release、debug等的配置。还可以在buildTypes{}里新增任意多个需要构建的类型。每一个BuildType还会生成一个SourceSet。上面示例中,release就是一个BuildType。一般地像defaultConfig{}中的配置如果需要区分不同的构建版本配置不同的参数的话,就得在这里进行配置。常用的配置字段有:
minifyEnabled(混淆)
用于配置是否启用Proguard混淆,接爱一个boolean类型的值。代码混淆是一个非常有用的功能,它不仅能使APK包size变小,还可以让反编译的人不容易看明白我们的源代码逻辑从而增加分析难度。一般情况下,release模式编译的版本会启动混淆功能。因为混淆后无法断点调试,所以debug模式下一般是不启动的。
proguardFiles/ proguardFile
proguardFiles是当我们启用混淆时,ProGuard的配置文件,它可以同时接受多个配置文件,因为它的参数是一个可变类型的参数。
proguardFile也是用于配置App proGuard混淆所使用的ProGuard配置文件,它接收一个文件作为参数。
当我们将minifyEnabled设为true,启动混淆后,还要通过proguardFiles或proguardFile指写混淆的配置表即可,如上面示例中代码:
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
说明:
- getDefaultProguardFile用于指定使用的混淆配置文件,该文件路径于Android SDK安装目录下的tools/proguard文件夹下。在该目录下有两个Android的Proguard配置文件:proguard-android.txt和proguard-android-optimize.txt,从名字可以看出,它们一个是无优化,另一个是有做优化的。
- 配置代码中,在逗号后是一个文件,一般地,该文件位于build.gradle同级目录中。它就是我们进行不混淆哪些类的配置文件,注意这里头配置的是不混淆白名单,当minifyEnabled设为true后默认是全部混淆的。一般情况下,如果你的代码使用到反射的话,都不能进行混淆,就要在此文件中配置你的不混淆的相关代码。一般规则用连起来单词表示,主要有:
keep 保留,例如keepattributes:表示保留属性
dont 不要,例如dontwarn:表示不要提示警告
ignore 忽略,例如ignorewarning:表示忽略警告
更多详细的规则大家可自行上网查找相关资料,这里不就作详情列举了。
applicationldSuffix
用于配置基于默认applicationId的后缀,比如默认defaultConfig中配置的applicationId为com.zyx.myapplication,若在debug的BuildType中指写applicationIdSuffix为.debug,那么构建生成的debug.apk的包名就是com.zyx.myapplication.debug。
debuggable
用于配置是否生成一个可供调试的apk。一般release中都是为false,而debug中都是为true。
jinDebuggable
跟debuggable类似,用于配置是否生成一个可供调试Jni(C/C++)代码的apk。
multiDexEnabled
用于配置是否启用自动拆分多个Dex的功能。一般用程序中代码太多,超过了65535个方法的时候,拆分多个Dex,接爱一个boolean类型的值。关于突破65535方法限制,我们后面再介绍
zipAlignEnabled
用于配置是否启用Android 的 zipalign整理优化APK文件的工具。zipalign能提高系统和应用运行效率,更快地读写APK中的资源,降低内存的使用。一般情况下,release模式编译的版本下都会启动此优化。
shrinkResources
用于配置是否自动清理未使用的资源,默认为false
signingConfig
用于配置APK包的签名信息。具体使用可见signingConfigs{}中介绍。
signingConfigs{}(APK签名)
一个APP只有在签名这后才能被发布、安装和使用,签名是保护APP的方式,它能标记APP的唯一性,防止恶意篡改。一般地我们在开发过程中使用的debug编译模式时,Android SDK已帮我们打上了一个默认的debug签名证书(该签名证书位于$HOME/.android/debug.keystore目录中),所以我们可以直接调试安装在手机上。但是在正式发布时构建的release模式版本时,我们就要对其进行配置签名证书了。
配置签名
关于配置签名可以在signingConfigs{}中进行,示例如:
android {
……
defaultConfig {
……
}
signingConfigs {
releaseConfig {
storeFile rootProject.file("buildkey/mykey.keystore")
storePassword "password"
keyAlias "MyKey"
keyPassword "password"
}
debugConfig { // debug可不配置
storeFile rootProject.file("buildkey/debug.keystore")
storePassword "android"
keyAlias "androiddebugkey"
keyPassword "android"
}
}
buildTypes {
……
}
}
storeFile
指定签名证书文件,接收一个文件类型
storePassword
配置签名证书文件的密码
keyAlias
配置签名证书中密钥别名
keyPassword
配置签名证书中该密钥的密码
应用签名
上述操作只是配置了签名证书,要使用它还需要在defaultConfig{}或buildTypes{}中进行signingConfig字段的指定,正如上面介绍defaultConfig{}或buildTypes{}中所提到的。示例:
android {
……
defaultConfig {
……
signingConfig signingConfigs.releaseConfig
}
signingConfigs {
……
}
buildTypes {
……
}
}
或者针对构建类型分别配置,比如release和debug区分配置:
android {
……
defaultConfig {
……
}
signingConfigs {
……
}
buildTypes {
release {
……
signingConfig signingConfigs.releaseConfig
}
}
}
隐藏签名文件
上面示例中展示了签名证书的配置和使用,但是忽略了一个安全性问题。签名信息是我们应用非常重要的信息,是公司重要的资源,如果我们项目中都把APP的签名证书文件和相关密钥放在项目中托管在git上的话,那岂不是所有的开发者都能获得到签名证书文件和密钥,这种方式出于安全考虑确实有所欠佳。所以要解决这类问题,最好的办法是将证书文件和相关密钥放在服务器编译机上,然后配置相应的环境变量。如若各位开发者本地不存在环境变量就使用默认的debug签名证书,这样的话又虽能解决编译的问题又可提高安全性了。使用示例如:
android {
……
defaultConfig {
……
}
signingConfigs {
def appStoreFile = System.getenv("STORE_FILE");
def appStorePassword = System.getenv("STORE_PASSWORD");
def appKeyAlias = System.getenv("KEY_ALIAS");
def appKeyPassword = System.getenv("KEY_PASSWORD");
if (!appStoreFile || !appStorePassword || !appKeyAlias || !appKeyPassword) {
appStoreFile = "buildkey/debug.keystore" // 将$HOME/.android/debug.keystore的debug证书文件拷贝到工程目录中
appStorePassword "android"
appKeyAlias "androiddebugkey"
appKeyPassword "android"
}
releaseConfig {
storeFile rootProject.file(appStoreFile)
storePassword appStorePassword
keyAlias appKeyAlias
keyPassword appKeyPassword
}
}
buildTypes {
release {
……
signingConfig signingConfigs.releaseConfig
}
}
}