Android插件
前面我们说到Gradle插件其实并没有提供真正的构建功能, 我们编译构建的Task很多都是由插件来提供的,如果对这点还不是很了解可以先看下Gradle脚本学习
Java插件
在某种意义上,android插件算是在java插件的基础上扩展而来的,而java插件也是Gradle官方支持的插件之一,为了让大家能够更好的理解Android插件中各个Task的执行和依赖关系,我们现对Java插件做一个介绍,英语好的同学可以直接去阅读Gradle官方The Java Plugin
Java插件的使用很简单,毕竟是官方支持的
apply plugin: 'java'
这样就可以了,对于java插件我们主要理解一张Tasks图表
这里包含了java插件中的绝大部分Tasks,图标中的Task描述如下
名称 | 依赖 | TaskType | 描述 |
---|---|---|---|
compileJava | 所有处理编译过程的任务 | JavaCompile | 使用javac编译java源码 |
processResources | - | Copy | 把资源文件复制到相应目录 |
classes | complileJava和processResources | Task | 生成.class文件和资源文件目录 |
compileTestJava | compile,加上编译测试文件的所有Task | JavaCompile | 使用javac编译java测试代码 |
processTestResources | - | Copy | 把测试资源文件复制到相应目录 |
testClasses | compileTestJava和processTestResources | Task | 申城测试的.class文件和资源文件目录 |
jar | compile | Jar | 生产jar文件 |
javadoc | compile | Javadoc | 使用javadoc生产Api文档 |
test | compile | Test | 使用JUnit或TestNG运行单元测试 |
uploadArchives | 生成所有archives需要的artifacts文件的Task,包括jar | Upload | 使用archives配置上传artifacts包括jar文件 |
assemble | 项目中的所有archive任务,包括jar | Task | 生成项目所有的archive文件 |
check | 项目中的所有验证任务,包括test | Task | 执行所有项目中的验证任务 |
build | assemble和check | Task | 执行完整的项目构建 |
clean | - | Delete | 删除项目构建过程生成的文件目录 |
clean TaskName | - | Delete | 删除指定任务创建的文件。 cleanJar将删除由jar任务创建的JAR文件,cleanTest将删除测试任务创建的文件 |
我们平时使用当然不可能一步步去编译,往往只会使用几个相对简单的命令,比如check、assemable之类的,但是如果我们对整个build的流程不了解,我们就很难在构建过程中对某一个具体的行为进行优化,这里先讲解java插件,是因为java的构建过程相对简明,Android工程的构建过程就相对复杂很多,但是本质上都差不多,建议大家还是可以先学习下
Android插件
Android插件是由google提供,用于配置、编译、打包android工程,它提供了一些新的DSL和task供我们配置,执行android工程的编译打包过程,关于android插件的使用个人建议可以看下Google提供的GradlePluginUserGuide和AndroidPluginDSL,这里我就算是抛砖引玉了
基本配置
android下最基本的配置很简单,完成最基本的配置之后Gradle就能够对我们的project进行构建,同时还有一些的零碎的配置,我也一并并在这里进行说明最最简单的,我们只需要配置compileSdkVersion和buildtoolsVersion
apply plugin: 'com.android.application'
android {
compileSdkVersion 25
buildToolsVersion "25.0.0"
}
这样就可以完成构建,当然我们还需要配置一些Apk的基本信息,这些信息主要通过defaultConfig{}来进行配置,主要的信息如下
minSdkVersion
targetSdkVersion
versionCode
versionName
applicationId
-
testApplicationId
(used by the test APK) testInstrumentationRunner
前四条都是一些基本的版本配置信息其中值得一提的是applicationId
这条属性,形式上和packageName是一致的,当我们使用AndroidStudio创建工程是,applicationId默认是和packageName一样,但是这两者是有本质区别的,packageName是可以改变的,但是applicationId一旦应用发布就不能修改了,applicationId是APK的标识,同时不同渠道版本的applicationId最好也进行不同的配置,这个稍后进行详细说明
关于test的配置信息,也会在后面的章节详细说明
sourceSets
资源目录Android插件的默认资源目录如下
src/
├──main/
│ ├── java/
│ ├── resources/
│ ├── res/
│ ├── assets/
│ ├── aidl/
│ ├── rs/
│ ├── jni/
│ ├── jniLibs/
│ └── AndroidManifest.xml
├── test/
└── androidTest/
如果需要更改目录需要手动修改,例如对于一般的eclipse工程我们可以使用下面的配置
android {
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['src']
resources.srcDirs = ['src']
aidl.srcDirs = ['src']
renderscript.srcDirs = ['src']
res.srcDirs = ['res']
assets.srcDirs = ['assets']
}
androidTest.setRoot('tests')
}
}
这样就无需手动更改文件目录,也可以直接编译
Dependencies Configration
前面我们说到dependencies本质上就是一个配置信息,Android插件提供的dependencies主要有:
- compile: main application
- androidTestCompile: test application
- debugCompile: debug Build Type
- releaseCompile: release Build Type
- testComplie:上面四种是google官方文档上写的,事实上testComplie这种纯java的test配置也是支持的
根据版本变种,android插件也会生成不同的dependencies,就像android自带的两种buildtype就生成了上面两种dependencies
Android Tasks
前面在gradle我们说到,在gradle中实际的执行是通过Task来进行的,Android插件能够对我们的Project进行构建,必然也提供了相应的Task才能完成构建,我们主要要用到的主要有下面几个
- assemble生成输出,会执行构建过程
- check运行所有检查任务
- connectedCheck运行检查连接的设备或模拟器,所有连接的设备将并行运行。
- deviceCheck使用API运行检查以连接到远程设备,这在CI服务器上使用。
- build这个任务会运行assemble和check。
- clean此任务清除项目的输出。
感觉和java插件大体相似,只是多了两个类似设备检查之类的task,但是事实上,android工程的构建过程还是比较复杂的,所以android插件并没有给出构建过程中具体的tasks,以及task间的依赖关系,更没有java插件中提供的task依赖表。
那么我们要怎么才能弄清android构建的具体过程呢,这里我为大家介绍一个插件Inspector,具体使用方法参考GitHub:https://github.com/jakeouellette/inspector,我就不多做介绍,这个插件可以生成我们所运行的task的依赖关系图,方便大家理解学习。
注意:Inspector不支持windows!不支持windows!不支持windows!
版本变种的配置
BuildType配置
版本变种中有两个内容,BuildType和ProductFlavor,首先是关于BuildType,Android插件默认提供debug和release两种BuildType,当然我们也可以自己添加新的BuildType,Android下对于每一种BuildType都可以有各自的配置信息,同时可以根据配置信息生成独特apk,首先对于不同的BuildType,我们会有不同的dependencies配置compile类型,就像上面 dubugCompile一样,类似下面的代码
android {
buildTypes {
jnidebug {
}
}
}
就会生成一个jnidebugCompile,前面我们说过aseemble这个task可以生产所有的输出,这里我们有三个BuildType,即assemble会生成3个不同Apk,如果我们只需要生成debug的Apk,这里和compile一样,Android插件也会生成一个assembleDubug的task,运行assembleDubug则不会生成其他版本的Apk
BuildType的配置就在buildTypes{}的闭包中
android {
buildTypes {
debug {
applicationIdSuffix ".debug"
}
jnidebug {
initWith(buildTypes.debug)
applicationIdSuffix ".jnidebug"
jniDebuggable true
}
}
}
其实我觉得这些东西反而没有什么好讲的,配置基本上就是一个表,列出所有可配置的东西,这里我姑且还是把一些我感觉可用的配置和方法都列出来,大家也可以参考官方文档
名称|类型|说明
---|--|--|--
applicationIdSuffix|String|为 applicationId添加后缀,applicationId是app唯一标识,每次调用都是在最开始的applicationId上添加
debuggable|Boolean|调试开关
consumerProguardFiles|List<File>|生成的aar文件中的混淆规则,只针对Library工程
jniDebuggable|Boolean|jniDebug开关
minifyEnabled|Boolean|混淆开关
signingConfig|SigningConfig|签名配置
proguardFiles|List<File>|生成apk时使用的混淆配置文件
shrinkResources|Boolean|移除没有用到的资源文件,默认为false
embedMicroApp|Boolean|Android Wear app是否需要嵌入此build type
manifestPlaceholders|Map<String, Object>|配置manifest属性,合并时使用这里的属性
multiDexEnabled|Boolean|Multi-Dex开关
multiDexKeepFile|File|main dex的配置文件,text文件,每行指定一个class文件,格式为com/example/MyClass.class
multiDexKeepProguard|File|main dex的混淆规则,会和构建系统的混淆规则合并
zipAlignEnabled|Boolean|压缩对齐开关
[buildConfigField](http://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.dsl.BuildType.html#com.android.build.gradle.internal.dsl.BuildType:buildConfigField(java.lang.String, java.lang.String, java.lang.String))(String, String, String)|Method|为生成的BuildConfig添加键值对
initWith(BuildType)|Method|复制所有属性
SigningConfig
Android 要求所有 APK 必须先使用证书进行数字签署,然后才能安装。Android插件已经帮我们配置了两种BuildType:debug和release,其中debug默认使用Android自动生成的dubug Signing,而release默认是没有配置Signing的,我们可以直接在代码中进行Signing的配置
android {
signingConfigs {
release{
storeFile file("other.keystore")
storePassword "android"
keyAlias "androiddebugkey"
keyPassword "android"
}
}
buildTypes {
release{
signingConfig signingConfigs.release
}
}
}
这里我们我们通过signingConfigs{}配置了一个release的signing,然后在配置buildTypes 的时候把它配置到,release的配置闭包中, 这里可以简单的把signingConfigs理解为一个配置文件,在上面我们直接keystore的pwd写在了代码中, 一般是不建议这么,我们通常使用一个专门的配置文件来存储signingConfigs,需要的时候从文件中读取,或者从控制台输入。
BuildConfig
在编译时期,Android插件会生成一个BuildConfig的类,包含部分Gralde配置中的常量默认BuildConfig有下列信息:
- boolean DEBUG 是否可以dubug
- int VERSION_CODE
- String VERSION_NAME
- String APPLICATION_ID
- String BUILD_TYPE – name of the build type, e.g. "release"
- String FLAVOR – name of the flavor, e.g. "paidapp"
同时我们也可以通过buildConfigField(String, String, String)把我们需要的配置信息加入到BuildConfig中
ProductFlavor配置
ProductFlavor的配置和BuildType基本类似,同时也会生成相应的Task和Compile,主要区别就是BuildType的分类是针对开发者的,如debug、release,而ProductFlavor的分类是针对用户的,如free、pay,所以可配置的内容是不同的,ProductFlavor的配置信息主要如下:
名称|类型|说明
---|--|--|--
applicationId|String|-
applicationIdSuffix|String|为 applicationId添加后缀,applicationId是app唯一标识,每次调用都是在最开始的applicationId上添加
consumerProguardFiles|List<File>|生成的aar文件中的混淆规则,只针对Library工程
dimension|String|此flavor的dimensioin类型
externalNativeBuild|ExternalNativeBuildOptions|封装了native相关构建的信息
jackOptions|JackOptions|jack配置
signingConfig|SigningConfig|签名配置
proguardFiles|List<File>|生成apk时使用的混淆配置文件
manifestPlaceholders|Map<String, Object>|配置manifest属性,合并时使用这里的属性
multiDexEnabled|Boolean|Multi-Dex开关
multiDexKeepFile|File|main dex的配置文件,text文件,每行指定一个class文件,格式为com/example/MyClass.class
multiDexKeepProguard|File|main dex的混淆规则,会和构建系统的混淆规则合并
[buildConfigField](http://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.dsl.BuildType.html#com.android.build.gradle.internal.dsl.BuildType:buildConfigField(java.lang.String, java.lang.String, java.lang.String))(String, String, String)|Method|为生成的BuildConfig添加键值对
maxSdkVersion(int or String)|Method|设置flavor最高sdk版本
minSdkVersion(int or String)|Method|设置flavor最低sdk版本
Build Variant
我们知道一种BuildType会生产一种Apk,ProductFlavor也是一样的,那个一个工程可以产出的不同种类的apk将是这两者的合并,比如一个有两个Flavor的工程,加上默认的BuildType,则会生成下面几个版本:
- Flavor1 - debug
- Flavor1 - release
- Flavor2 - debug
- Flavor2 - release
Build Type + Product Flavor = Build Variant
Sourcesets and Dependencies
不同的BuildVariant可以有不同的资源和依赖,他们同时共享主目录下的资源,举个例子flavor1Debug这样一个Variant,它的资源可能来自如下目录
-
android.sourceSets.main
位于 src/main/ -
android.sourceSets.flavor1
位于 src/flavor1/ -
android.sourceSets.debug
位于 src/debug/ -
android.sourceSets.flavor1Debug
位于 src/flavor1Debug/
如果出现同名的文件那么他们的优先级顺序是flavor1Debug>debug>flavor1>main,一层会覆盖一层。对于Dependencies,这个规则也是一样的。
小结
Android插件的内容并不算多,但是想要用好Gradle,我们除了要了解这些东西之外,还需要了解Gradle和Groovy提供的API以及一些其他的插件才能更好的使用它。