Gradle是一个基于JVM的构建工具,其 build 脚本使用 groovy dsl 编写。
Gradle 的核心在于基于 Groovy的丰富而可扩展的域描述语言(DSL)。 Groovy 通过声明性的语言元素将基于声明的构建推向下层,你可以按你想要的方式进行组合。
projects 和 tasks是 Gradle 中最重要的两个概念。
任何一个 Gradle 构建都是由一个或多个 projects 组成。每个 project 包括许多可构建组成部分。 每个 project 都由多个 tasks 组成。每个 task 都代表了构建执行过程中的一个原子性操作。如编译,打包,生成 javadoc,发布到某个仓库等操作。
| 名称 | 类型 | 默认值 |
project | Project | Project实例 |
name | String | 项目目录的名称。 |
path | String | 项目的绝对路径。 |
description | String | 项目的描述。 |
projectDir | File | 包含生成脚本的目录。 |
buildDir | File | |
group | Object | 通常是application的label |
version | Object | 未指定 |
ant | AntBuilder | AntBuilder实例 |
一个简单task,可点击左边的开始按钮
执行;
- task hello {
- return 'Hello world!'
- }
也可以指明task依赖关系:
- task dep(dependsOn: hello) {
- println "I'm Gradle"
- }
执行结果如下

循环执行任务
- task count {
- doFirst {//doFirst,doLast是内置函数
- 4.times { print "$it " }
- }
- }
创建动态任务
- 4.times { counter ->
- task "task$counter" {
- doFirst{
- println "I'm task number $counter"
- }
- }
- }
- task tout(dependsOn: task2){//打印出I'm task number 2
- print "finish"
- }
增加依赖:为已存在的任务增加行为
- 4.times { counter ->
- task "task$counter" {
- doFirst{
- println "I'm task number $counter"
- }
- }
- }
- task2.dependsOn task1, task3
- task tout(dependsOn: task2){//依次打印出I'm task number 1,3,2
- print "finish"
- }
以属性的方式访问任务,对于插件提供的内置任务。这尤其方便(例如:complie)
- task hello{
- println("helloKitty")
- }
- hello.doFirst{
- println "task name is $hello.name"
- }
为任务增加自定义属性
- task myTask {
- ext.myProperty = "myValue"
- }
- task hello{
- print myTask.myProperty //打印出myValue
- }
Gradle 允许在脚本中定义多个默认任务。在多项目构建中,每个子项目都可以指定单独的默认任务。如果子项目未进行指定将会调用父项目指定的的默认任务。
- defaultTasks 'cleanD', 'runD'
- task cleanD {
- println 'Default Cleaning!'
- }
- task runD {
- println 'Default Running!'
- }
- task other {//运行会先执行前两个任务
- println "I'm not a default task!"
- }
配置阶段后,Gradle 会了解所有要执行的任务 Gradle 提供了一个钩子来捕获这些信息。例如可以检查已经执行的任务中有没有被释放。借由此,你可以为一些变量赋予不同的值。
在下面的例子中,为 distribution 和 release 任务赋予了不同的 version 值。
- gradle.taskGraph.whenReady {taskGraph ->
- if (taskGraph.hasTask(releaseTask)) {
- version = '1.0'
- } else {
- version = '1.0-SNAPSHOT'
- }
- }
android中的bulid.gradle有两种,一种是整个项目的,另一个是每个module中的。
下面先看整个项目的gradle:分为两个部分,buildscript{}中是编译过程中的配置;allprojects{}是整个项目需要依赖的仓库
- buildscript {//编译过程配置
- ext {//自定义属性,可通过rootProject.ext.x来引用
- kotlin_version = '1.3.72'
- }
- repositories {//代码托管仓库
- maven { url 'https://maven.aliyun.com/nexus/content/repositories/google' }
- maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
- maven { url 'http://maven.aliyun.com/nexus/content/repositories/jcenter' }
- google()
- jcenter()
- }
- dependencies {
- classpath 'com.android.tools.build:gradle:4.2.2'
- classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.61"
- classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5'
- // NOTE: Do not place your application dependencies here; they belong
- // in the individual module build.gradle files
- }
-
- }
-
- allprojects {
- //配置整个项目依赖的仓库
- repositories {
- maven { url 'https://maven.aliyun.com/nexus/content/repositories/google' }
- maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
- maven { url 'http://maven.aliyun.com/nexus/content/repositories/jcenter' }
- google()
- mavenCentral()
- maven { url 'https://www.jitpack.io' }
- }
- }
ext{}中是自定义的属性;
也可以在gradle.propertities中定义属性,如下代码定义了android编译版本,用于统一不同module的android版本
- VERSION_TARGET_SDK=30
- VERSION_COMPILE=30
- VERSION_BUILD_TOOL=30.0.3
- #图标
- PROD_APP_ICON=@mipmap/ic_launcher
可通过如下方式引用
compileSdkVersion VERSION_COMPILE.toInteger() buildToolsVersion VERSION_BUILD_TOOL
然后看每个module中的bulid.gradle:
首先是插件的声明,根据plugin可以判断这个module是可运行的app或者是library
- apply plugin: 'com.android.application'//通常在最顶部写
-
- plugins {//应用插件的另一种写法
- id 'com.android.library'
- }
Android常见五种插件id:
| plugin id | 描述 |
| com.android.application | 应用程序插件,生成apk |
| com.android.library | 库插件,生成aar,可供其它项目使用 |
| com.android.test | 测试插件 |
| com.android.feature | 创建Android Instant App时需要用到的插件 |
| com.android.instantapp | Android Instant App的入口 |
依赖的添加:分为依赖本地SDK、依赖本地module、依赖远程库
- implementation fileTree(dir: 'libs', include: ['*.aar', '*.jar'], exclude: [])//依赖libs目录下的所有相关类型文件
- implementation project(path: ':ZXingForAndroid')//依赖本地文件
- implementation files('libs/Msc.jar')//依赖本地库
- //远程依赖库
- implementation('com.alibaba:QLExpress:3.2.0'){exclude group: 'com.android.support', module:'design' }// 加载时排除框架中的design包
compile/implementation/api:编译范围依赖在所有的 classpath 中可用,同时它们也会被打包,其中compile与implementation相同,已废弃使用;api是可以在其它module中使用,例如module A、B都依赖C,A依赖B,则可以在B中使用api添加C的依赖,A中不必添加C的依赖。 implementation:依赖在运行和测试系统的时候需要,但在编译的时候不需要。比如,你可能在编译的时候只需要 JDBC API JAR,而只有在运行的时候才需要 JDBC 驱动实现。 compileOnly:只参与编译,不打包,常用于添加系统的库文件以通过编译。 testXXX:只用于测试。
用于默认配置,常用属性包括
- minSdkVersion 21
- targetSdkVersion 30
- versionCode 2
- versionName "1.0.1"
- testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
- ndk.abiFilters 'arm64-v8a'//支持的ndk链接库类型
- multiDexEnabled true //是否支持多dex
- externalNativeBuild {}//ndk编译设置
用于构建不同的apk
- buildTypes {
- release {
- minifyEnabled true //开启混淆
- shrinkResources true //移除未使用资源
- proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
- signingConfig signingConfigs.release //设置使用的签名
- }
- debug {
- debuggable true
- }
- custom {
- minifyEnabled false
- }
- }
如上代码,可生成app-release,app-debug,app-custom三种apk。常用的属性如下
| 属性 | 描述 |
|---|---|
| applicationIdSuffix | 配置applicationId的后缀 |
| debuggable | 是否支持断点调试 |
| jniDebuggable | 是否可以调试NDK代码 |
| buildConfigField | 配置不同的开发环境,比如测试环境和正式环境 |
| shrinkResources | 编译时是否移除未使用的资源,默认false |
| zipAlignEnabled | 是否开启开启zipalign优化,提高apk运行效率 |
| proguardFile | ProGuard混淆所使用的ProGuard配置文件 |
| proguardFiles | 同时配置多个ProGuard配置文件 |
| signingConfig | 配置签名信息 |
| multiDexEnabled | 是否自动拆分多个Dex |
- signingConfigs {
- debug {//可以在bulidTypes下的signingConfig中引用
- storeFile file('release.keystore')//签名文件路径
- storePassword 'xxxxxx'
- keyAlias 'androidreleasekey'
- keyPassword '123456'
- }
- release {
- storeFile file('release.keystore')
- storePassword 'xxxxxx'
- keyAlias 'androidreleasekey'
- keyPassword '123456'
- }
- }
- flavorDimensions 'default' // 定义产品维度,所有渠道都要指定维度
- productFlavors {
- dev {// 每个环境包名不同
- applicationId DEVELOP_PACKAGE_NAME as String
- dimension "default"
- // 自定义buildConfig.java中的变量供代码中使用
- buildConfigField "String", "MODE", '"develop"'
- }
- prod {
- applicationId PROD_PACKAGE_NAME as String
- dimension "default"
- buildConfigField "String", "MODE", '"production"'
- }
-
-
- productFlavors.all { flavor ->
- flavor.manifestPlaceholders += [CHANNEL_VALUE: name]
- if (name.equals('dev')) { //开发环境
- flavor.manifestPlaceholders += [APP_NAME: DEV_APP_NAME as String]
- flavor.manifestPlaceholders += [APP_ICON: DEV_APP_ICON as String]
- flavor.manifestPlaceholders += ["apk.applicationId" : DEV_PACKAGE_NAME as String]
- } else if (name.equals('prod')) { //生产环境
- flavor.manifestPlaceholders += [APP_NAME: PROD_APP_NAME as String]
- flavor.manifestPlaceholders += [APP_ICON: PROD_APP_ICON as String]
- flavor.manifestPlaceholders += ["apk.applicationId" : PROD_PACKAGE_NAME as String]
- }
-
- //打包配置
- applicationVariants.all { variant ->
- def name = variant.flavorName
- variant.outputs.all {//设置输出apk的文件名
- if (name.equals('dev')){
- outputFileName = "app-debug-${variant.versionName}.apk"
- }else if (name.equals('prod')) {
- outputFileName = "app-prod-${variant.versionName}.apk"
- }
- }
- }
- }
-
- }
1)defaultConfig{}中的 ndk.abiFilters 属性,配置ndk链接库支持的cpu架构
2)externalNativeBuild{}中配置cmake
- externalNativeBuild {
- cmake {
- path "CMakeLists.txt"
- cppFlags '-std=c++11'
- arguments '-DANDROID_PLATFORM=android-21',
- '-DANDROID_TOOLCHAIN=clang',
- '-DANDROID_STL=c++_shared'
- }
- }
3)sourceSets中配置动态链接库的目录
- sourceSets {
- main {
- jniLibs.srcDirs = ['src/main/jniLibs']
- }
- }
4)android{}中的ndkVersion 属性,配置ndk版本号
在要发布的module的bulid.gradle中添加配置
- apply plugin: 'maven'
- //...其它配置
- //将源码打包 为了保证引入的aar 包可以查看源码
- task androidSourcesJar(type: Jar) {
- classifier = 'sources'
- from android.sourceSets.main.java.srcDirs
- }
- //包含文档和源码的aar
- artifacts {
- archives androidSourcesJar
- }
- //上传到Maven仓库的task
- uploadArchives {
- repositories {
- mavenDeployer {
- //指定maven仓库url
- repository(url: "http://10.10.25.223:8081/repository/maven-releases/") {
- //nexus登录默认用户名和密码
- authentication(userName: "admin", password: "123456")
- }
- pom.groupId = "com.test.camera"// 唯一标识(通常为模块包名,也可以任意)
- pom.artifactId = "CameraMix" // 项目名称(通常为类库模块名称,也可以任意)
- pom.version = "1.0.0" // 版本号
- }
- }
- }
- compileOptions {//编译选项
- sourceCompatibility JavaVersion.VERSION_1_8
- targetCompatibility JavaVersion.VERSION_1_8
- }
- lintOptions {
- checkReleaseBuilds false
- abortOnError false
- }
- packagingOptions {
- pickFirst 'lib/arm64-v8a/*.so'//解决重复引用库文件的问题
- exclude 'META-INF/spring.schemas'//排除不需要打包的文件
- }