Android 打包之 Gradle

2023-08-07  本文已影响0人  斋芳女

一、什么是Gradle

Gradle 是目前非常流行的一个项目构建工具,它不局限于前端或者后端,利用基于jvm的动态语言Groovy,语法灵活,配置简单,方便扩展。

Tips:Gradle是Gradle,AndroidGradle是AndroidGradle,不能混为一谈,可以理解Google为了在AS上使用Gradle来构建Project,自己根据Android项目拓展了Gradle,开发出了AndroidGradle插件,结合了AndroidTools等工具,方便对Android项目进行构建。

详解:https://www.cwiki.us/display/GradleZH/What+is+Gradle

二、Android中的Gradle

Android中的Gradle可以称为gradle插件,要想编译安卓项目,不仅要下载gradle,也要下载Android对应的gradle插件,插件中包含了Gradle和Android一些工具的结合,目的是为了构建Android Project。

贴一张Gradle插件版本号和Gralde版本的对应版本

https://developer.android.google.cn/studio/releases/gradle-plugin

gradle/wrapper/gradle-wrapper.properties 中配置gradle版本,build文件中配置gradle插件版本

classpath 'com.android.tools.build:gradle:3.3.2' ----插件版本

distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip ---- gradle版本


1.Android-sync project with gradle file发生了什么?

详解来自:https://developer.android.com/studio/build/dependencies?hl=zh-cn

首先,看一下安卓整个项目结构:

挨个说:

顶层build.gradle文件:

顶层 build.gradle 文件位于项目的根目录下,用于定义适用于项目中所有模块的依赖项。默认情况下,顶层 build 文件使用 plugins 代码块定义项目中所有模块共用的 Gradle 依赖项。此外,顶层 build 文件还包含用于清理 build 目录的代码。以下代码示例说明了创建新项目后可在顶层 build.gradle 文件中找到的默认设置和 DSL 元素。

其中配置项解析:

project/build.gradle project/build.gradle

settings.gradle文件:

主要功能:配置要构建几个模块

settings.gradle

模块的gradle文件配置,module/build.gradle

module/build.gradle module/build.gradle

小点补充:

Gradle编译后,只会停留到加载各种依赖资源和初步编译代码阶段

常见闭包参数详解:

android DSL

–领域特定语言(domain-specific languages,简称DSL)

defaultConfig{}默认配置,是ProductFlavor类型。它共享给其他ProductFlavor使用

sourceSets{ }源文件目录设置,是AndroidSourceSet类型。

buildTypes{ } BuildType类型

signingConfigs{ }签名配置,SigningConfig类型

productFlavors{ }产品风格配置,ProductFlavor类型

testOptions{ }测试配置,TestOptions类型

aaptOptions{ } aapt配置,AaptOptions类型

lintOptions{ } lint配置,LintOptions类型

dexOptions{ } dex配置,DexOptions类型

compileOptions{ }编译配置,CompileOptions类型

packagingOptions{ } PackagingOptions类型

jacoco{ } JacocoExtension类型。用于设定jacoco版本

splits{ } Splits类型。

android{… }配置了用于android构建的所有参数。这是Android DSL的入口。

2.那么,打包过程是怎样的?

内容整理来自:https://docs.gradle.org/current/userguide/build_lifecycle.html

首先gradle构建生命周期:

初始化阶段(Initialization)

配置阶段(Configuration)

执行阶段(Execution)

初始化阶段:

Gradle支持单工程或者多工程构建,初始化阶段的任务是确定有多少工程需要构建,创建整个项目的层次结构,并且为每一个项目创建一个Project实例对象。

如果是多工程构建,一般都会在根工程目录下声明一个settings.gradle脚本,在脚本中include所有需要参与构建的子工程,通过解析settings.gradle脚本,读取include信息,确定有多少个Project需要构建。

配置阶段:

配置阶段的主要任务是生成整个构建过程的有向无环图

确定了所有需要参与构建的工程后,通过读取解析各个工程对应的build.gradle脚本,构造Task任务,并根据Task的依赖关系,生成一个基于Task的有向无环图TaskExecutionGraph

执行阶段:

通过读取配置阶段生成有向无环图TaskExecutionGraph,按顺序依此执行各个Task,像流水线一样,一步一步构建整个工程,这也是构建过程中最耗时的阶段。

图片来自网络

///项目中具体log图片待补充

3.接着,主要task有哪些?

先贴一张打包大致流程图,图片来自网络:

图片来自网络

aapt-打包res资源文件,生成R.java、resources.arsc和res文件(二进制&非二进制如res/raw和pic保持原样)

AIDL-Android借口定义语言,Android提供的IPC(Inter Process Communication,进程间通信)的一种独特实现。这个阶段处理.aidl文件,生成对应的Java接口文件。

Java Compiler-通过Java Compiler编译R.java、Java接口文件、Java源文件,生成.class文件。

dex-通过dex命令,将.class文件和第三方库中的.class文件处理生成class.dex。

apkbuilder-将class.dex、resources.arsc、res文件夹(res/raw资源被原封不动的打包进APK之外,其他资源都会被编译或者处理)、OtherResouces(assets文件夹)、AndroidManifest.xml打包进apk文件。

Jarsigner-对上面的apk进行debug或release签名

aipalign-将签名后的pak进行对其处理

图片来自网络

Task序列:

1.1

分段来说:

1.2

1-4: 

preDebugBuild task主要是得到compile 和 runtime的依赖包并对其做一些版本号,依赖等的校验工作。compileDebugAidl,处理记录aidl和java相关的信息。generateDebugBuildConfig 生成BuildConfig文件

1.3

这一部分task主要作用是整理资源合并,分辨率资源文件整理等

其中generateDebugResValues比较重要,它的作用是,配置在gradle中的一些参数,自动整理到res目录中供代码调用,比如:

1.4

如果你有该配置的话,执行./gradlew generateDebugResValues

则会生成以下代码:

1.5

可以方便的在代码中调用

1.6

这一部分task主要任务是一些加jar文件以及载处理依赖关系。其中

compileDebugJavaWithJavac尤为重要:

./gradlew compileDebugJavaWithJavac

一共做了比较重要的几件事:

已知内容(依赖此task之前task)

依赖工程的jar文件

javaPreCompileDebug 任务的输出json文件

项目的java文件

项目生成的R文件,buildconfig文件,aidl等一系列重要文件

做一下输出:

annotationProcessor 生成的java文件

生成的classes文件

下面是transform

1.7

transform vs task

TransformManager.java

1.8

addTransform 方法在执行过程中,会将 Transform 包装成一个 AndroidTask 对象,所以transfrom最终会被转换成一个task

./gradlew transformClassesWithDexBuilderForDebug

根据依赖库的jar文件和class文件,生成dex文件。

值得注意的是,既然是生成dex文件,但是为甚么输出后有后缀为jar文件,实际情况是,jar后缀文件解压后,是dex。了解一下就行。

1.9

最后就是打包签名输出apk

4.所以我们利用task可以做些什么?

Task一些关键字语法:

http://doc.yonyoucloud.com/doc/wiki/project/GradleUserGuide-Wiki/more_about_tasks/README.html

首先,命令行 gradle task --all 可以看到项目中所有的task

那么我们如何方便看到task之间的依赖关系呢,这里有个插件 task-tree可以辅助我们打印task之间的关系

还有一个 gradle-visteg有兴趣的小伙伴可以看看。

首先纠正一个配置阶段对task的定义的理解:

1.10

在配置阶段,会输出那些内容呢?

事实上,会输出,hello,helloworld的内容,那么问题来了,不是不会执行task吗?为什么会输出呢?

这个跟方法块理解不一样,配置阶段是会走一遍task的配置,但是执行是从doFirst开始的,只有在执行task的时候,才会从doFirst入口开始执行。doLast结束。

不论执行什么task,都会完成一遍配置,哪怕clean一下缓存。

afterEvaluate

x0;这个关键字是指配置阶段结束后,之所以所有hook内容放在该关键字处,是因为只有在这里才能拿到所有task的信息,然后进行操作。

1.11

gradle.taskGraph.whenReady

x0;这里输出的是当前任务构建需要依赖的所有的task的集合

1.12

所以,在配置阶段结束后,我们可以做任何想做的操作,插入自己的task

列举几个项目中的例子:图片待补充。。。

文章中诸多内容借鉴了其他文章,犹豫时间久远未记录原文档地址,希望我们每个技术人都可以向原创致敬。谢谢观看。

上一篇下一篇

猜你喜欢

热点阅读