Android中Gradle的使用

1.Gradle简介

Gradle是一个基于JVM的构建工具,其 build 脚本使用 groovy dsl 编写。

Gradle 的核心在于基于 Groovy的丰富而可扩展的域描述语言(DSL)。 Groovy 通过声明性的语言元素将基于声明的构建推向下层,你可以按你想要的方式进行组合。

2.Project和task

projects 和 tasks是 Gradle 中最重要的两个概念。

任何一个 Gradle 构建都是由一个或多个 projects 组成。每个 project 包括许多可构建组成部分。 每个 project 都由多个 tasks 组成。每个 task 都代表了构建执行过程中的一个原子性操作。如编译,打包,生成 javadoc,发布到某个仓库等操作。

Project属性

名称类型默认值
projectProjectProject实例
nameString项目目录的名称。
pathString项目的绝对路径。
descriptionString项目的描述。
projectDirFile包含生成脚本的目录。
buildDirFileprojectDir/build
groupObject通常是application的label
versionObject未指定
antAntBuilderAntBuilder实例

task

一个简单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'
    }
}

3.依赖管理

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.instantappAndroid 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:只用于测试。

4. Android中常用的gradle配置

defaultConfig块

用于默认配置,常用属性包括

        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编译设置
        

此外,可以自定义BuildConfig属性

    defaultConfig {
        buildConfigField 'String','API_SERVER_URL','"http://url/"'
    }

buildTypes块

用于构建不同的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运行效率
proguardFileProGuard混淆所使用的ProGuard配置文件
proguardFiles同时配置多个ProGuard配置文件
signingConfig配置签名信息
multiDexEnabled是否自动拆分多个Dex

signingConfig块

    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'
        }
    }

productFlavors 多渠道打包配置

    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"
                    }
                }
            }
        }

    }

SourceSets配置

可以指定编译哪些源文件

    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']
            resources.srcDirs = ['src']
            aidl.srcDirs = ['src']
            renderscript.srcDirs = ['src']
            res.srcDirs = ['res']
            assets.srcDirs = ['assets']
            jniLibs.srcDirs = ['src/main/jniLibs']
            java {
                exclude '/test/**'  // 不想包含文件的路径
            }
        }
    }

可以加逻辑判断,比如通过flag判断使用哪个manifest

    sourceSets {
        main {
            if (DEBUG) {
                manifest.srcFile 'src/main/debug/AndroidManifest.xml'
            } else {
                manifest.srcFile 'src/main/AndroidManifest.xml'
            }
        }
    }

NDK配置

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'//排除不需要打包的文件
    }

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值