1 获取 Project
命令行操作:
./gradlew projects
#输出
Root project 'HelloAndroid'
+--- Project ':app'
\--- Project ':TestLib'
Project 对象提供的方法:
//getAllprojects返回所有的project,包括当前project,返回类型:Set集合。
def getProjects() {
println '-----------------'
println 'Root Project'
println '-----------------'
this.getAllprojects().eachWithIndex { Project project, int index
if(index == 0) {
println "Root project : ${project.name}"
} else {
println "+--- project : ${project.name}"
}
}
}
def getSubprojects() {
println "-------------------------------------"
println "Sub Project"
println "-------------------------------------"
// 获取所有子project
this.getSubprojects().eachWithIndex { Project project, int index ->
println "+---- Project: ${project.name}"
}
}
/**
* 获取父Project, 如果本身就是Root Project,返回null
*/
def getMyParentProject() {
// The parent project, or null if this is the root project.
if (this.getParent()) {
println "the parent project name is : ${this.getParent().name}"
} else {
println "the parent project is null"
}
}
/**
* 获取Root Project,如果本身就是Root Project,返回自己,不会返回null
*/
def getMyRootProject() {
// The root project. Never returns null.
def name = this.getRootProject().name
println "the root project name is: ${name}"
}
2 扩展属性
在 Gradle 对象中使用扩展属性
//settings.gradle 中添加
gradle.ext.testGradleExt=10
println gradle.testGradleExt
在 Project 对象中使用扩展属性
//在根 build.gradle 定义扩展属性
ext {
compileSdkVersion = 25
libAndroidDesign = 'com.android.support:design:25.0.0'
}
//在子 build.gradle 中访问扩展属性
println rootProject.ext.compileSkdVersion
//进一步简化
println rootProject.compileSkdVersion
//扩展属性会被子Project继承,子Project可直接访问
println this.compileSdkVersion
利用扩展属性解决 gradle 脚本中的魔数问题:
//根目录下创建 commmon.gradle 文件:
//用来存放应用中的所有配置变量,统一管理,而不再是每个moudle里都自己写一份,修改起来更加的方便
ext {
android = [compileSdkVersion : 25,
buildToolsVersion : '25.0.0',
applicationId : 'com.youdu',
minSdkVersion : 16,
targetSdkVersion : 23,
versionCode : 1,
versionName : '1.0.0',
multiDexEnabled : true,
manifestPlaceholders: [UMENG_CHANNEL_VALUE: 'imooc']]
signConfigs = ['storeFile' : 'youdo.jks',
'storePassword': 'rzq123456',
'keyAlias' : 'qndroid',
'keyPassword' : 'rzq123456']
java = ['javaVersion': JavaVersion.VERSION_1_7]
dependence = ['libSupportV7' : 'com.android.support:appcompat-v7:25.0.0',
'libSupportMultidex' : 'com.android.support:multidex:1.0.1',
'libCommonLibrary' : ':vuandroidadsdk',
'libPullAlive' : ':lib_pullalive',
'libCircleImageView' : 'de.hdodenhof:circleimageview:2.1.0',
'libSystembarTint' : 'com.readystatesoftware.systembartint:systembartint:1.0.3',
'libUmengAnalytics' : 'com.umeng.analytics:analytics:latest.integration',
'libUniversalImageLoader': 'com.nostra13.universalimageloader:universal-image-loader:1.9.5',
'libOkhttp' : 'com.squareup.okhttp3:okhttp:3.3.0',
'libAutoScrollViewPager' : 'cn.trinea.android.view.autoscrollviewpager:android-auto-scroll-view-pager:1.1.2',
'libSlidableActivity' : 'com.r0adkll:slidableactivity:2.0.5',
'libAndfix' : 'com.alipay.euler:andfix:0.5.0@aar',
'libLogger' : 'com.orhanobut:logger:+',
'libTinker' : "com.tencent.tinker:tinker-android-lib:1.7.7",
'libTinkerAndroid' : "com.tencent.tinker:tinker-android-anno:1.7.7"]
}
//在根 build.gradle 中
apply from: this.file('common.gradle')
//其他地方引用:
rootProject.ext.android.compileSdkVersion
3 properties
gradle.properties:
gradle.properties 中定义扩展属性,只能定义 Key-value 属性
isLoadTest=false
mCompileSdkVersion=25
gradle 脚本中使用:
if(hasProperty('isLoadTest') ? isLoadTest.toBoolean() : false) {
include ':Test'
}
android {
compileSdkVersion mCompileSdkVersion.toInteger()
}
其他 properties:
Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())
ext."signing.keyId" = properties.getProperty("signing.keyId")
ext."signing.password" = properties.getProperty("signing.password")
ext."signing.secretKeyRingFile" = properties.getProperty("signing.secretKeyRingFile")
4 文件相关 API
//获取路径
println getRoootDir().absolutePath
println getBuildDir().absolutePath
println getProjectDir().absolutePath
//获取文件内容
def getContent(String path) {
try {
def file = file(path) //相对于当前路径查找
return file.text
} catch(GradleException e) {
println 'file not found..'
}
return null
}
//文本拷贝
copy {
from file('youdo.jks')
into getRootProject().getBuildDir()
}
//拷贝 apk 文件夹
copy {
from file('build/outputs/apk/')
into getRootProject().getBuildDir().path + '/apk/'
}
//对文件树进行遍历
fileTree('build/outputs/apk') {
fileTree.visit { FileTreeElement element ->
println 'the file name is:' + element.file.name
copy {
from element
into getRootProject().getBuildDir().path + '/test/'
}
}
}
5 依赖相关 Api
settings.gradle 中
pluginManagement { PluginManagementSpec spec ->
//配置 gradle 插件的依赖仓库地址,即我们 apply 的 gradle 插件去哪里下载?
spec.repositories { RepositoryHandler handler ->
handler.gradlePluginPortal()
handler.google()
handler.mavenCentral()
handler.maven {
name 'personal'
url 'http://localhost:8081:/nexus/repositories/'
credentials {
username = 'admin'
password = 'admin123'
}
}
}
}
//根 build.gradle
plugins {
id 'com.android.application' version '7.1.2' apply false
id 'com.android.library' version '7.1.2' apply false
}
//配置工程的依赖仓库地址
dependencyResolutionManagement { DependencyResolutionManagement management ->
management.repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
management.repositories { RepositoryHandler handler ->
handler.google()
handler.mavenCentral()
}
}
// app 下的 build.gradle
dependencies {
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.5.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}
依赖方法及其区别
- implementation api:这种是我们最常用的方式,使用该方式依赖的库将会参与编译和打包。implementation 依赖方式所依赖的库不会传递。api 依赖方式会传递所依赖的库。
- compileOnly:只在编译时有效,不会参与打包
- runtimeOnly:只在生成apk的时候参与打包,编译时不会参与,很少用。
- testImplementation:只在单元测试代码的编译以及最终打包测试apk时有效。
- debugImplementation:debugCompile 只在debug模式的编译和最终的debug apk打包时有效
- releaseImplementation:Release compile 仅仅针对Release 模式的编译和最终的Release apk打包
6 执行外部命令
task(name: 'apkcopy') {
doLast {
def sourcePath = this.buildDir.path + '/outputs/apk'
def desationPath = '~/Downloads/'
def command = "mv -f ${sourcePath} ${desationPath}"
exec {
try {
executable 'bash'
args '-c' command
println 'the command is execute success.'
} catch(GradleException e) {
println 'the command is execute failed'
}
}
}
}
7 Task
A Task represents a single atomic piece of work for a build, such as compiling classes or generating javadoc.
定义Task
task helloTask {
println "i am helloTask" //配置阶段执行
}
//通过TaskContainer去创建Task
this.tasks.create(name:'helloTask2') {
println 'i am helloTask2'
}
//对 Task 进行基本配置
task helloTask(group: 'imooc', description:'task study'){
println 'i am helloTask '
}
task helloTask {
setGroup('imooc')
setDescription('task study')
println "i am helloTask"
}
//doFirst doLast
task helloTask {
println 'i am helloTask' //配置阶段执行
doFirst {
println 'i am helloTask doFirst' //执行阶段执行
}
doLast {
println 'i am helloTask doLast'
}
}
task.doFirst {
println 'i am helloTask doFirst'
}
执行顺序与依赖
task taskX {
doLast {
println 'taskX'
}
}
task taskY {
doLast {
println 'taskY'
}
}
task taskZ(dependsOn:[taskX, taskY]) {
dependOn this.tasks.findAll {
task -> return task.name.startsWith('lib')
}
doLast {
println 'taskZ'
}
}
task lib1 << {println 'lib1'}
task lib2 << {println 'lib2'}
task nolib << {println 'nolib'}
8 Extension
8.1 什么是 extension
//先定义一个普通的java类,包含2个属性
class Foo {
int age
String username
String toString() {
return "name = ${username}, age = ${age}"
}
}
//通过 Project 的 getExtensions 方法创建一个名为 foo 的Extension
Project.getExtensions().create("foo", Foo)
//脚本中配置Extension
foo {
age = 30
username = "hjy"
}
task testExt << {
//能直接通过 project 获取到自定义的 Extension
println project.foo
}
8.2嵌套的 Extension
class OuterExt {
String outerName
String msg
InnerExt innerExt = new InnerExt()
void outerName(String name) {
outerName = name
}
void msg(String msg) {
this.msg = msg
}
//创建内部Extension,名称为方法名 inner
void inner(Action<InnerExt> action) {
action.execute(innerExt)
}
String toString() {
return "OuterExt[ name = ${outerName}, msg = ${msg}] " + innerExt
}
}
class InnerExt {
String innerName
String msg
void innerName(String name) {
innerName = name
}
void msg(String msg) {
this.msg = msg
}
String toString() {
return "InnerExt[ name = ${innerName}, msg = ${msg}]"
}
}
def outExt = getExtensions().create("outer", OuterExt)
outer {
outerName "outer"
msg "this is a outer message."
inner {
innerName "inner"
msg "This is a inner message."
}
}
task testExt {
doLast {
println outExt
}
}