• 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,可点击左边的开始按钮执行;

    1. task hello {
    2. return 'Hello world!'
    3. }

    也可以指明task依赖关系:

    1. task dep(dependsOn: hello) {
    2. println "I'm Gradle"
    3. }

    执行结果如下

    循环执行任务

    1. task count {
    2. doFirst {//doFirst,doLast是内置函数
    3. 4.times { print "$it " }
    4. }
    5. }

     创建动态任务

    1. 4.times { counter ->
    2. task "task$counter" {
    3. doFirst{
    4. println "I'm task number $counter"
    5. }
    6. }
    7. }
    8. task tout(dependsOn: task2){//打印出I'm task number 2
    9. print "finish"
    10. }

    增加依赖:为已存在的任务增加行为

    1. 4.times { counter ->
    2. task "task$counter" {
    3. doFirst{
    4. println "I'm task number $counter"
    5. }
    6. }
    7. }
    8. task2.dependsOn task1, task3
    9. task tout(dependsOn: task2){//依次打印出I'm task number 1,3,2
    10. print "finish"
    11. }

    以属性的方式访问任务,对于插件提供的内置任务。这尤其方便(例如:complie)

    1. task hello{
    2. println("helloKitty")
    3. }
    4. hello.doFirst{
    5. println "task name is $hello.name"
    6. }

    为任务增加自定义属性

    1. task myTask {
    2. ext.myProperty = "myValue"
    3. }
    4. task hello{
    5. print myTask.myProperty //打印出myValue
    6. }

    Gradle 允许在脚本中定义多个默认任务。在多项目构建中,每个子项目都可以指定单独的默认任务。如果子项目未进行指定将会调用父项目指定的的默认任务。

    1. defaultTasks 'cleanD', 'runD'
    2. task cleanD {
    3. println 'Default Cleaning!'
    4. }
    5. task runD {
    6. println 'Default Running!'
    7. }
    8. task other {//运行会先执行前两个任务
    9. println "I'm not a default task!"
    10. }

    配置阶段后,Gradle 会了解所有要执行的任务 Gradle 提供了一个钩子来捕获这些信息。例如可以检查已经执行的任务中有没有被释放。借由此,你可以为一些变量赋予不同的值。

    在下面的例子中,为 distribution 和 release 任务赋予了不同的 version 值。

    1. gradle.taskGraph.whenReady {taskGraph ->
    2. if (taskGraph.hasTask(releaseTask)) {
    3. version = '1.0'
    4. } else {
    5. version = '1.0-SNAPSHOT'
    6. }
    7. }

    3.依赖管理

    android中的bulid.gradle有两种,一种是整个项目的,另一个是每个module中的。

    下面先看整个项目的gradle:分为两个部分,buildscript{}中是编译过程中的配置;allprojects{}是整个项目需要依赖的仓库

    1. buildscript {//编译过程配置
    2. ext {//自定义属性,可通过rootProject.ext.x来引用
    3. kotlin_version = '1.3.72'
    4. }
    5. repositories {//代码托管仓库
    6. maven { url 'https://maven.aliyun.com/nexus/content/repositories/google' }
    7. maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
    8. maven { url 'http://maven.aliyun.com/nexus/content/repositories/jcenter' }
    9. google()
    10. jcenter()
    11. }
    12. dependencies {
    13. classpath 'com.android.tools.build:gradle:4.2.2'
    14. classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.61"
    15. classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5'
    16. // NOTE: Do not place your application dependencies here; they belong
    17. // in the individual module build.gradle files
    18. }
    19. }
    20. allprojects {
    21. //配置整个项目依赖的仓库
    22. repositories {
    23. maven { url 'https://maven.aliyun.com/nexus/content/repositories/google' }
    24. maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
    25. maven { url 'http://maven.aliyun.com/nexus/content/repositories/jcenter' }
    26. google()
    27. mavenCentral()
    28. maven { url 'https://www.jitpack.io' }
    29. }
    30. }

    ext{}中是自定义的属性;

            也可以在gradle.propertities中定义属性,如下代码定义了android编译版本,用于统一不同module的android版本

    1. VERSION_TARGET_SDK=30
    2. VERSION_COMPILE=30
    3. VERSION_BUILD_TOOL=30.0.3
    4. #图标
    5. PROD_APP_ICON=@mipmap/ic_launcher

    可通过如下方式引用

    compileSdkVersion VERSION_COMPILE.toInteger()
    buildToolsVersion VERSION_BUILD_TOOL

    然后看每个module中的bulid.gradle:

    首先是插件的声明,根据plugin可以判断这个module是可运行的app或者是library

    1. apply plugin: 'com.android.application'//通常在最顶部写
    2. plugins {//应用插件的另一种写法
    3. id 'com.android.library'
    4. }

    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、依赖远程库

    1. implementation fileTree(dir: 'libs', include: ['*.aar', '*.jar'], exclude: [])//依赖libs目录下的所有相关类型文件
    2. implementation project(path: ':ZXingForAndroid')//依赖本地文件
    3. implementation files('libs/Msc.jar')//依赖本地库
    4. //远程依赖库
    5. 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块

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

    1. minSdkVersion 21
    2. targetSdkVersion 30
    3. versionCode 2
    4. versionName "1.0.1"
    5. testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    6. ndk.abiFilters 'arm64-v8a'//支持的ndk链接库类型
    7. multiDexEnabled true //是否支持多dex
    8. externalNativeBuild {}//ndk编译设置

    buildTypes块

    用于构建不同的apk

    1. buildTypes {
    2. release {
    3. minifyEnabled true //开启混淆
    4. shrinkResources true //移除未使用资源
    5. proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    6. signingConfig signingConfigs.release //设置使用的签名
    7. }
    8. debug {
    9. debuggable true
    10. }
    11. custom {
    12. minifyEnabled false
    13. }
    14. }

    如上代码,可生成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块

    1. signingConfigs {
    2. debug {//可以在bulidTypes下的signingConfig中引用
    3. storeFile file('release.keystore')//签名文件路径
    4. storePassword 'xxxxxx'
    5. keyAlias 'androidreleasekey'
    6. keyPassword '123456'
    7. }
    8. release {
    9. storeFile file('release.keystore')
    10. storePassword 'xxxxxx'
    11. keyAlias 'androidreleasekey'
    12. keyPassword '123456'
    13. }
    14. }

    productFlavors 多渠道打包配置

    1. flavorDimensions 'default' // 定义产品维度,所有渠道都要指定维度
    2. productFlavors {
    3. dev {// 每个环境包名不同
    4. applicationId DEVELOP_PACKAGE_NAME as String
    5. dimension "default"
    6. // 自定义buildConfig.java中的变量供代码中使用
    7. buildConfigField "String", "MODE", '"develop"'
    8. }
    9. prod {
    10. applicationId PROD_PACKAGE_NAME as String
    11. dimension "default"
    12. buildConfigField "String", "MODE", '"production"'
    13. }
    14. productFlavors.all { flavor ->
    15. flavor.manifestPlaceholders += [CHANNEL_VALUE: name]
    16. if (name.equals('dev')) { //开发环境
    17. flavor.manifestPlaceholders += [APP_NAME: DEV_APP_NAME as String]
    18. flavor.manifestPlaceholders += [APP_ICON: DEV_APP_ICON as String]
    19. flavor.manifestPlaceholders += ["apk.applicationId" : DEV_PACKAGE_NAME as String]
    20. } else if (name.equals('prod')) { //生产环境
    21. flavor.manifestPlaceholders += [APP_NAME: PROD_APP_NAME as String]
    22. flavor.manifestPlaceholders += [APP_ICON: PROD_APP_ICON as String]
    23. flavor.manifestPlaceholders += ["apk.applicationId" : PROD_PACKAGE_NAME as String]
    24. }
    25. //打包配置
    26. applicationVariants.all { variant ->
    27. def name = variant.flavorName
    28. variant.outputs.all {//设置输出apk的文件名
    29. if (name.equals('dev')){
    30. outputFileName = "app-debug-${variant.versionName}.apk"
    31. }else if (name.equals('prod')) {
    32. outputFileName = "app-prod-${variant.versionName}.apk"
    33. }
    34. }
    35. }
    36. }
    37. }

    NDK配置

    1)defaultConfig{}中的 ndk.abiFilters 属性,配置ndk链接库支持的cpu架构

    2)externalNativeBuild{}中配置cmake

    1. externalNativeBuild {
    2. cmake {
    3. path "CMakeLists.txt"
    4. cppFlags '-std=c++11'
    5. arguments '-DANDROID_PLATFORM=android-21',
    6. '-DANDROID_TOOLCHAIN=clang',
    7. '-DANDROID_STL=c++_shared'
    8. }
    9. }

    3)sourceSets中配置动态链接库的目录

    1. sourceSets {
    2. main {
    3. jniLibs.srcDirs = ['src/main/jniLibs']
    4. }
    5. }

    4)android{}中的ndkVersion 属性,配置ndk版本号

    发布到局域网私有仓库

    在要发布的module的bulid.gradle中添加配置

    1. apply plugin: 'maven'
    2. //...其它配置
    3. //将源码打包 为了保证引入的aar 包可以查看源码
    4. task androidSourcesJar(type: Jar) {
    5. classifier = 'sources'
    6. from android.sourceSets.main.java.srcDirs
    7. }
    8. //包含文档和源码的aar
    9. artifacts {
    10. archives androidSourcesJar
    11. }
    12. //上传到Maven仓库的task
    13. uploadArchives {
    14. repositories {
    15. mavenDeployer {
    16. //指定maven仓库url
    17. repository(url: "http://10.10.25.223:8081/repository/maven-releases/") {
    18. //nexus登录默认用户名和密码
    19. authentication(userName: "admin", password: "123456")
    20. }
    21. pom.groupId = "com.test.camera"// 唯一标识(通常为模块包名,也可以任意)
    22. pom.artifactId = "CameraMix" // 项目名称(通常为类库模块名称,也可以任意)
    23. pom.version = "1.0.0" // 版本号
    24. }
    25. }
    26. }

    其它配置

    1. compileOptions {//编译选项
    2. sourceCompatibility JavaVersion.VERSION_1_8
    3. targetCompatibility JavaVersion.VERSION_1_8
    4. }
    1. lintOptions {
    2. checkReleaseBuilds false
    3. abortOnError false
    4. }
    1. packagingOptions {
    2. pickFirst 'lib/arm64-v8a/*.so'//解决重复引用库文件的问题
    3. exclude 'META-INF/spring.schemas'//排除不需要打包的文件
    4. }

  • 相关阅读:
    如何实现该图的遍历算法
    债券数据集:绿色债券数据集、历时新发、发行债券、DCM定价估值四大指标数据
    leetcode148. 排序链表
    【云原生之kubernetes实战】在k8s环境下部署RSS阅读器Selfoss
    java毕业设计远程教育系统Mybatis+系统+数据库+调试部署
    求职应聘找工作的同学,在线测评怎么过?
    中国地图坐标系转换详解:从WGS-84到GCJ-02再到BD-09
    GPIO子系统编写LED驱动
    【OS】进程通信
    H5自定义属性
  • 原文地址:https://blog.csdn.net/wlxyhy/article/details/126104731