Android Gradle的入门

一前言
现在的Android应用都是采用Android Studio来开发的,AS默认是采用Gradle作为构建工具的。通常开发者可以不需要理解任何Gradle的脚本配置,就可以开发出一个APP。但是,当你想做一些更智能的操作时,比如修改打包后的输出目录、提高打包速度等等,就必须对Gradle有比较深入的了解。Gradle脚本是基于Groovy语言来编译执行的,在这之前最好要对Groovy语言有所了解。
二:AS 目录下的gradle
1.Android 视图下我们可以清晰看到gradle配置
image.png
(1)gradle-wrapper.properties(Gradle Version)为gradle的版本配置信息。

所需的 Gradle 版本

distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip

这个与Project下的build.gradle对应的插件版本

buildscript {
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath "com.android.tools.build:gradle:4.1.0"//对应着Gradle版本号

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

image.png
(2)gradle.properties(Project Properties)是与当前项目相关的一个配置文件,主要包括一些当前项目中需要用到的键值对信息。


org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app"s APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
# Automatically convert third-party libraries to use AndroidX
android.enableJetifier=true

#SDK下build工具的版本号
buildToolsVer=29.0.0

#app内部版本号 
verCode=16

#app外部版本号
verName=1.2

(3)settings.gradle(Project Settings)为工程的设置文件,告诉gradle当前工程的组成部分,比如有多少个子工程或者模块

include ':module_red'
include ':module_goods'
include ':module_free'
include ':module_me'
include ':module_login'
include ':common_base'
include ':app'
rootProject.name = "KuaiLaiTao"

(4)build.gradle(Project)为root project(这里我们称项目的根目录为root project)下的gradle配置文件,该配置文件一般用来做一些全局性的配置。

apply from:"config.gradle"//应用一个config.gradle的配置文件
//全局配置构建工具的classpath和远程仓库路径,这里一般配置为gradle的,因为项目在构建过程中需要使用gradle去执行,当然如果你使用到了一些额外的插件,比如注解处理器,也可以放在这里。
buildscript {
    repositories {//这里是gradle脚本执行所需依赖,分别是对应的maven库和插件
        google()//从Android Studio3.0后新增了google()配置,可以引用google上的开源项目
        jcenter()//是一个类似于github的代码托管仓库,声明了jcenter()配置,可以轻松引用 jcenter上的开源项目
    }
    dependencies {
        classpath "com.android.tools.build:gradle:3.5.4"//此处是android的插件gradle,gradle是一个强大的项目构建工具
        classpath 'com.jakewharton:butterknife-gradle-plugin:10.2.0'//butterKnife组件化第一步

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {//这里是项目本身需要的依赖,比如项目所需的maven库
        google()
        jcenter()
        maven { url "http://mvn.gt.igexin.com/nexus/content/repositories/releases/" }//个推的Maven库
    }
}
// 运行gradle clean时,执行此处定义的task任务。
// 该任务继承自Delete,删除根目录中的build目录。
// 相当于执行Delete.delete(rootProject.buildDir)。
// gradle使用groovy语言,调用method时可以不用加()。
task clean(type: Delete) {
    delete rootProject.buildDir
}

(5)build.gradle(Module)为module下的gradle配置,该配置只对该module生效。

//第一行代码应用了Android 程序的gradle插件,作为Android 的应用程序,这一步是必须的,因为plugin中提供了Android 编译、测试、打包等等的所有task。
plugins {
    id 'com.android.application'
}
//android:这是编译文件中最大的代码块,关于android 的所有特殊配置都在这里,这就是又我们前面的声明的 plugin 提供的。
android {
    compileSdkVersion 30//设置编译时用的Android版本
    buildToolsVersion "30.0.2"

    defaultConfig {
        applicationId "com.ruan.mygitignore"//项目包名
        minSdkVersion 16//项目最低兼容的版本
        targetSdkVersion 30//项目的目标版本
        versionCode 1//版本号
        versionName "1.0"//版本名称

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"//表明要使用AndroidJUnitRunner进行单元测试
    }
    /**
     * 新增debug和release签名配置属性*/
    signingConfigs {//自动化打包配置,签名
        debug {//测试环境
            keyAlias 'androiddebugkey'
            keyPassword 'android'
            storePassword 'android'
            storeFile file('C:/Users/Administrator/.android/debug.keystore')
        }
        release{//线上环境
            keyAlias 'rocky'
            keyPassword 'rockyruan'
            storePassword 'rockyruan'
            storeFile file('F:/soudaoProject/MyGitignore/rocky_ruan.jks')
        }
    }


    buildTypes {// 生产/测试环境配置
        release {// 生产环境
            buildConfigField("boolean", "LOG_DEBUG", "false")//配置Log日志
            buildConfigField("String", "URL_PERFIX", "\"https://release.cn/\"")// 配置URL前缀
            minifyEnabled false//是否对代码进行混淆
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'//指定混淆的规则文件
            signingConfig signingConfigs.release//设置签名信息
            pseudoLocalesEnabled false//是否在APK中生成伪语言环境,帮助国际化的东西,一般使用的不多
            zipAlignEnabled true//是否对APK包执行ZIP对齐优化,减小zip体积,增加运行效率
            applicationIdSuffix 'test'//在applicationId 中添加了一个后缀,一般使用的不多
            versionNameSuffix 'test'//在applicationId 中添加了一个后缀,一般使用的不多
        }
        debug {// 测试环境
            buildConfigField("boolean", "LOG_DEBUG", "true")//配置Log日志
            buildConfigField("String", "URL_PERFIX", "\"https://test.com/\"")// 配置URL前缀
            minifyEnabled false//是否对代码进行混淆
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'//指定混淆的规则文件
            signingConfig signingConfigs.debug//设置签名信息
            debuggable false//是否支持断点调试
            jniDebuggable false//是否可以调试NDK代码
            renderscriptDebuggable false//是否开启渲染脚本就是一些c写的渲染方法
            zipAlignEnabled true//是否对APK包执行ZIP对齐优化,减小zip体积,增加运行效率
            pseudoLocalesEnabled false//是否在APK中生成伪语言环境,帮助国际化的东西,一般使用的不多
            applicationIdSuffix 'test'//在applicationId 中添加了一个后缀,一般使用的不多
            versionNameSuffix 'test'//在applicationId 中添加了一个后缀,一般使用的不多
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {

    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.android.material:material:1.2.1'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
    implementation 'androidx.recyclerview:recyclerview:1.1.0'
    implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"

    implementation 'com.scwang.smart:refresh-layout-kernel:2.0.3'      //核心必须依赖
    implementation 'com.scwang.smart:refresh-header-classics:2.0.3'//经典刷新头
    implementation 'com.scwang.smart:refresh-footer-classics:2.0.3'    //经典加载

    implementation 'com.google.android:flexbox:2.0.1'
    implementation 'com.squareup.okhttp3:okhttp:3.8.0'
    implementation 'com.squareup.okio:okio:1.12.0'
    implementation 'com.google.code.gson:gson:2.6.2'
    //rxjava2
    implementation 'io.reactivex.rxjava2:rxjava:2.2.20'
    implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
    //RxLifecycle
    implementation 'com.trello.rxlifecycle3:rxlifecycle:3.1.0'
    implementation 'com.trello.rxlifecycle3:rxlifecycle-components:3.1.0'

    //AutoDispose
    implementation 'com.uber.autodispose:autodispose:0.6.1'
    implementation 'com.uber.autodispose:autodispose-android-archcomponents:0.6.1'

    implementation 'com.squareup.picasso:picasso:2.5.2'

    implementation 'com.github.bumptech.glide:glide:4.11.0'
    annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
    implementation "com.github.bumptech.glide:okhttp3-integration:4.11.0"

    implementation "androidx.work:work-runtime:2.5.0"
}

defaultConfig就是程序的默认配置,注意,如果在AndroidMainfest.xml里面定义了与这里相同的属性,会以这里的为主。
这里最有必要要说明的是applicationId的选项:在我们曾经定义的AndroidManifest.xml中,那里定义的包名有两个用途:一个是作为程序的唯一识别ID,防止在同一手机装两个一样的程序;另一个就是作为我们R资源类的包名。在以前我们修改这个ID会导致所有用引用R资源类的地方都要修改。但是现在我们如果修改applicationId只会修改当前程序的ID,而不会去修改源码中资源文件的引用。
buildTypes:定义了编译类型,针对每个类型我们可以有不同的编译配置,不同的编译配置对应的有不同的编译命令。默认的有debug、release 的类型。
dependencies:是属于gradle 的依赖配置。它定义了当前项目需要依赖的其他库。
三:Gradle 构建生命周期
在解析 Gradle 的编译过程之前我们需要理解在 Gradle 中非常重要的两个对象。Project和Task
每个项目的编译至少有一个 Project,一个 build.gradle就代表一个project,每个project里面包含了多个task,task 里面又包含很多action,action是一个代码块,里面包含了需要被执行的代码
在编译过程中, Gradle 会根据 build 相关文件,聚合所有的project和task,执行task 中的 action。因为 build.gradle文件中的task非常多,先执行哪个后执行那个需要一种逻辑来保证。这种逻辑就是依赖逻辑,几乎所有的Task 都需要依赖其他 task 来执行,没有被依赖的task 会首先被执行。所以到最后所有的 Task 会构成一个 有向无环图(DAG Directed Acyclic Graph)的数据结构。
无论什么时候执行Gradle构建,都会运行3个不同的生命周期阶段:初始化、配置、执行。

  • 初始化(Initialization):Gradle为每个项目创建一个Project实例,在多项目构建中,Gradle会找出哪些项目依赖需要参与到构建中。
  • 配置(Configuration):执行所有项目的构建脚本,也就是执行每个项目的build.gradle文件。这里需要注意的是,task里的配置代码也会在这个阶段执行。
  • 执行(Execution):Gradle按照依赖顺序依次执行task。

执行顺序:

setting 开始配置
setting 配置完成

> Configure project :
根build.gradle 开始配置
根build.gradle 配置完成

> Configure project :app
app build.gradle 开始配置
app build.gradle 配置完成

所有模块都已配置完成
image.png
assembleDebug 会打出debug包
assembleRelease 会打出release包
assemble 会同时打出debug包和release包
1.android Task:
image.png
image.png
image.png
可以获取的是debug下的签名文件和Release下签名文件的MD5值,SHA1值,SHA256值
2.build Task:
image.png
构建依赖的编译的执行assemble
3.build setup
image.png
4.clean up
image.png
5.help
image.png
6.install
在设备上安装一个Debug/Release版本
image.png
7.other
image.png
点击assembleRelease 打包生成的apk在app下build-outputs-relase包下
显示是一个未被签名的正式包
image.png
但是如果app下build.gradle配置

 buildTypes {
        /*正式版本*/
        release {
            minifyEnabled false//代码混淆
            /*代码混淆规则*/
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            //debuggable  false //这个构建类型是否应该生成可调式的apk
            signingConfig signingConfigs.release //设置默认调用上方我们刚配置的signingConfigs.release

        }
        
        }

signingConfig signingConfigs.release调用上面配置好的签名文件
image.png
还可以命令行使用 在Terminal 下使用gradlew assembleRelease
image.png

8.verification
build task依赖于check任务,但是不依赖于connectedCheck或者deviceCheck,执行check任务时Lint会产生一些相关文件,可以在
image.png

END:知识需要不断的汲取


Rocky_ruan
57 声望5 粉丝

不积跬步,无以至千里