apply plugin: 'com.android.application' //加载APP插件
//加载utils.gradle
apply from:rootProject.getRootDir().getAbsolutePath() + "/utils.gradle"
//buildscript设置android app插件的位置
buildscript {
repositories { jcenter() }
dependencies { classpath 'com.android.tools.build:gradle:1.2.3' }
}
//androidScriptBlock
android {
compileSdkVersion gradle.api
buildToolsVersion "22.0.1"
sourceSets{//源码设置SB
main{
manifest.srcFile 'AndroidManifest.xml'
jni.srcDirs = []
jniLibs.srcDir 'libs'
aidl.srcDirs=['src']
java.srcDirs=['src']
res.srcDirs=['res']
assets.srcDirs = ['assets'] //多了一个assets目录
}
}
signingConfigs {//签名设置
debug { //debug对应的SB。注意
if(project.gradle.debugKeystore != null){
storeFile file("file://${project.gradle.debugKeystore}")
storePassword "android"
keyAlias "androiddebugkey"
keyPassword "android"
}
}
}
/*
最关键的内容来了: buildTypesScriptBlock.
buildTypes和上面的signingConfigs,当我们在build.gradle中通过{}配置它的时候,
其背后的所代表的对象是NamedDomainObjectContainer<BuildType> 和
NamedDomainObjectContainer<SigningConfig>
注意,NamedDomainObjectContainer<BuildType/或者SigningConfig>是一种容器,
容器的元素是BuildType或者SigningConfig。我们在debug{}要填充BuildType或者
SigningConfig所包的元素,比如storePassword就是SigningConfig类的成员。而proguardFile等
是BuildType的成员。
那么,为什么要使用NamedDomainObjectContainer这种数据结构呢?因为往这种容器里
添加元素可以采用这样的方法: 比如signingConfig为例
signingConfig{//这是一个NamedDomainObjectContainer<SigningConfig>
test1{//新建一个名为test1的SigningConfig元素,然后添加到容器里
//在这个花括号中设置SigningConfig的成员变量的值
}
test2{//新建一个名为test2的SigningConfig元素,然后添加到容器里
//在这个花括号中设置SigningConfig的成员变量的值
}
}
在buildTypes中,Android默认为这几个NamedDomainObjectContainer添加了
debug和release对应的对象。如果我们再添加别的名字的东西,那么gradleassemble的时候
也会编译这个名字的apk出来。比如,我添加一个名为test的buildTypes,那么gradle assemble
就会编译一个xxx-test-yy.apk。在此,test就好像debug、release一样。
*/
buildTypes{
debug{ //修改debug的signingConfig为signingConfig.debug配置
signingConfig signingConfigs.debug
}
demo{ //demo版需要混淆
proguardFile 'proguard-project.txt'
signingConfig signingConfigs.debug
}
//release版没有设置,所以默认没有签名,没有混淆
}
......//其他和posdevice 类似的处理。来看如何动态生成runtime_config文件
def runtime_config_file = 'assets/runtime_config'
/*
我们在gradle解析完整个任务之后,找到对应的Task,然后在里边添加一个doFirst Action
这样能确保编译开始的时候,我们就把runtime_config文件准备好了。
注意,必须在afterEvaluate里边才能做,否则gradle没有建立完任务有向图,你是找不到
什么preDebugBuild之类的任务的
*/
project.afterEvaluate{
//找到preDebugBuild任务,然后添加一个Action
tasks.getByName("preDebugBuild"){
it.doFirst{
println "generate debug configuration for ${project.name}"
def configFile = new File(runtime_config_file)
configFile.withOutputStream{os->
os << I am Debug\n' //往配置文件里写 I am Debug
}
}
}
//找到preReleaseBuild任务
tasks.getByName("preReleaseBuild"){
it.doFirst{
println "generate release configuration for ${project.name}"
def configFile = new File(runtime_config_file)
configFile.withOutputStream{os->
os << I am release\n'
}
}
}
//找到preDemoBuild。这个任务明显是因为我们在buildType里添加了一个demo的元素
//所以Android APP插件自动为我们生成的
tasks.getByName("preDemoBuild"){
it.doFirst{
println "generate offlinedemo configuration for${project.name}"
def configFile = new File(runtime_config_file)
configFile.withOutputStream{os->
os << I am Demo\n'
}
}
}
}
}
.....//copyOutput
最终的结果如图39所示:
图39 实例2的结果 |
几个问题,为什么我知道有preXXXBuild这样的任务?
答案:gradle tasks --all查看所有任务。然后,多尝试几次,直到成功